diff --git a/.github/workflows/auto-tag.yml b/.github/workflows/auto-tag.yml index 172203cb..9f56dbd2 100644 --- a/.github/workflows/auto-tag.yml +++ b/.github/workflows/auto-tag.yml @@ -2,33 +2,30 @@ name: Semantic Release Version and Tag on: workflow_dispatch: - inputs: - release_mode: - description: Choose preview to inspect the next version, or release to create and push the next tag. - required: true - default: preview - type: choice - options: - - preview - - release concurrency: group: semantic-release-main cancel-in-progress: false jobs: - semantic-release: + preview: if: > github.ref == 'refs/heads/main' runs-on: ubuntu-latest permissions: - contents: write + contents: read + outputs: + published: ${{ steps.semantic_release.outputs.new_release_published }} + last_tag: ${{ steps.semantic_release.outputs.last_release_git_tag }} + next_version: ${{ steps.semantic_release.outputs.new_release_version }} + next_tag: ${{ steps.semantic_release.outputs.new_release_git_tag }} steps: - name: Checkout code uses: actions/checkout@v6 with: fetch-depth: 0 persist-credentials: false + ref: ${{ github.sha }} - name: Validate release branch run: | @@ -37,19 +34,8 @@ jobs: exit 1 fi - - name: Validate PAT token - if: inputs.release_mode == 'release' - run: | - if [ -z "${PAT_TOKEN}" ]; then - echo "::error::PAT_TOKEN is required because a tag created with GITHUB_TOKEN will not trigger publish.yml." - exit 1 - fi - env: - PAT_TOKEN: ${{ secrets.PAT_TOKEN }} - - # preview 模式只输出版本推导结果,不会真正推送 tag。 + # preview 始终先运行,用于给当前 SHA 生成待发布版本预览。 - name: Semantic release preview - if: inputs.release_mode == 'preview' id: semantic_release uses: cycjimmy/semantic-release-action@v6 with: @@ -58,28 +44,80 @@ jobs: env: GITHUB_TOKEN: ${{ github.token }} - # release 模式由维护者手动触发,直接创建并推送下一个 tag。 - - name: Semantic release - if: inputs.release_mode == 'release' - id: semantic_release - uses: cycjimmy/semantic-release-action@v6 - env: - GITHUB_TOKEN: ${{ secrets.PAT_TOKEN }} - - - name: Show result + - name: Show preview result run: | - echo "mode=${{ inputs.release_mode }}" echo "published=${{ steps.semantic_release.outputs.new_release_published }}" echo "last_tag=${{ steps.semantic_release.outputs.last_release_git_tag }}" echo "next_version=${{ steps.semantic_release.outputs.new_release_version }}" echo "next_tag=${{ steps.semantic_release.outputs.new_release_git_tag }}" - - name: Write summary + - name: Write preview summary run: | { - echo "## Semantic Release" + echo "## Semantic Release Preview" echo - echo "- Mode: \`${{ inputs.release_mode }}\`" + echo "- Commit: \`${{ github.sha }}\`" + echo "- Release needed: \`${{ steps.semantic_release.outputs.new_release_published }}\`" + echo "- Last tag: \`${{ steps.semantic_release.outputs.last_release_git_tag }}\`" + echo "- Next version: \`${{ steps.semantic_release.outputs.new_release_version }}\`" + echo "- Next tag: \`${{ steps.semantic_release.outputs.new_release_git_tag }}\`" + echo + echo "If the version looks correct, approve the \`release-approval\` environment to continue." + } >> "${GITHUB_STEP_SUMMARY}" + + release: + if: > + github.ref == 'refs/heads/main' && + needs.preview.outputs.published == 'true' + needs: + - preview + runs-on: ubuntu-latest + permissions: + contents: write + environment: + name: release-approval + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + fetch-depth: 0 + persist-credentials: false + ref: ${{ github.sha }} + + - name: Validate PAT token + run: | + if [ -z "${PAT_TOKEN}" ]; then + echo "::error::PAT_TOKEN is required because a tag created with GITHUB_TOKEN will not trigger publish.yml." + exit 1 + fi + env: + PAT_TOKEN: ${{ secrets.PAT_TOKEN }} + + - name: Semantic release + id: semantic_release + uses: cycjimmy/semantic-release-action@v6 + env: + GITHUB_TOKEN: ${{ secrets.PAT_TOKEN }} + + - name: Show release result + run: | + echo "published=${{ steps.semantic_release.outputs.new_release_published }}" + echo "preview_last_tag=${{ needs.preview.outputs.last_tag }}" + echo "preview_next_version=${{ needs.preview.outputs.next_version }}" + echo "preview_next_tag=${{ needs.preview.outputs.next_tag }}" + echo "last_tag=${{ steps.semantic_release.outputs.last_release_git_tag }}" + echo "next_version=${{ steps.semantic_release.outputs.new_release_version }}" + echo "next_tag=${{ steps.semantic_release.outputs.new_release_git_tag }}" + + - name: Write release summary + run: | + { + echo "## Semantic Release Publish" + echo + echo "- Commit: \`${{ github.sha }}\`" + echo "- Preview last tag: \`${{ needs.preview.outputs.last_tag }}\`" + echo "- Preview next version: \`${{ needs.preview.outputs.next_version }}\`" + echo "- Preview next tag: \`${{ needs.preview.outputs.next_tag }}\`" echo "- Published: \`${{ steps.semantic_release.outputs.new_release_published }}\`" echo "- Last tag: \`${{ steps.semantic_release.outputs.last_release_git_tag }}\`" echo "- Next version: \`${{ steps.semantic_release.outputs.new_release_version }}\`" diff --git a/ai-plan/public/semantic-release-versioning/todos/semantic-release-versioning-tracking.md b/ai-plan/public/semantic-release-versioning/todos/semantic-release-versioning-tracking.md index 41dc324a..9841fab7 100644 --- a/ai-plan/public/semantic-release-versioning/todos/semantic-release-versioning-tracking.md +++ b/ai-plan/public/semantic-release-versioning/todos/semantic-release-versioning-tracking.md @@ -17,7 +17,7 @@ - 当前阶段:`Phase 1` - 当前焦点: - 增加 `.releaserc.json`,仅启用版本分析与 release notes 生成,不启用 GitHub Release 发布插件 - - 将 `auto-tag.yml` 改成纯 `workflow_dispatch` 双模式入口,由维护者手动选择 `preview` 或 `release` + - 将 `auto-tag.yml` 改成同一次 `workflow_dispatch` 里先 `preview`,再等待 environment 审批后继续 `release` - 明确 `PAT_TOKEN` 与 `GITHUB_TOKEN` 的职责边界,确保 tag 继续触发 `publish.yml` ### 已知风险 @@ -35,12 +35,14 @@ - 已新增 `.releaserc.json`,仅保留 `@semantic-release/commit-analyzer` 与 `@semantic-release/release-notes-generator`,避免 `semantic-release` 直接创建 GitHub Release - 已将 `.github/workflows/auto-tag.yml` 重写为: - - `workflow_dispatch` 由维护者手动选择 `preview` 或 `release` + - `workflow_dispatch` 启动后总是先跑 `preview` - `preview` 只执行 dry-run,输出 `last_tag`、`next_version` 与 `next_tag` - - `release` 由维护者手动触发真实打 tag,并把结果写入 job summary + - `release` job 依赖 `preview` 输出,并通过 `release-approval` environment 暂停等待人工确认 + - 人工批准后,`release` 在同一 SHA 上执行真实打 tag,并把 preview / release 结果都写入 job summary - 已明确真实打 tag 仍使用 `PAT_TOKEN`,因为 `GITHUB_TOKEN` 推送的 tag 不会继续触发 `publish.yml` - 已更新 `AGENTS.md` 的 Conventional Commit 规则,显式禁止把纯文档变更写成 `feat(...)` 或 `feat(docs)` - 已移除基于 `workflow_run` 和 `[release ci]` 的自动发版门闸,后续版本预览与真实发版都由维护者手动触发 +- 已将 release 流程从“两次独立 workflow_dispatch”收敛为“同一次 run 里 preview + 审批 + release”的链路 ## 验证 @@ -68,6 +70,6 @@ ## 下一步 -1. 复核 `workflow_dispatch` 的 `preview` / `release` 两种模式命名是否还要进一步收紧 -2. 评估是否要在 release 模式中补充额外输入,例如预期 tag 确认或二次确认文本 -3. 若本轮验证通过,按仓库要求创建补充提交并等待你审阅手动发版流程细节 +1. 在仓库 Settings -> Environments 中为 `release-approval` 配置 required reviewers,确保 workflow 会在 preview 后真正暂停 +2. 复核 Actions summary 呈现方式是否还需要更醒目的版本展示 +3. 若本轮验证通过,按仓库要求创建补充提交并等待你审阅同次 run 的手动发版流程细节 diff --git a/ai-plan/public/semantic-release-versioning/traces/semantic-release-versioning-trace.md b/ai-plan/public/semantic-release-versioning/traces/semantic-release-versioning-trace.md index b1a63edc..63a3851b 100644 --- a/ai-plan/public/semantic-release-versioning/traces/semantic-release-versioning-trace.md +++ b/ai-plan/public/semantic-release-versioning/traces/semantic-release-versioning-trace.md @@ -27,7 +27,9 @@ - 按用户反馈继续调整发版入口: - 删除基于 `workflow_run` 的自动发版路径 - 统一改为 `workflow_dispatch` 手动触发 - - 通过 `release_mode=preview|release` 区分“查看下个版本”和“真实打 tag” + - 先在同一次 run 中执行 `preview` + - 再通过 `release-approval` environment 做人工确认 + - 审批通过后继续同一 SHA 的真实 `release` - 复验最小构建命令: - `dotnet build GFramework.Core.Abstractions/GFramework.Core.Abstractions.csproj -c Release -p:RestoreFallbackFolders=` - 结果:通过,`0 warning / 0 error`