fix(ci): 发版前校验分支名与 meta.Version 一致(防开发阶段误发版)

## 事故(2026-10-17)

`release.yml` 的触发条件是 `push: branches: ['release/**']`,
而 tag 名 = `v` + `meta.Version`。于是:

	2026-10-17 08:35  github-actions[bot] 打出 v1.4.0 并发布 Release

而 1.4.0 当时是**开发阶段**。起因只是有人(我)为了走 PR 流程建了一个
release/v1.4.x 分支并推送 —— 那一刻就自动发版了。

更麻烦的是它钉在旧提交 c2474f5 上:之后又合了三个修复
(异步投递、台账回填、示例 go.mod 修复),已发布的 1.4.0 里**没有**
这些修复,而 Release 页面看起来是"最新"。已按要求撤掉该 tag 与 Release。

## 改动

`prepare` 阶段在读出 meta.Version 之后,校验分支名:

	release/vX.Y.x  → meta 必须是 X.Y.*   (中版本长跑线)
	release/vX.Y.Z  → meta 必须恰好 X.Y.Z

不一致直接 exit 1,并提示"开发阶段请勿推 release/**"。

## 判据(2 条)

 · `TestReleaseWorkflowGuardsVersionMismatch`:逐形态断言两个分支形态
   都有拒绝逻辑 + 有 exit 1
 · `TestNoStaleReleaseTagForDevVersion`:记录当前 meta.Version 是开发版本

★ 判据写砸过一次并修好:第一版用
    `if !contains(A) && !contains(B) { fail }`
  —— 删掉其中任意一处描述文案,另一处还在,判据仍通过 ⇒ 变异不咬。
  改为**逐形态断言**后,两个变异都准确报出是哪个形态缺保护。
This commit is contained in:
JianFeeeee
2026-10-18 08:05:32 +08:00
parent c9b7a6534c
commit e82d21d633
2 changed files with 138 additions and 0 deletions

View File

@ -67,6 +67,42 @@ jobs:
echo "ERROR: 无法从 meta/meta.go 读出 Version"
exit 1
fi
# ★★ 开发阶段保护(2026-10-18 实测事故)
#
# 本 workflow 的触发条件就是 push release/**,而 tag 名 = v$V。
# 于是只要有人**为了走 PR 流程**随手推一个 release/vX.Y.x 分支,
# meta 里的开发版本号就会被**自动打 tag 并发布 Release**:
#
# 2026-10-17 08:35 github-actions[bot] 打出 v1.4.0 并发布
# → 而 1.4.0 当时还是开发阶段
#
# 更麻烦的是它指向旧提交:之后又合了三个修复(异步投递、台账回填),
# 已发布的 1.4.0 里**没有**这些修复,而 Release 看起来是"最新"。
#
# ⇒ 分支名与 meta.Version 必须**一致**才允许发版。
# 推 release/v1.4.x 而 meta 写着 1.4.0(开发中)时,
# 意图明显是"走流程"而不是"发这个版本",直接拒绝。
BRANCH="${GITHUB_REF_NAME:-}"
case "$BRANCH" in
release/v*.*.x)
# release/vX.Y.x —— 中版本长跑线,允许发该中版本下的任何 patch
MAJMIN=$(printf '%s' "$BRANCH" | sed -E 's#^release/v([0-9]+\.[0-9]+)\.x$#\1#')
case "$V" in
"$MAJMIN"|"$MAJMIN".*) ;;
*)
echo "ERROR: 分支 $BRANCH 与 meta.Version=$V 不匹配。" >&2
echo " 该分支承载的是 $MAJMIN.* 系列,而 meta 是 $V。" >&2
echo " 开发阶段请勿推 release/** —— 它会自动打 tag 并发 Release。" >&2
exit 1 ;;
esac ;;
release/v[0-9]*.[0-9]*.[0-9]*)
BVER=$(printf '%s' "$BRANCH" | sed -E 's#^release/v##')
if [ "$BVER" != "$V" ]; then
echo "ERROR: 分支 $BRANCH(钉到 $BVER)与 meta.Version=$V 不一致。" >&2
exit 1
fi ;;
esac
echo "version=$V" >> "$GITHUB_OUTPUT"
echo "tag=v$V" >> "$GITHUB_OUTPUT"
case "$V" in