build(release): 调整为同次运行预览后审批发版

- 重构 semantic-release workflow 为 preview 预览后经 environment 审批继续 release

- 绑定同一 SHA 的 preview 与 release 结果并在 summary 中展示版本信息

- 更新 semantic-release 迁移跟踪文档记录新的审批式发版链路
This commit is contained in:
gewuyou 2026-04-26 10:10:53 +08:00
parent d7ddff9f53
commit 16e04cc541
3 changed files with 85 additions and 43 deletions

View File

@ -2,33 +2,30 @@ name: Semantic Release Version and Tag
on: on:
workflow_dispatch: 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: concurrency:
group: semantic-release-main group: semantic-release-main
cancel-in-progress: false cancel-in-progress: false
jobs: jobs:
semantic-release: preview:
if: > if: >
github.ref == 'refs/heads/main' github.ref == 'refs/heads/main'
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: 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: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v6 uses: actions/checkout@v6
with: with:
fetch-depth: 0 fetch-depth: 0
persist-credentials: false persist-credentials: false
ref: ${{ github.sha }}
- name: Validate release branch - name: Validate release branch
run: | run: |
@ -37,19 +34,8 @@ jobs:
exit 1 exit 1
fi fi
- name: Validate PAT token # preview 始终先运行,用于给当前 SHA 生成待发布版本预览。
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。
- name: Semantic release preview - name: Semantic release preview
if: inputs.release_mode == 'preview'
id: semantic_release id: semantic_release
uses: cycjimmy/semantic-release-action@v6 uses: cycjimmy/semantic-release-action@v6
with: with:
@ -58,28 +44,80 @@ jobs:
env: env:
GITHUB_TOKEN: ${{ github.token }} GITHUB_TOKEN: ${{ github.token }}
# release 模式由维护者手动触发,直接创建并推送下一个 tag。 - name: Show preview result
- 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
run: | run: |
echo "mode=${{ inputs.release_mode }}"
echo "published=${{ steps.semantic_release.outputs.new_release_published }}" echo "published=${{ steps.semantic_release.outputs.new_release_published }}"
echo "last_tag=${{ steps.semantic_release.outputs.last_release_git_tag }}" echo "last_tag=${{ steps.semantic_release.outputs.last_release_git_tag }}"
echo "next_version=${{ steps.semantic_release.outputs.new_release_version }}" echo "next_version=${{ steps.semantic_release.outputs.new_release_version }}"
echo "next_tag=${{ steps.semantic_release.outputs.new_release_git_tag }}" echo "next_tag=${{ steps.semantic_release.outputs.new_release_git_tag }}"
- name: Write summary - name: Write preview summary
run: | run: |
{ {
echo "## Semantic Release" echo "## Semantic Release Preview"
echo 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 "- Published: \`${{ steps.semantic_release.outputs.new_release_published }}\`"
echo "- Last tag: \`${{ steps.semantic_release.outputs.last_release_git_tag }}\`" echo "- Last tag: \`${{ steps.semantic_release.outputs.last_release_git_tag }}\`"
echo "- Next version: \`${{ steps.semantic_release.outputs.new_release_version }}\`" echo "- Next version: \`${{ steps.semantic_release.outputs.new_release_version }}\`"

View File

@ -17,7 +17,7 @@
- 当前阶段:`Phase 1` - 当前阶段:`Phase 1`
- 当前焦点: - 当前焦点:
- 增加 `.releaserc.json`,仅启用版本分析与 release notes 生成,不启用 GitHub Release 发布插件 - 增加 `.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` - 明确 `PAT_TOKEN``GITHUB_TOKEN` 的职责边界,确保 tag 继续触发 `publish.yml`
### 已知风险 ### 已知风险
@ -35,12 +35,14 @@
- 已新增 `.releaserc.json`,仅保留 `@semantic-release/commit-analyzer` - 已新增 `.releaserc.json`,仅保留 `@semantic-release/commit-analyzer`
`@semantic-release/release-notes-generator`,避免 `semantic-release` 直接创建 GitHub Release `@semantic-release/release-notes-generator`,避免 `semantic-release` 直接创建 GitHub Release
- 已将 `.github/workflows/auto-tag.yml` 重写为: - 已将 `.github/workflows/auto-tag.yml` 重写为:
- `workflow_dispatch` 由维护者手动选择 `preview``release` - `workflow_dispatch` 启动后总是先跑 `preview`
- `preview` 只执行 dry-run输出 `last_tag``next_version``next_tag` - `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` - 已明确真实打 tag 仍使用 `PAT_TOKEN`,因为 `GITHUB_TOKEN` 推送的 tag 不会继续触发 `publish.yml`
- 已更新 `AGENTS.md` 的 Conventional Commit 规则,显式禁止把纯文档变更写成 `feat(...)``feat(docs)` - 已更新 `AGENTS.md` 的 Conventional Commit 规则,显式禁止把纯文档变更写成 `feat(...)``feat(docs)`
- 已移除基于 `workflow_run``[release ci]` 的自动发版门闸,后续版本预览与真实发版都由维护者手动触发 - 已移除基于 `workflow_run``[release ci]` 的自动发版门闸,后续版本预览与真实发版都由维护者手动触发
- 已将 release 流程从“两次独立 workflow_dispatch”收敛为“同一次 run 里 preview + 审批 + release”的链路
## 验证 ## 验证
@ -68,6 +70,6 @@
## 下一步 ## 下一步
1. 复核 `workflow_dispatch``preview` / `release` 两种模式命名是否还要进一步收紧 1. 在仓库 Settings -> Environments 中为 `release-approval` 配置 required reviewers确保 workflow 会在 preview 后真正暂停
2. 评估是否要在 release 模式中补充额外输入,例如预期 tag 确认或二次确认文本 2. 复核 Actions summary 呈现方式是否还需要更醒目的版本展示
3. 若本轮验证通过,按仓库要求创建补充提交并等待你审阅手动发版流程细节 3. 若本轮验证通过,按仓库要求创建补充提交并等待你审阅同次 run 的手动发版流程细节

View File

@ -27,7 +27,9 @@
- 按用户反馈继续调整发版入口: - 按用户反馈继续调整发版入口:
- 删除基于 `workflow_run` 的自动发版路径 - 删除基于 `workflow_run` 的自动发版路径
- 统一改为 `workflow_dispatch` 手动触发 - 统一改为 `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=` - `dotnet build GFramework.Core.Abstractions/GFramework.Core.Abstractions.csproj -c Release -p:RestoreFallbackFolders=`
- 结果:通过,`0 warning / 0 error` - 结果:通过,`0 warning / 0 error`