# Web 项目发布构建 Action [![GitHub](https://img.shields.io/badge/github-actions-blue.svg)](https://github.com/features/actions) 自动化 Web 项目发布流程的 GitHub Action,专注于版本管理和发布核心功能,智能处理各种版本格式。 ## 功能特性 - 🚀 **自动化发布**: 支持任意发布命令进行版本管理和发布 - 🌍 **环境变量支持**: 支持传递任意数量的环境变量给发布命令 - 📦 **智能版本处理**: 自动获取版本号,确保输出格式一致(无 `v` 前缀) - 📊 **状态监控**: 实时监控发布状态,支持成功/失败状态输出和退出码 - 🔧 **简洁配置**: 最小化配置,专注于发布核心功能 - ✅ **灵活使用**: 可配置发布命令,适应不同项目需求 - 🛡️ **错误控制**: 可配置发布失败时的行为(中断或继续) ## 快速开始 ### 基础用法 ```yaml - name: 发布Web项目 uses: actions/xgj/release-web@main env: GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} ``` ### 使用环境变量 ```yaml - name: 发布Web项目 uses: actions/xgj/release-web@main env: # 🌍 可以传递任意数量的环境变量给发布命令 GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} APP_ENV: production SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_DSN: ${{ vars.SENTRY_DSN }} SENTRY_VITE: true BUILD_NUMBER: ${{ github.run_number }} CUSTOM_CONFIG: "your-value" FEATURE_FLAG: ${{ github.ref == 'refs/heads/main' }} # ... 更多任意环境变量 ``` ### 完整示例 ```yaml - name: 发布Web项目 uses: actions/xgj/release-web@main with: release-command: "npm run release -- --release -V" env: GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} APP_ENV: "production" SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_DSN: ${{ vars.SENTRY_DSN }} SENTRY_VITE: "true" ``` ### 自定义版本文件路径 ```yaml - name: 发布Web项目 uses: actions/xgj/release-web@main with: version-file: "./dist/version.txt" # 自定义版本文件位置 env: GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} ``` ### 版本格式处理 Action 自动处理各种版本格式,确保输出一致: ```yaml # 输入可能的格式: # - 版本文件: "v1.2.3" 或 "1.2.3" # - Git tag: "v1.2.3" 或 "1.2.3" # - package.json: "v1.2.3" 或 "1.2.3" # - 提交信息: "release: v1.2.3" 或 "release: 1.2.3" # 输出始终为: "v1.2.3" (统一添加 v 前缀) # 带横线版本: "v1-2-3" (保持 v 前缀) ``` ## 输入参数 | 参数名 | 描述 | 必需 | 默认值 | | ----------------- | ---------------------------- | ---- | --------------------------------- | | `release-command` | 发布命令 | ❌ | `npm run release -- --release -V` | | `node-debug` | 是否启用 Node.js 调试模式 | ❌ | `false` | | `version-file` | 自定义版本文件路径 | ❌ | `/tmp/last-version` | | `fail-on-error` | 发布失败时是否让 action 失败 | ❌ | `true` | ## 环境变量支持 Action 支持通过 `env` 传递**任意数量**的环境变量给发布命令,这些环境变量会自动传递给 `npm run release` 或其他发布命令: ```yaml - uses: actions/xgj/release-web@main env: # 🌍 任意环境变量都会自动传递给发布命令 GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} APP_ENV: production SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_TOKEN }} CUSTOM_VAR: "your-value" BUILD_NUMBER: ${{ github.run_number }} FEATURE_FLAG: ${{ github.ref == 'refs/heads/main' }} # ... 更多任意变量 ``` ### 常用环境变量示例 | 环境变量名 | 描述 | 示例值 | | ------------------- | ---------------- | ----------------------------- | | `GITEA_TOKEN` | Gitea 访问令牌 | `${{ secrets.GITEA_TOKEN }}` | | `APP_ENV` | 应用环境 | `production` | | `SENTRY_AUTH_TOKEN` | Sentry 认证令牌 | `${{ secrets.SENTRY_TOKEN }}` | | `SENTRY_DSN` | Sentry DSN 配置 | `${{ vars.SENTRY_DSN }}` | | `SENTRY_VITE` | 是否启用 Sentry | `true` | | `NODE_DEBUG` | Node.js 调试模式 | `release-it:*` | | `BUILD_NUMBER` | 构建编号 | `${{ github.run_number }}` | ## 输出参数 | 参数名 | 描述 | | ------------------- | -------------------------------------- | | `version` | 发布的版本号(带 v 前缀) | | `version-with-dash` | 版本号(带 v 前缀,点号替换为横线) | | `release-status` | 发布命令执行状态 (`success`/`failure`) | | `exit-code` | 发布命令退出码(仅在失败时有值) | ## 使用场景 ### 1. 基础发布流程 适用于简单的 Web 项目发布: ```yaml steps: - uses: actions/checkout@v4 - name: 设置环境 uses: actions/xgj/setup-env@main with: docker-password: ${{ secrets.DOCKER_PASSWORD }} - name: 安装依赖 uses: actions/xgj/npm-install@main - name: 发布项目 uses: actions/xgj/release-web@main env: GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} ``` ### 2. 完整 CI/CD 流程 包含完整的构建、测试、发布流程: ```yaml steps: - uses: actions/checkout@v4 - name: 设置构建环境 uses: actions/xgj/setup-env@main with: docker-password: ${{ secrets.DOCKER_PASSWORD }} kube-config: ${{ secrets.KUBE_CONFIG }} - name: 安装依赖 uses: actions/xgj/npm-install@main with: package-manager: "pnpm" - name: 运行测试 run: npm run test - name: 发布构建 id: release uses: actions/xgj/release-web@main env: GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} APP_ENV: ${{ github.ref == 'refs/heads/main' && 'production' || 'staging' }} SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_DSN: ${{ vars.SENTRY_DSN }} SENTRY_VITE: "true" - name: 部署到Kubernetes run: | kubectl set image deployment/web-app web-app=docker-registry.bjxgj.com/${{ github.event.repository.name }}:${{ steps.release.outputs.version }} ``` ### 3. 多环境发布 支持不同环境的差异化配置: ```yaml strategy: matrix: environment: [staging, production] include: - environment: staging dockerfile: "./container/dev/Dockerfile" app-env: "staging" - environment: production dockerfile: "./container/prod/Dockerfile" app-env: "production" steps: - name: 发布到 ${{ matrix.environment }} uses: actions/xgj/release-web@main env: GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} APP_ENV: ${{ matrix.app_env }} ``` ### 4. 状态检查和错误处理 演示如何处理发布状态和错误: ```yaml steps: - uses: actions/checkout@v4 - name: 发布项目 id: release uses: actions/xgj/release-web@main with: fail-on-error: false # 发布失败时不中断 workflow env: GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} # 总是执行的清理步骤 - name: 清理临时文件 if: always() run: | echo "清理临时文件..." rm -rf temp/ dist/temp/ # 根据发布状态执行不同操作 - name: 处理发布结果 if: always() run: | echo "发布状态: ${{ steps.release.outputs.release-status }}" if [[ "${{ steps.release.outputs.release-status }}" == "success" ]]; then echo "✅ 发布成功,版本: ${{ steps.release.outputs.version }}" echo "开始部署流程..." else echo "❌ 发布失败,退出码: ${{ steps.release.outputs.exit-code }}" echo "发送失败通知..." # 这里可以添加通知逻辑 fi # 只在成功时执行的部署步骤 - name: 部署到生产环境 if: steps.release.outputs.release-status == 'success' run: | echo "部署版本 ${{ steps.release.outputs.version }} 到生产环境" kubectl set image deployment/app app=registry.com/app:${{ steps.release.outputs.version }} # 失败时的回退操作 - name: 回退操作 if: steps.release.outputs.release-status == 'failure' run: | echo "执行回退操作..." # 回退到上一个稳定版本的逻辑 ``` ### 5. 严格模式发布(默认行为) 适用于生产环境,发布失败时立即停止: ```yaml steps: - uses: actions/checkout@v4 - name: 发布项目 id: release uses: actions/xgj/release-web@main with: fail-on-error: true # 默认值,发布失败时中断 workflow env: GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} APP_ENV: "production" # 这个步骤只有在发布成功时才会执行 - name: 部署到生产环境 run: | echo "部署版本 ${{ steps.release.outputs.version }}" kubectl apply -f k8s/ ``` ## 工作流程 1. **发布构建**: 执行指定的发布命令进行版本发布 - 捕获命令执行状态和退出码 - 设置 `release-status` 输出(`success`/`failure`) - 失败时记录 `exit-code` 输出 2. **智能版本获取**: 只在发布成功时执行,通过多种方法自动获取版本号 - 优先从版本文件读取(`/tmp/last-version` 或自定义路径) - 回退到最新 git tag(保持原始格式) - 回退到 `package.json` 中的版本 - 最后尝试从提交信息解析(支持 `v1.2.3` 和 `1.2.3` 格式) - **所有方法都确保输出统一包含 `v` 前缀** 3. **发布总结**: 显示详细的发布状态信息 - 成功时:显示版本号和发布信息 - 失败时:显示错误状态和退出码 4. **状态检查**: 根据 `fail-on-error` 参数决定最终行为 - `true`(默认):发布失败时让 action 失败,中断 workflow - `false`:发布失败时继续完成,允许后续步骤执行 ## 依赖要求 ### 项目要求 - 包含 `package.json` 文件(用于版本回退) - 配置了发布工具(如 `release-it`) - 包含发布脚本(如 `npm run release`) - 推荐发布命令生成版本文件到 `/tmp/last-version`(或自定义路径) ### 环境依赖 - Node.js 环境 - npm/pnpm/yarn 包管理器 - 配置好的 Gitea 访问权限 ## 配置示例 ### release-it 配置 确保项目中有类似的 `.release-it.js` 配置: ```javascript module.exports = { hooks: { "before:release": [ "echo 'v${version}' > /tmp/last-version", "npm run build", ], }, git: { tagName: "v${version}", commitMessage: "chore: released version v${version} [no ci]", }, npm: { publish: false, }, }; ``` ### Docker 多阶段构建 推荐使用多阶段构建优化镜像大小: ```dockerfile # 构建阶段 FROM node:18-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci --only=production # 运行阶段 FROM node:18-alpine WORKDIR /app COPY --from=builder /app/node_modules ./node_modules COPY dist ./dist EXPOSE 3000 CMD ["npm", "start"] ``` ## 错误处理 ### 发布失败处理 Action 提供灵活的错误处理机制: **严格模式** (`fail-on-error: true` - 默认): - 发布命令失败时,action 立即失败并中断 workflow - 适用于生产环境,确保发布质量 **宽松模式** (`fail-on-error: false`): - 发布命令失败时,action 继续完成并返回状态信息 - 允许执行清理、通知等后续操作 - 可通过 `outputs.release-status` 检查发布结果 ### 常见错误情况 Action 会在以下情况报错: - 发布命令执行失败(返回非零退出码) - 无法获取版本信息(所有版本获取方法都失败) - 版本文件不存在且无其他版本源 ## 安全注意事项 - 🔒 始终通过 `secrets` 传递敏感令牌 - 🔍 定期检查和轮换访问令牌 - 📋 限制 Docker 仓库访问权限 - 🚫 避免在日志中暴露敏感信息 ## 故障排除 ### 常见问题 ### Q: 如何处理发布失败的情况? A: Action 提供了多种方式处理发布失败: 1. **检查发布状态**: ```yaml - name: 发布项目 id: release uses: actions/xgj/release-web@main - name: 检查发布结果 run: | if [[ "${{ steps.release.outputs.release-status }}" == "failure" ]]; then echo "发布失败,退出码: ${{ steps.release.outputs.exit-code }}" # 执行失败处理逻辑 fi ``` 2. **宽松模式处理**: ```yaml - name: 发布项目 uses: actions/xgj/release-web@main with: fail-on-error: false # 失败时不中断 - name: 清理操作 if: always() run: echo "总是执行清理" ``` ### Q: 如何获取发布失败的详细信息? A: 通过输出参数获取: - `release-status`: `success` 或 `failure` - `exit-code`: 失败时的命令退出码 - 检查 action 日志中的详细错误信息 ### Q: 无法获取版本信息 ```bash ❌ 错误: 无法获取版本信息 ``` A: Action 会按优先级尝试多种方法获取版本: 1. **版本文件** (推荐):确保发布命令创建版本文件 ```javascript // .release-it.js hooks: { 'before:release': ['echo \'v${version}\' > /tmp/last-version'] } ``` 2. **Git Tags**:确保发布过程创建了 git tag ```bash git tag v1.2.3 ``` 3. **package.json**:确保 package.json 包含有效的 version 字段 ```json { "version": "1.2.3" } ``` 4. **提交信息**:在提交信息中包含版本号 ```bash git commit -m "release: v1.2.3" # 或者 git commit -m "release: 1.2.3" ``` ### Q: Gitea Token 权限不足 A: 确保 token 具有以下权限: - Repository 写权限 - Releases 创建权限 ### 调试模式 启用详细调试信息: ```yaml - uses: actions/xgj/release-web@main with: node-debug: "true" env: GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} ``` ## 更新日志 查看 [Releases](https://github.com/your-org/actions/releases) 获取详细的更新历史。 ## 贡献 欢迎提交 Issue 和 Pull Request 来改进这个 Action! ## 许可证 MIT License - 详见 [LICENSE](../LICENSE) 文件。