build(release): 收紧手动发版入口与提交语义约束

- 重构 semantic-release workflow 为 preview 与 release 两种手动触发模式

- 更新 AGENTS 中的 Conventional Commit 规则并禁止 feat(docs) 这类文档提交类型

- 补充 semantic-release 迁移跟踪与二次验证记录
This commit is contained in:
gewuyou 2026-04-26 09:49:14 +08:00
parent b194238385
commit d7ddff9f53
4 changed files with 87 additions and 62 deletions

View File

@ -1,56 +1,26 @@
name: Semantic Release Version and Tag
on:
workflow_run:
workflows: ["CI - Build & Test"]
types:
- completed
branches:
- main
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:
dry-run:
semantic-release:
if: >
github.event_name == 'workflow_dispatch' &&
github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
fetch-depth: 0
persist-credentials: false
# 手动触发仅用于验证 semantic-release 的版本推导结果,不会真正推送 tag。
- name: Semantic release dry-run
id: semantic_release
uses: cycjimmy/semantic-release-action@v6
with:
dry_run: true
ci: false
env:
GITHUB_TOKEN: ${{ github.token }}
- name: Show dry-run result
run: |
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 }}"
release-tag:
if: >
github.event_name == 'workflow_run' &&
github.event.workflow_run.conclusion == 'success' &&
github.event.workflow_run.head_branch == 'main' &&
contains(github.event.workflow_run.head_commit.message, '[release ci]')
runs-on: ubuntu-latest
permissions:
contents: write
steps:
@ -59,9 +29,16 @@ jobs:
with:
fetch-depth: 0
persist-credentials: false
ref: ${{ github.event.workflow_run.head_branch }}
- name: Validate release branch
run: |
if [ "${GITHUB_REF}" != "refs/heads/main" ]; then
echo "::error::Semantic Release Version and Tag only supports workflow_dispatch on main."
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."
@ -70,21 +47,41 @@ jobs:
env:
PAT_TOKEN: ${{ secrets.PAT_TOKEN }}
# 真实 workflow_run 负责按 Conventional Commits 计算版本并推送 tag。
# preview 模式只输出版本推导结果,不会真正推送 tag。
- name: Semantic release preview
if: inputs.release_mode == 'preview'
id: semantic_release
uses: cycjimmy/semantic-release-action@v6
with:
dry_run: true
ci: false
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 release result
env:
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 }}
- name: Show result
run: |
echo "published=${PUBLISHED}"
echo "last_tag=${LAST_TAG}"
echo "next_version=${NEXT_VERSION}"
echo "next_tag=${NEXT_TAG}"
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
run: |
{
echo "## Semantic Release"
echo
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 }}\`"
} >> "${GITHUB_STEP_SUMMARY}"

View File

@ -55,6 +55,19 @@ All AI agents and contributors must follow these rules when writing, reviewing,
- The commit `body` MUST use unordered list items, and each item MUST start with a verb such as `新增``修复``优化`
`更新``补充``重构`.
- Each commit body bullet MUST describe one independent change point; avoid repeated or redundant descriptions.
- Commit `type` MUST reflect release semantics instead of author intent:
- Use `feat` only for user-facing or consumer-facing capability additions that should raise the next released version's
`minor` segment.
- Use `fix` for behavior corrections, `perf` for observable performance improvements, and `refactor` only for
non-feature code restructuring.
- Use `docs``test``chore``build``ci``style` for their literal categories; do not encode these changes as
`feat` just because they feel important.
- Documentation-only changes MUST NOT use `feat`, including new guides, refreshed examples, navigation updates, and
adoption notes for existing capabilities. If a commit changes both product behavior and related docs, either split the
commit or use `feat` only when the code/package behavior is the primary released change.
- Contributors MUST avoid ambiguous scopes such as `feat(docs)` for documentation work. If the change only affects docs,
prefer `docs(<module-or-area>)`; if it adds a real capability in a docs-related toolchain, use the scope of that
actual subsystem instead of `docs`.
- Keep technical terms in English when they are established project terms, such as `API``Model``System`.
- When composing a multi-line commit body from shell commands, contributors MUST NOT rely on Bash `$"..."` quoting for
newline escapes, because it passes literal `\n` sequences to Git. Use multiple `-m` flags or ANSI-C `$'...'`

View File

@ -17,7 +17,7 @@
- 当前阶段:`Phase 1`
- 当前焦点:
- 增加 `.releaserc.json`,仅启用版本分析与 release notes 生成,不启用 GitHub Release 发布插件
- 将 `auto-tag.yml` 改成 `workflow_run` 真正打 tag、`workflow_dispatch` 只做 dry-run 的双入口
- 将 `auto-tag.yml` 改成`workflow_dispatch` 双模式入口,由维护者手动选择 `preview``release`
- 明确 `PAT_TOKEN``GITHUB_TOKEN` 的职责边界,确保 tag 继续触发 `publish.yml`
### 已知风险
@ -35,9 +35,12 @@
- 已新增 `.releaserc.json`,仅保留 `@semantic-release/commit-analyzer`
`@semantic-release/release-notes-generator`,避免 `semantic-release` 直接创建 GitHub Release
- 已将 `.github/workflows/auto-tag.yml` 重写为:
- `workflow_run``main` 上、CI 成功且提交消息包含 `[release ci]` 时执行真实打 tag
- `workflow_dispatch` 只执行 dry-run输出 `last_tag``next_version``next_tag`
- `workflow_dispatch` 由维护者手动选择 `preview``release`
- `preview` 只执行 dry-run输出 `last_tag``next_version``next_tag`
- `release` 由维护者手动触发真实打 tag并把结果写入 job summary
- 已明确真实打 tag 仍使用 `PAT_TOKEN`,因为 `GITHUB_TOKEN` 推送的 tag 不会继续触发 `publish.yml`
- 已更新 `AGENTS.md` 的 Conventional Commit 规则,显式禁止把纯文档变更写成 `feat(...)``feat(docs)`
- 已移除基于 `workflow_run``[release ci]` 的自动发版门闸,后续版本预览与真实发版都由维护者手动触发
## 验证
@ -59,9 +62,12 @@
- `npx --yes semantic-release --dry-run --no-ci`(在 `/tmp/gframework-semrel-dryrun`
- 结果:通过
- 备注dry-run 成功识别 `v0.0.222` 为最新 release并分析 `269` 个提交;按当前规则会提升到下一次 `minor` 发布,预期 tag 为 `v0.1.0`
- `dotnet build GFramework.Core.Abstractions/GFramework.Core.Abstractions.csproj -c Release -p:RestoreFallbackFolders=`(手动发版入口调整后复验)
- 结果:通过
- 备注:`0 warning / 0 error`
## 下一步
1. 复核 `workflow_dispatch` dry-run 输出格式是否还需要额外收窄或增加说明
2. 评估是否要`workflow_run``[release ci]` 门闸改成更显式的 PR label 或 manual approval
3. 若本轮验证通过,按仓库要求创建提交并等待你审阅发版流程细节
1. 复核 `workflow_dispatch` `preview` / `release` 两种模式命名是否还要进一步收紧
2. 评估是否要在 release 模式中补充额外输入,例如预期 tag 确认或二次确认文本
3. 若本轮验证通过,按仓库要求创建补充提交并等待你审阅手动发版流程细节

View File

@ -19,9 +19,18 @@
- `docs/test/chore/build/ci/style -> no release`
- `BREAKING CHANGE` / `BREAKING CHANGES` 作为 major 信号
- 重写 `auto-tag.yml`
- 保留 `workflow_run` 监听 `CI - Build & Test`
- `workflow_dispatch` 变为 dry-run 入口
- 真实打 tag 改由 `semantic-release-action` 处理,并要求 `PAT_TOKEN`
- 改为纯 `workflow_dispatch` 手动入口
- 增加 `release_mode=preview|release` 输入
- `preview` 只跑 dry-run 并输出 `last_tag``next_version``next_tag`
- `release` 由维护者手动触发真实打 tag并要求 `PAT_TOKEN`
- 收紧 `AGENTS.md` 的提交信息约束,明确提交类型必须反映 release semantics纯文档变更禁止写成 `feat(...)`
- 按用户反馈继续调整发版入口:
- 删除基于 `workflow_run` 的自动发版路径
- 统一改为 `workflow_dispatch` 手动触发
- 通过 `release_mode=preview|release` 区分“查看下个版本”和“真实打 tag”
- 复验最小构建命令:
- `dotnet build GFramework.Core.Abstractions/GFramework.Core.Abstractions.csproj -c Release -p:RestoreFallbackFolders=`
- 结果:通过,`0 warning / 0 error`
- 完成最小构建验证:
- `dotnet build GFramework.Core.Abstractions/GFramework.Core.Abstractions.csproj -c Release -p:RestoreFallbackFolders=`
- 结果:通过,`0 warning / 0 error`