fix(ci): Check Changeset 的失败文案不再把「空 changeset」当作与标签等价的出路 (#5292) - #5467
Merged
Conversation
…talled the release (#5292) The gate's failure message offered "an empty changeset" and the `skip-changeset` label as two equal ways out, and the comment above the counter called them "on par". They are equal to THIS gate's counting, but not downstream: the label is a gate-level exemption that produces no input for changesets/action, while an empty-frontmatter changeset is a real input to it. When every pending changeset is empty the action takes its `hasChangesets && !hasNonEmptyChangesets` branch, prints "All changesets are empty; not creating PR" and returns in 0 seconds -- no version PR, no publish, Release run green. That is #4898, which stalled 17.0.0-rc.2. The message was therefore an active mis-prescription: it handed a known release-stalling input to whoever had just hit the wall. Rewritten to three ranked routes, with the label preferred and the empty changeset demoted to a warned last resort that names #4898. The counting logic is untouched: an empty changeset still counts, so today's precedent (#5453 / #5454, both merged behind empty changesets) stays valid. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GX3sL71LFq8m2usg6VqTSE
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
Author
附:新文案在本 PR 上的实跑证据(CI 自证)本 PR 恰好把两条出路都跑了一遍,而且顺序刚好是「先撞门、再按新文案的首选出路脱困」—— 1. 开 PR 时(标签尚未加上)→ Check Changeset 红,打印的正是新文案 这一跑同时证掉了两件本地无法证的事:heredoc 在 GitHub Actions 真实 runner 上的缩进逐字保真(终止符落位正确), 2. 加上 也就是说:红 → 读文案 → 走第 2 条(标签)→ 绿。这条路径就是新文案推荐的那条,本 PR 自己走了一遍。旧文案在同样这一刻会把第 3 条(空 changeset)与第 2 条并列推荐给作者,而在一个改发布闸门的 PR 里种空 changeset,正是 #5292 指出的最难查的情形。 Generated by Claude Code |
os-zhuang
marked this pull request as ready for review
August 5, 2026 13:18
This was referenced Aug 5, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #5292
问题(前提已对 origin/main 复核)
origin/main@61fde5e44:.github/workflows/pr-automation.yml:108—— 失败文案仍写着an empty changeset is fine for changes that release nothing;:102-104—— 计数逻辑上方的注释把空 changeset 称作on par with the skip-changeset label。两处都在,issue 的前提成立。
这两条出路在本闸门的计数里确实等价,但在
changesets/action眼里不等价:skip-changeset标签 = 闸门层面的豁免,不产生任何输入;hasChangesets && !hasNonEmptyChangesets分支,打印All changesets are empty; not creating PR,0 秒返回 —— 不建版本 PR、不发布,而 Release run 全绿。这条机制不是本 PR 的推断,仓内已有记录:
.github/workflows/release.yml:203-208的恢复步骤注释原文写着 "changesets/action reaches its publish branch only with ZERO pending changesets, and an EMPTY changeset still counts ... and a GREEN run (#4898)"。所以旧文案是一条主动的错误处方:开发者(或 agent)刚撞上红闸门的那一刻,它把一个已知会静默卡死发布的输入推荐给对方。
改动
只动文案与注释,不动计数逻辑(按分诊口径)。
失败时改为输出三条有序出路:
pnpm changeset并点名 package;.github/、.claude/、docs/、content/、examples/、纯测试等)→ 首选skip-changeset标签,并说明它为什么安全(不产生 action 输入);#4898、点名「全空则 0 秒静默不发版且 Release 全绿」。上方注释同步改写,去掉
on par with the skip-changeset label这个错误等价,同时明确保留「仍然计数」这一事实。完整对照写进 job log(作者用
gh run view --log-failed或在 UI 里展开这一步时看到的就是它),::error::注解保留为 Checks 页签上的单行版本 —— 一行装不下两条出路的取舍。验证:计数逻辑逐字未动
把
origin/main与本分支的run:脚本从 YAML 里各自抽出,喂同一组 fixture 仓库跑,比对退出码:.changeset/README.md四个 fixture 退出码完全一致。B2 是关键的一格:空 changeset 仍然计数、仍然放行 —— 与今日先例(#5453 / #5454,两者都是带空 frontmatter changeset 过的这道门)保持一致。唯一的差异是 A / C 打印的文案。
关于反向验证方向的老实话:这里不存在「回退改动 → 测试转红」那种方向。本次修改按分诊口径刻意不碰判定,四个 fixture 的判定本就应当前后一致;能证明改对了的,是「退出码逐格相同」+「文案不再包含
an empty changeset is fine」这两条,而不是一次红绿翻转。仓内全域 grep 确认empty changeset is fine改后 0 处命中,且skip-changeset只在本文件出现,没有第二份需要同步的副本。YAML 与 heredoc 也实测过:
yaml.safe_load解析通过,抽出的脚本里终止符MSG落在第 0 列(YAML 会剥掉块标量的公共缩进,所以终止符必须停在本块基准缩进 —— 这点已写进代码注释,防止后来者重新缩进时踩坑)。门禁:
node scripts/check-nul-bytes.mjs→OK (scanned 5447 tracked text file(s) ... no raw NUL bytes);另按 AGENTS.md 的控制字符纪律对改动文件做了越界自扫grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f]'→ 无命中。清点:
.changeset/的空 frontmatter 残留(分诊范围 ②)origin/main@61fde5e44快照:.changeset/*.md(不含 README).changeset/pre.json处于mode: pre/tag: rc,记录了 860 个已被changeset version消费过的 changeset id。以此切分那 172 个空文件:pre.json—— 即已被某次 RC 版本运行消费过、按 pre 模式保留在盘上的残留。这正是:95-101注释描述的、也是本闸门改用BASE_SHAdiff 计数所要绕开的那堆残留。b49ccfdf就已存在。该提交无父提交(仓库历史起点),git 无法再往前归因。adr-0076-status-line-calibration.md0c1660306docs/ci-filter-implicit-success-guard.mdb8add3758.github/pm-dispatch-three-axis-decision-frame.md3681d2a7d(#5453).claude/showcase-register-contact-views.mded0d2aac0(#5438)examples/tenancy-modes-doc-posture-rewrite.md23e9c9004content/widget-contract-theme-token-vocabulary.md31b05372e(#5454)content/结论:未发现无主残留。 每个可归因的待消费空 changeset 都来自一个只改非发布路径的 PR,即分诊评论所说的「正当存在的『releases nothing』声明」,按口径一个都没有删。
当前
#4898的 0 秒分支并未被触发:待消费的 changeset 里还有 173 个非空,所以hasNonEmptyChangesets为真。换句话说今天的残留是账面事实,不是正在燃烧的火。一条顺手核实、写进了新文案的事实
新文案第 3 条里那句「空 changeset 也给不了你标签给不了的东西」不是修辞,是实测:
adr-0044-revise-service-owned-note、ci-node-22-pin、duplicate-fix-guard),把它们的正文原句拿去 grep 全仓CHANGELOG.md→ 各 0 处命中;packages/spec/CHANGELOG.md与packages/cli/CHANGELOG.md2 处。即:空 frontmatter 不点名任何 package,正文因此进不了任何 CHANGELOG。它相对标签没有任何正向收益,却多出「是 action 真实输入」这一项风险 —— 这正是把它降为次选、而不是并列的依据。
(顺带说明:这条事实同样加强了 issue 里那个「干脆禁止空 changeset 进
.changeset/」的备选方案。该方案按分诊口径明确不在本单,牵动发布机器语义,留给维护者裁定,本 PR 不做。)本 PR 自身怎么过这道门
按 walking the talk,走新文案的首选出路:
skip-changeset标签(先例 PR #5290)。本 PR 只改 CI workflow 文案,不发布任何 package —— 正是新文案第 2 条描述的情形。故不附 changeset。skip-changeset标签已随本 PR 一并加上(见 Labels),Check Changeset 因此对本 PR 豁免 —— 这正是新文案第 2 条推荐的走法。