diff --git a/release-web/.release-it.js b/release-web/.release-it.js new file mode 100644 index 0000000..b8dbb4e --- /dev/null +++ b/release-web/.release-it.js @@ -0,0 +1,129 @@ +const version = '${version}'; + +const isRelease = process.argv.includes('--release'); +const preRelease = process.argv.find(arg => arg.startsWith('--preRelease=')); +const preReleaseName = preRelease ? (preRelease.split('=')[1]) : ''; +// const tagMatchOpts = isRelease ? {} : { tagMatch: `v[0-9]*.[0-9]*.[0-9]*-${preReleaseName}.[0-9]*` }; +const tagMatchOpts = isRelease ? { tagExclude: `*[-]*` } : {}; + +console.log(`Release(${isRelease ? true : preReleaseName}): `, process.argv.join(' ')); +console.log(`TagMatch: ${tagMatchOpts}`); + +module.exports = { + plugins: { + '@release-it/conventional-changelog': { + infile: `CHANGELOG${isRelease ? '' : '-' + preReleaseName.toUpperCase()}.md`, + preset: { + name: "conventionalcommits", + types: [ + { + type: "feat", + section: "新特性", + }, + { + type: "fix", + section: "修复BUG", + }, + { + type: "perf", + section: "性能优化", + }, + { + type: "revert", + section: "回滚", + }, + { + type: "docs", + section: "文档", + }, + { + type: "style", + section: "代码格式", + }, + { + type: "refactor", + section: "重构", + }, + { + type: "test", + section: "测试", + }, + { + type: "build", + section: "构建", + }, + { + type: "ci", + section: "CI", + }, + { + type: "chore", + section: "其他", + }, + ], + }, + }, + 'release-it-gitea': { + releaseTitle: "🎉 v${version}", + releaseNotes: (t) => { + const lines = t.changelog.split('\n'); + + const cateLines = lines.filter(line => line.startsWith('###') || line.startsWith('* ')); + + const cateMap = {}; + let currentCate = ''; + + cateLines.forEach(line => { + if (line.startsWith('###')) { + currentCate = line; + cateMap[currentCate] = cateMap[currentCate] || []; + } else { + cateMap[currentCate].push(line); + } + }); + + return Object.entries(cateMap).map(([cate, lines]) => { + return `${cate}\n\n${lines.map(line => `${line}`).join('\n')}\n`; + }).join('\n'); + }, + assets: [ + { + "path": "dist/**/*.map", + "name": "sourcemap.zip", + "type": "zip" + } + ] + } + }, + git: { + push: true, + tagName: `v${version}`, + commitsPath: '.', + commitMessage: `chore: released version v${version} [no ci]`, + requireCommits: false, + requireCommitsFail: false, + getLatestTagFromAllRefs: true, + requireBranch: ['main', 'dev'], + ...tagMatchOpts, + }, + npm: { + publish: false, + ignoreVersion: true, + tag: preReleaseName ? preReleaseName : 'latest', + versionArgs: ['--workspaces false'], + }, + github: { + release: false, + releaseName: `Release v${version}`, + autoGenerate: true, + skipChecks: true, + host: 'git.bjxgj.com' + }, + hooks: { + 'before:release': [ + `echo '\${version}' > /tmp/last-version`, + 'git add --all', + 'npm run build' + ], + } +}; \ No newline at end of file diff --git a/release-web/README.md b/release-web/README.md new file mode 100644 index 0000000..007996f --- /dev/null +++ b/release-web/README.md @@ -0,0 +1,349 @@ +# Web 项目发布构建 Action + +[![GitHub](https://img.shields.io/badge/github-actions-blue.svg)](https://github.com/features/actions) + +自动化 Web 项目发布流程的 GitHub Action,包括版本发布、Docker 镜像构建和推送等完整的 CI/CD 流程。 + +## 功能特性 + +- 🚀 **自动化发布**: 支持 `release-it` 工具进行版本管理和发布 +- 🐳 **Docker 集成**: 自动构建和推送 Docker 镜像到私有仓库 +- 🏷️ **灵活标签**: 支持自定义 Docker 标签,自动生成版本标签 +- 📊 **Sentry 集成**: 可选的 Sentry 错误监控集成 +- 🔧 **高度可配置**: 丰富的输入参数满足不同项目需求 +- ✅ **参数验证**: 自动验证必需参数和文件存在性 + +## 快速开始 + +### 基础用法 + +```yaml +- name: 发布Web项目 + uses: actions/xgj/release-web@main + with: + gitea-token: ${{ secrets.GITEA_TOKEN }} +``` + +### 使用环境变量 + +```yaml +- name: 发布Web项目 + uses: actions/xgj/release-web@main + with: + gitea-token: ${{ secrets.GITEA_TOKEN }} + env: + # 🌍 可以传递任意数量的环境变量给发布命令 + 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: + gitea-token: ${{ secrets.GITEA_TOKEN }} + app-env: "production" + sentry-auth-token: ${{ secrets.SENTRY_AUTH_TOKEN }} + sentry-dsn: ${{ vars.SENTRY_DSN }} + enable-sentry: "true" + docker-registry: "docker-registry.bjxgj.com" + dockerfile-path: "./container/prod/Dockerfile" + docker-tags: | + stable + v2024 +``` + +## 输入参数 + +| 参数名 | 描述 | 必需 | 默认值 | +| --------------------- | ------------------------- | ---- | --------------------------------- | +| `gitea-token` | Gitea 访问令牌 | ✅ | - | +| `app-env` | 应用环境 | ❌ | `production` | +| `sentry-auth-token` | Sentry 认证令牌 | ❌ | - | +| `sentry-dsn` | Sentry DSN 配置 | ❌ | - | +| `enable-sentry` | 是否启用 Sentry | ❌ | `false` | +| `release-command` | 发布命令 | ❌ | `npm run release -- --release -V` | +| `docker-registry` | Docker 仓库地址 | ❌ | `docker-registry.bjxgj.com` | +| `docker-context` | Docker 构建上下文路径 | ❌ | `.` | +| `dockerfile-path` | Dockerfile 路径 | ❌ | `./container/dev/Dockerfile` | +| `docker-tags` | 额外的 Docker 标签 | ❌ | - | +| `enable-docker-build` | 是否执行 Docker 构建 | ❌ | `true` | +| `node-debug` | 是否启用 Node.js 调试模式 | ❌ | `false` | + +## 环境变量支持 + +Action 支持通过 `env` 传递**任意数量**的环境变量给发布命令,这些环境变量会自动传递给 `npm run release` 或其他发布命令: + +```yaml +- uses: actions/xgj/release-web@main + with: + gitea-token: ${{ secrets.GITEA_TOKEN }} + env: + # 🌍 任意环境变量都会自动传递给发布命令 + 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' }} + # ... 更多任意变量 +``` + +### 常用环境变量示例 + +| 环境变量名 | 描述 | 示例值 | +| ------------------- | ---------------- | ----------------------------- | +| `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` | 发布的版本号 | +| `version-with-dash` | 版本号(点号替换为横线) | +| `docker-image-digest` | Docker 镜像摘要 | +| `docker-image-tags` | Docker 镜像标签列表 | + +## 使用场景 + +### 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 + with: + 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 + with: + 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 }} + enable-sentry: "true" + dockerfile-path: "./Dockerfile" + docker-tags: | + ${{ github.sha }} + ${{ github.ref_name }} + + - 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 + with: + gitea-token: ${{ secrets.GITEA_TOKEN }} + app-env: ${{ matrix.app-env }} + dockerfile-path: ${{ matrix.dockerfile }} + docker-tags: ${{ matrix.environment }} +``` + +## 工作流程 + +1. **参数验证**: 检查必需参数和文件是否存在 +2. **发布构建**: 执行 `release-it` 命令进行版本发布 +3. **获取版本**: 从 `/tmp/last-version` 读取新版本号 +4. **准备标签**: 生成 Docker 镜像标签列表 +5. **Docker 构建**: 构建并推送 Docker 镜像(可选) +6. **发布总结**: 输出发布信息和结果 + +## 依赖要求 + +### 项目要求 + +- 包含 `package.json` 文件 +- 配置了 `release-it` 工具 +- 包含发布脚本(如 `npm run release`) +- Docker 构建需要有效的 `Dockerfile` + +### 环境依赖 + +- Node.js 环境 +- npm/pnpm/yarn 包管理器 +- Docker(如果启用 Docker 构建) +- 配置好的 Docker 仓库访问权限 + +## 配置示例 + +### release-it 配置 + +确保项目中有类似的 `.release-it.js` 配置: + +```javascript +module.exports = { + hooks: { + "before:release": [ + "echo '${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 会在以下情况报错并退出: + +- 缺少必需的 `gitea-token` 参数 +- 指定的 `Dockerfile` 不存在 +- `/tmp/last-version` 文件不存在(发布命令未正确执行) +- Docker 构建失败 + +## 安全注意事项 + +- 🔒 始终通过 `secrets` 传递敏感令牌 +- 🔍 定期检查和轮换访问令牌 +- 📋 限制 Docker 仓库访问权限 +- 🚫 避免在日志中暴露敏感信息 + +## 故障排除 + +### 常见问题 + +**Q: 版本文件不存在错误** + +``` +❌ 错误: 版本文件 /tmp/last-version 不存在 +``` + +A: 检查 `release-it` 配置是否包含创建版本文件的 hook: + +```javascript +hooks: { + 'before:release': ['echo \'${version}\' > /tmp/last-version'] +} +``` + +**Q: Docker 构建失败** + +A: 检查: + +1. Dockerfile 路径是否正确 +2. Docker 仓库是否已登录(使用 `actions/xgj/setup-env` action) +3. 构建上下文是否包含必需文件 + +**Q: Gitea Token 权限不足** + +A: 确保 token 具有以下权限: + +- Repository 写权限 +- Releases 创建权限 + +### 调试模式 + +启用详细调试信息: + +```yaml +- uses: actions/xgj/release-web@main + with: + gitea-token: ${{ secrets.GITEA_TOKEN }} + node-debug: "true" +``` + +## 更新日志 + +查看 [Releases](https://github.com/your-org/actions/releases) 获取详细的更新历史。 + +## 贡献 + +欢迎提交 Issue 和 Pull Request 来改进这个 Action! + +## 许可证 + +MIT License - 详见 [LICENSE](../LICENSE) 文件。 diff --git a/release-web/action.yml b/release-web/action.yml new file mode 100644 index 0000000..6cccb4b --- /dev/null +++ b/release-web/action.yml @@ -0,0 +1,200 @@ +name: 'Web项目发布构建' +description: '自动化Web项目发布流程,包括版本发布、Docker镜像构建和推送' +author: 'Your Organization' + +branding: + icon: 'upload-cloud' + color: 'green' + +inputs: + gitea-token: + description: 'Gitea访问令牌' + required: true + + app-env: + description: '应用环境 (development, production等)' + required: false + default: 'production' + + + release-command: + description: '发布命令,默认为 npm run release -- --release -V' + required: false + default: 'npm run release -- --release -V' + + docker-registry: + description: 'Docker仓库地址' + required: false + default: 'docker-registry.bjxgj.com' + + docker-context: + description: 'Docker构建上下文路径' + required: false + default: '.' + + dockerfile-path: + description: 'Dockerfile路径' + required: false + default: './container/dev/Dockerfile' + + docker-tags: + description: '额外的Docker标签 (每行一个标签)' + required: false + default: '' + + enable-docker-build: + description: '是否执行Docker构建 (true/false)' + required: false + default: 'true' + + node-debug: + description: '是否启用Node.js调试模式 (true/false)' + required: false + default: 'false' + +outputs: + version: + description: '发布的版本号' + value: ${{ steps.get_var.outputs.version }} + + version-with-dash: + description: '版本号(点号替换为横线)' + value: ${{ steps.get_var.outputs.version_with_dash }} + + docker-image-digest: + description: 'Docker镜像摘要' + value: ${{ steps.build.outputs.digest }} + + docker-image-tags: + description: 'Docker镜像标签列表' + value: ${{ steps.build.outputs.tags }} + +runs: + using: 'composite' + steps: + - name: 验证必需参数 + shell: bash + run: | + echo "🔍 验证输入参数..." + + if [[ -z "${{ inputs.gitea-token }}" ]]; then + echo "❌ 错误: gitea-token 参数是必需的" + exit 1 + fi + + if [[ "${{ inputs.enable-docker-build }}" == "true" ]]; then + if [[ ! -f "${{ inputs.dockerfile-path }}" ]]; then + echo "❌ 错误: Dockerfile 不存在: ${{ inputs.dockerfile-path }}" + exit 1 + fi + fi + + echo "✅ 参数验证通过" + + - name: 发布构建 + shell: bash + run: | + echo "🚀 开始发布构建..." + echo "执行命令: ${{ inputs.release-command }}" + ${{ inputs.release-command }} + echo "✅ 发布构建完成" + env: + NODE_DEBUG: ${{ inputs.node-debug == 'true' && 'release-it:*' || '' }} + GITEA_TOKEN: ${{ inputs.gitea-token }} + APP_ENV: ${{ inputs.app-env }} + + - name: 获取版本信息 + id: get_var + shell: bash + run: | + echo "📝 获取版本信息..." + + if [[ ! -f "/tmp/last-version" ]]; then + echo "❌ 错误: 版本文件 /tmp/last-version 不存在" + echo "请确保发布命令正确执行并生成了版本文件" + exit 1 + fi + + VERSION=$(cat /tmp/last-version) + VERSION_WITH_DASH=$(echo "$VERSION" | sed 's/\./-/g') + + echo "version=$VERSION" >> $GITHUB_OUTPUT + echo "version_with_dash=$VERSION_WITH_DASH" >> $GITHUB_OUTPUT + + echo "📦 发布版本: $VERSION" + echo "📦 带横线版本: $VERSION_WITH_DASH" + + - name: 准备Docker标签 + if: ${{ inputs.enable-docker-build == 'true' }} + id: docker_tags + shell: bash + run: | + echo "🏷️ 准备Docker标签..." + + REPO_NAME="${{ github.event.repository.name }}" + REGISTRY="${{ inputs.docker-registry }}" + VERSION="${{ steps.get_var.outputs.version }}" + + # 基础标签(保留版本标签) + TAGS="${TAGS}\n${REGISTRY}/${REPO_NAME}:${VERSION}" + + # 添加用户自定义标签 + if [[ -n "${{ inputs.docker-tags }}" ]]; then + while IFS= read -r tag; do + if [[ -n "$tag" ]]; then + # 如果标签不包含仓库地址,则添加默认仓库前缀 + if [[ "$tag" != *"/"* ]]; then + TAGS="${TAGS}\n${REGISTRY}/${REPO_NAME}:${tag}" + else + TAGS="${TAGS}\n${tag}" + fi + fi + done <<< "${{ inputs.docker-tags }}" + fi + + echo "Docker标签列表:" + echo -e "$TAGS" | sed 's/^/ - /' + + # 将标签转换为多行格式供后续步骤使用 + echo -e "$TAGS" > /tmp/docker-tags.txt + + # 输出标签给后续步骤使用 + { + echo "tags<> $GITHUB_OUTPUT + + - name: 构建并推送Docker镜像 + if: ${{ inputs.enable-docker-build == 'true' }} + id: build + uses: docker/build-push-action@v6 + with: + context: ${{ inputs.docker-context }} + file: ${{ inputs.dockerfile-path }} + push: true + tags: ${{ steps.docker_tags.outputs.tags }} + + - name: 发布总结 + shell: bash + run: | + echo "🎉 发布流程完成!" + echo "" + echo "📋 发布信息:" + echo " - 版本号: ${{ steps.get_var.outputs.version }}" + echo " - 应用环境: ${{ inputs.app-env }}" + echo " - Sentry启用: ${{ inputs.enable-sentry }}" + echo "" + + if [[ "${{ inputs.enable-docker-build }}" == "true" ]]; then + echo "🐳 Docker信息:" + echo " - 仓库: ${{ inputs.docker-registry }}" + echo " - 项目名: ${{ github.event.repository.name }}" + echo " - 主要标签:" + echo " - ${{ steps.get_var.outputs.version }}" + if [[ -n "${{ steps.build.outputs.digest }}" ]]; then + echo " - 镜像摘要: ${{ steps.build.outputs.digest }}" + fi + else + echo "🐳 Docker构建已跳过" + fi diff --git a/release-web/examples/basic-release.yml b/release-web/examples/basic-release.yml new file mode 100644 index 0000000..def6e27 --- /dev/null +++ b/release-web/examples/basic-release.yml @@ -0,0 +1,43 @@ +name: "基础发布流程" + +on: + push: + branches: + - main + workflow_dispatch: + +jobs: + release: + runs-on: ubuntu-latest + name: "发布Web项目" + + steps: + - name: 检出代码 + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.GITEA_TOKEN }} + + - name: 设置构建环境 + uses: actions/xgj/setup-env@main + with: + docker-password: ${{ secrets.DOCKER_PASSWORD }} + skip-kubectl: "true" + + - name: 安装依赖 + uses: actions/xgj/npm-install@main + with: + package-manager: "npm" + + - name: 发布构建 + id: release + uses: actions/xgj/release-web@main + with: + gitea-token: ${{ secrets.GITEA_TOKEN }} + app-env: "production" + + - name: 发布结果 + run: | + echo "✅ 发布完成!" + echo "📦 版本: ${{ steps.release.outputs.version }}" + echo "🐳 Docker镜像已推送到仓库" diff --git a/release-web/examples/custom-docker-tags.yml b/release-web/examples/custom-docker-tags.yml new file mode 100644 index 0000000..6d492a6 --- /dev/null +++ b/release-web/examples/custom-docker-tags.yml @@ -0,0 +1,64 @@ +name: "自定义Docker标签发布" + +on: + push: + branches: + - main + - develop + workflow_dispatch: + inputs: + custom_tag: + description: "自定义Docker标签" + required: false + default: "manual" + +jobs: + release: + runs-on: ubuntu-latest + name: "发布项目(自定义标签)" + + steps: + - name: 检出代码 + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.GITEA_TOKEN }} + + - name: 设置构建环境 + uses: actions/xgj/setup-env@main + with: + docker-password: ${{ secrets.DOCKER_PASSWORD }} + skip-kubectl: "true" + + - name: 安装依赖 + uses: actions/xgj/npm-install@main + with: + package-manager: "pnpm" + + - name: 发布构建(带自定义标签) + id: release + uses: actions/xgj/release-web@main + with: + 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 }} + enable-sentry: "true" + docker-tags: | + ${{ github.sha }} + ${{ github.ref_name }} + ${{ github.event.inputs.custom_tag || 'auto' }} + stable + ${{ github.ref == 'refs/heads/main' && 'production' || 'staging' }} + + - name: 显示所有Docker标签 + run: | + echo "🏷️ 生成的Docker标签包括:" + echo " - latest(默认)" + echo " - prod(默认)" + echo " - ${{ steps.release.outputs.version }}(版本标签,保留)" + echo " - ${{ github.sha }}(提交哈希)" + echo " - ${{ github.ref_name }}(分支名)" + echo " - ${{ github.event.inputs.custom_tag || 'auto' }}(自定义标签)" + echo " - stable(稳定版本)" + echo " - ${{ github.ref == 'refs/heads/main' && 'production' || 'staging' }}(环境标签)" diff --git a/release-web/examples/environment-variables.yml b/release-web/examples/environment-variables.yml new file mode 100644 index 0000000..2743015 --- /dev/null +++ b/release-web/examples/environment-variables.yml @@ -0,0 +1,83 @@ +name: "环境变量配置示例" + +on: + push: + branches: + - main + workflow_dispatch: + +jobs: + release-with-env: + runs-on: ubuntu-latest + name: "使用环境变量配置发布" + + steps: + - name: 检出代码 + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.GITEA_TOKEN }} + + - name: 设置构建环境 + uses: actions/xgj/setup-env@main + with: + docker-password: ${{ secrets.DOCKER_PASSWORD }} + skip-kubectl: "true" + + - name: 安装依赖 + uses: actions/xgj/npm-install@main + with: + package-manager: "npm" + + - name: 发布构建(环境变量配置) + id: release + uses: actions/xgj/release-web@main + with: + gitea-token: ${{ secrets.GITEA_TOKEN }} + env: + # 🌍 任意数量的环境变量都会自动传递给 release-it 命令 + APP_ENV: "production" + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + SENTRY_DSN: ${{ vars.SENTRY_DSN }} + SENTRY_VITE: "true" + + # 自定义环境变量示例 + BUILD_NUMBER: ${{ github.run_number }} + BRANCH_NAME: ${{ github.ref_name }} + COMMIT_SHA: ${{ github.sha }} + + # release-it 相关的环境变量 + RELEASE_VERSION_TYPE: "patch" + CHANGELOG_PRESET: "conventionalcommits" + + # 其他可能需要的环境变量 + CI: "true" + NODE_ENV: "production" + + - name: 多环境配置示例 + uses: actions/xgj/release-web@main + with: + gitea-token: ${{ secrets.GITEA_TOKEN }} + docker-tags: | + env-example + ${{ github.ref_name }} + env: + # 🎯 根据分支设置不同的环境变量 + APP_ENV: ${{ github.ref == 'refs/heads/main' && 'production' || 'staging' }} + SENTRY_VITE: ${{ github.ref == 'refs/heads/main' && 'true' || 'false' }} + + # 动态环境变量 + DEPLOY_TARGET: ${{ github.ref == 'refs/heads/main' && 'prod' || 'dev' }} + FEATURE_FLAG_NEW_UI: ${{ contains(github.event.head_commit.message, '[enable-new-ui]') && 'true' || 'false' }} + + - name: 发布结果 + run: | + echo "🎉 发布完成!" + echo "📦 版本: ${{ steps.release.outputs.version }}" + echo "" + echo "✨ 环境变量的优势:" + echo " 🌍 可以传递任意数量的环境变量" + echo " 🔄 支持动态配置" + echo " 🎯 基于条件设置不同值" + echo " 🔧 release-it 和构建脚本可直接使用" + echo " 📋 不需要修改 action 代码" diff --git a/release-web/examples/full-cicd.yml b/release-web/examples/full-cicd.yml new file mode 100644 index 0000000..fa2cc37 --- /dev/null +++ b/release-web/examples/full-cicd.yml @@ -0,0 +1,111 @@ +name: "完整CI/CD流程" + +on: + push: + branches: + - main + - develop + pull_request: + branches: + - main + +env: + REGISTRY: docker-registry.bjxgj.com + NODE_VERSION: "18" + +jobs: + test: + runs-on: ubuntu-latest + name: "代码测试" + + steps: + - name: 检出代码 + uses: actions/checkout@v4 + + - name: 设置Node.js环境 + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + + - name: 安装依赖 + uses: actions/xgj/npm-install@main + with: + package-manager: "npm" + + - name: 代码检查 + run: | + npm run lint + npm run type-check + + - name: 运行测试 + run: npm run test:ci + + - name: 构建项目 + run: npm run build + + release: + runs-on: ubuntu-latest + name: "发布构建" + needs: test + if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop') + + steps: + - name: 检出代码 + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.GITEA_TOKEN }} + + - name: 设置构建环境 + uses: actions/xgj/setup-env@main + with: + docker-registry: ${{ env.REGISTRY }} + docker-password: ${{ secrets.DOCKER_PASSWORD }} + kube-config: ${{ secrets.KUBE_CONFIG }} + + - name: 安装依赖 + uses: actions/xgj/npm-install@main + with: + package-manager: "npm" + cache-prefix: "release" + + - name: 发布构建 + id: release + uses: actions/xgj/release-web@main + with: + gitea-token: ${{ secrets.GITEA_TOKEN }} + app-env: ${{ github.ref == 'refs/heads/main' && 'production' || 'develop' }} + sentry-auth-token: ${{ secrets.SENTRY_AUTH_TOKEN }} + sentry-dsn: ${{ vars.SENTRY_DSN }} + enable-sentry: ${{ github.ref == 'refs/heads/main' && 'true' || 'false' }} + docker-registry: ${{ env.REGISTRY }} + dockerfile-path: "./Dockerfile" + docker-tags: | + ${{ github.sha }} + ${{ github.ref_name }} + ${{ github.ref == 'refs/heads/main' && 'stable' || 'unstable' }} + + - name: 部署到Kubernetes (生产环境) + if: github.ref == 'refs/heads/main' + run: | + echo "🚀 部署到生产环境..." + kubectl set image deployment/web-app \ + web-app=${{ env.REGISTRY }}/${{ github.event.repository.name }}:${{ steps.release.outputs.version }} \ + -n production + kubectl rollout status deployment/web-app -n production + + - name: 部署到Kubernetes (开发环境) + if: github.ref == 'refs/heads/develop' + run: | + echo "🧪 部署到开发环境..." + kubectl set image deployment/web-app-dev \ + web-app=${{ env.REGISTRY }}/${{ github.event.repository.name }}:${{ steps.release.outputs.version }} \ + -n development + kubectl rollout status deployment/web-app-dev -n development + + - name: 通知发布结果 + run: | + echo "🎉 发布完成!" + echo "📦 版本: ${{ steps.release.outputs.version }}" + echo "🌍 环境: ${{ github.ref == 'refs/heads/main' && '生产环境' || '开发环境' }}" + echo "🐳 Docker镜像: ${{ env.REGISTRY }}/${{ github.event.repository.name }}:${{ steps.release.outputs.version }}" diff --git a/release-web/examples/multi-environment.yml b/release-web/examples/multi-environment.yml new file mode 100644 index 0000000..41c1a93 --- /dev/null +++ b/release-web/examples/multi-environment.yml @@ -0,0 +1,151 @@ +name: "多环境发布" + +on: + workflow_dispatch: + inputs: + environment: + description: "部署环境" + required: true + default: "staging" + type: choice + options: + - staging + - production + - testing + version_type: + description: "版本类型" + required: true + default: "patch" + type: choice + options: + - patch + - minor + - major + custom_tags: + description: "自定义Docker标签(每行一个)" + required: false + default: "" + +jobs: + release: + runs-on: ubuntu-latest + name: "发布到 ${{ github.event.inputs.environment }} 环境" + + strategy: + matrix: + include: + - environment: staging + dockerfile: "./container/dev/Dockerfile" + app_env: "staging" + registry: "docker-registry.bjxgj.com" + namespace: "staging" + - environment: production + dockerfile: "./container/prod/Dockerfile" + app_env: "production" + registry: "docker-registry.bjxgj.com" + namespace: "production" + - environment: testing + dockerfile: "./container/test/Dockerfile" + app_env: "testing" + registry: "docker-registry.bjxgj.com" + namespace: "testing" + + steps: + - name: 检出代码 + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.GITEA_TOKEN }} + + - name: 设置构建环境 + uses: actions/xgj/setup-env@main + with: + docker-registry: ${{ matrix.registry }} + docker-password: ${{ secrets.DOCKER_PASSWORD }} + kube-config: ${{ secrets.KUBE_CONFIG }} + + - name: 安装依赖 + uses: actions/xgj/npm-install@main + with: + package-manager: "pnpm" + + - name: 准备环境特定的标签 + id: env_tags + run: | + ENVIRONMENT="${{ github.event.inputs.environment }}" + VERSION_TYPE="${{ github.event.inputs.version_type }}" + CUSTOM_TAGS="${{ github.event.inputs.custom_tags }}" + + # 基础标签 + TAGS="${ENVIRONMENT}" + TAGS="${TAGS}\n${ENVIRONMENT}-${VERSION_TYPE}" + TAGS="${TAGS}\n$(date +%Y%m%d)-${ENVIRONMENT}" + + # 添加自定义标签 + if [[ -n "$CUSTOM_TAGS" ]]; then + while IFS= read -r tag; do + if [[ -n "$tag" ]]; then + TAGS="${TAGS}\n${tag}-${ENVIRONMENT}" + fi + done <<< "$CUSTOM_TAGS" + fi + + { + echo "tags<> $GITHUB_OUTPUT + + echo "🏷️ 环境特定标签:" + echo -e "$TAGS" | sed 's/^/ - /' + + - name: 发布构建 + id: release + uses: actions/xgj/release-web@main + with: + gitea-token: ${{ secrets.GITEA_TOKEN }} + app-env: ${{ matrix.app_env }} + sentry-auth-token: ${{ secrets.SENTRY_AUTH_TOKEN }} + sentry-dsn: ${{ vars.SENTRY_DSN }} + enable-sentry: ${{ matrix.environment == 'production' && 'true' || 'false' }} + docker-registry: ${{ matrix.registry }} + dockerfile-path: ${{ matrix.dockerfile }} + release-command: "npm run release -- --release -V --increment ${{ github.event.inputs.version_type }}" + docker-tags: ${{ steps.env_tags.outputs.tags }} + + - name: 部署到Kubernetes + run: | + ENVIRONMENT="${{ github.event.inputs.environment }}" + VERSION="${{ steps.release.outputs.version }}" + NAMESPACE="${{ matrix.namespace }}" + IMAGE="${{ matrix.registry }}/${{ github.event.repository.name }}:${VERSION}" + + echo "🚀 部署到 ${ENVIRONMENT} 环境..." + echo "📦 版本: ${VERSION}" + echo "🐳 镜像: ${IMAGE}" + echo "📍 命名空间: ${NAMESPACE}" + + kubectl set image deployment/web-app \ + web-app=${IMAGE} \ + -n ${NAMESPACE} + + kubectl rollout status deployment/web-app -n ${NAMESPACE} + + echo "✅ 部署完成!" + + - name: 发布总结 + run: | + echo "🎉 多环境发布完成!" + echo "" + echo "📋 发布信息:" + echo " - 环境: ${{ github.event.inputs.environment }}" + echo " - 版本: ${{ steps.release.outputs.version }}" + echo " - 版本类型: ${{ github.event.inputs.version_type }}" + echo " - Docker仓库: ${{ matrix.registry }}" + echo " - Kubernetes命名空间: ${{ matrix.namespace }}" + echo "" + echo "🏷️ 主要标签:" + echo " - latest(默认)" + echo " - prod(默认)" + echo " - ${{ steps.release.outputs.version }}(版本标签)" + echo " - ${{ github.event.inputs.environment }}(环境标签)"