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:
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 }}\`"

View File

@ -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 的手动发版流程细节

View File

@ -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`