Skip to content

fix(release): 发版准备工作流可重入——已有 PR 不动分支,只覆盖机器产出 - #473

Merged
modusensus merged 1 commit into
mainfrom
fix/release-prep-rerun
Oct 18, 2026
Merged

modusensus merged 1 commit into
mainfrom
fix/release-prep-rerun

Conversation

@modusensus

Copy link
Copy Markdown
Member

起因

为发 v0.9.1,在真实 main 上跑了两遍新版 Release Prep 工作流。八步里前七步全 success,两次都只卡在最后一步——但原因完全不同,是两条独立的缺陷。

真因一:开 PR 被组织策略拒(run 39123249758)

pull request create failed: GraphQL: GitHub Actions is not permitted to create or approve pull requests (createPullRequest)

工作流 job 里写着 pull-requests: write,但那只是声明式权限,不是总开关。实测:

$ gh api repos/slow-stack/mneme/actions/permissions/workflow
{"default_workflow_permissions":"read","can_approve_pull_request_reviews":false}

我用 gh api -X PUT 想打开它,返回 409 Conflict:The organization does not allow GitHub Actions to create or approve pull requests——开关在组织层,仓库层改不动。这条只能人去开,代码侧能做的是把失败说清楚。

真因二:工作流不可重入(run 39126751114)

! [rejected]        release-prep/0.9.1 -> release-prep/0.9.1 (fetch first)
error: failed to push some refs to 'https://github.com/slow-stack/mneme'

第一次运行已经把分支推上去了,第二次就撞。不可重入的代价不是「重跑失败」这么轻:人会以为流程坏了,转去手工发版——而那正是这套自动化想避免的结果。

改法:推分支前三档守卫

远端分支状态 行为
有进行中的 PR 什么都不动,::warning:: 说明并 exit 0。分支上可能已有人补了 CHANGELOG 条目——那正是留给人的那部分工作,覆盖掉比不能重跑更糟
无 PR,顶端是上次机器产出(作者 modusensus、标题 chore: v<V> 发布准备) 按重跑处理,--force-with-lease=refs/heads/<分支>:<fetch 到的 SHA> 覆盖
其余 ::error:: 停下,要人先确认那条分支是谁的

用 --force-with-lease 而不是 --force:远端在我们 fetch 之后被推过就拒绝,宁可失败也不悄悄覆盖。

开 PR 失败时给可行动的报错(去哪个页面、开叫什么名字的开关、然后重跑——此时还没有 PR,守卫会覆盖机器产出,不会丢任何人的改动)。

回归锁

test/workflow-guards.test.js 5 → 7 条:

  • 重跑守卫:断言 --state open 的查询排在 git push 之前、用了 --force-with-lease 而非 --force、且 if [ "$MACHINE_TAIL" != "yes" ] 这个 if 本身在(不是只查变量名——变量名留在 case 里、判定被删掉照样绿)。
  • 可行动报错:codeOnly() 剥掉注释后再断言三条文案串。

变异验证(五处全部变红)

变异 结果
去掉 PR 查询 ✖ 红
--force 退回无条件 ✖ 红
删掉「顶端不是机器产出就停」的判定 ✖ 红
报错文案去掉开关名 ✖ 红
报错文案去掉具体报错 ✖ 红

后两条第一次是 GREEN 未捕获——对全文 grep 会被注释里解释这件事的文字骗过;判定那条同理。两处断言加严后才真正锁住。

验证

  • 车道内 npm test:2173 tests / 2172 pass / 0 fail / 1 skip
  • node scripts/check-sync.js:✓ 72 个文件一致
  • 三个 run: 块 bash -n 语法通过

合并后还需要人做一件事

组织 Settings → Actions → General → 打开 Allow GitHub Actions to create and approve pull requests。不开的话,Release Prep 会一直停在最后一步(但报错现在会告诉你去哪开)。

两次在真实 main 上跑 v0.9.1 的 Release Prep,八步里前七步都成功,
每次都卡在最后一步,但原因不同:

1. 第一次(run 39123249758)gh pr create 被拒:
   GraphQL: GitHub Actions is not permitted to create or approve pull requests。
   工作流 job 里的 pull-requests: write 只是声明式权限,总开关在仓库
   Settings → Actions → General;组织默认关闭时仓库层改不动(gh api PUT 返回 409)。
   代码这边能做的只有把失败说清楚,报错要点名去哪个页面、开哪个开关。

2. 第二次(run 39126751114)更早就挂:release-prep/0.9.1 已存在,
   push 被 fetch first 拒——这条工作流原本不可重入。

不可重入的代价不是重跑失败这么轻:人会以为流程坏了,转去手工发版,
整套自动化就此被绕开。

修法:推分支前加三档守卫——
  · 分支上有进行中的 PR:什么都不动、静默退出(分支上可能已有人补条目)
  · 没有 PR 且顶端是上次机器产出:按重跑处理,用 --force-with-lease 覆盖
    (不是 --force:远端在 fetch 之后被推过就拒)
  · 其余:停下,要人先确认那条分支是谁的

回归锁加在 test/workflow-guards.test.js 两条,五处变异验证全部变红。
其中报错文案那条第一版是 GREEN——对全文 grep 会被注释里解释这件事的
文字骗过,改用 codeOnly() 剥注释后才真正锁住;同理,判定那条断言的是
if 本身而不是变量名,否则变量名留在 case 里、判定删掉照样绿。

车道内 npm test: 2173 tests / 2172 pass / 0 fail / 1 skip
check-sync: 72 个文件一致
Copilot AI lite review requested due to automatic review settings October 18, 2026 12:32

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.

@coderabbitai

coderabbitai Bot commented Oct 18, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 16 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 2 included reviews currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Repository: slow-stack/mneme/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 81585256-7082-4b0b-973a-e25e1d8e8ee7
📥 Commits

Reviewing files that changed from the base of the PR and between 6db884b and 5f225a5.

📒 Files selected for processing: 5
  • .github/workflows/release-prep.yml
  • README.md
  • dsh-mneme/CHANGELOG.md
  • dsh-mneme/README.md
  • dsh-mneme/test/workflow-guards.test.js
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Oct 18, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@modusensus
modusensus merged commit 7c15465 into main Oct 18, 2026
11 checks passed
@modusensus
modusensus deleted the fix/release-prep-rerun branch October 18, 2026 12:37
modusensus added a commit that referenced this pull request Oct 18, 2026
[0.9.1] 节此前只有 #466–#473 的文档、安全与发版条目共 11 条,
而 v0.9.0 的 tag(94d855e)之后共有 65 笔非合并提交,扣掉 13 笔
纯徽章同步,还有 52 笔实质提交从没进过任何 CHANGELOG 节 ——
直接发出去等于把一个完整的 M.O. 运行时悄悄发布到 npm。

补四节:
- 🆕 新增 8 条:M.O. 写侧(执行窗口 + 运行账 + 归属候选)、会话事件
  翻成观察、P1/P2/P3 三级、步骤 assert 与 optional、R1/R2 提议、
  沉淀链草稿挖掘、人格定义页 v1.2
- 🐛 修复 6 条:#460 检查更新把成功报成失败、#450 向量写入回执与行级
  模型出处、#458 账本 ids 跨块引用被 catch 吞、candidates.js 双 CR 行尾、
  peer 范围、effective 键计数锁
- 🎨 面板 1 条:#448 三轮 UX 复检
- 📚 文档 2 条:#466 门面、#467 SECURITY.md
- 🧪 内部与测试 2 条:注释裸行号改符号名 + 零消费者代码清理

节序按功能面重排(新增 / 修复 / 面板 / 文档 / 安全 / 发版与文档 /
仓库结构 / 内部与测试),[Unreleased] 仍留空。

同时补上三处人写内容:
- 根 README 的 News 表中英各两行(M.O. 写侧、人格页 v1.2)
- 根 README 路线图 v0.9 行状态改成「已发布(至 v0.9.1)」并补写侧主题
- 子 README 版本历史 v0.9.1 行填上主题

验证:npm test 2173 tests / 2172 pass / 0 fail / 1 skip;check-sync
72 文件一致;security-doc + release-notes + release-docs + changelog-prep
+ workflow-guards 共 49 条全过;Release 正文渲染 39752 字符,默认可见
38 行 / 10334 字符(v0.9.0 是 60 行 / 29921 字符)。
modusensus added a commit that referenced this pull request Oct 18, 2026
* chore: v0.9.1 发布准备(版本号 + 测试徽章 + CHANGELOG/版本表占位行)

机械部分已由 scripts/release-prep.mjs 完成。合并前还需要人来写:

- [ ] dsh-mneme/CHANGELOG.md 新节里的条目(现在只有一条「- (待填)」)
- [ ] 两个 README 里新占位行的主题描述
- [ ] 根 README 的「📰 最近更新」/「📰 Recent updates」表各加一行头条
- [ ] 跨 minor 时确认 README 路线图上新 minor 行的主题(占位行只写了「(待填)」)
- [ ] 跨 minor 时把 SECURITY.md 中英两张支持版本表挪一格(活跃开发 / 尽力维护 / 不支持三段一起挪,含停止维护那段通知)

* chore(release): v0.9.1 补上 tag 之后 52 笔提交的功能条目

[0.9.1] 节此前只有 #466–#473 的文档、安全与发版条目共 11 条,
而 v0.9.0 的 tag(94d855e)之后共有 65 笔非合并提交,扣掉 13 笔
纯徽章同步,还有 52 笔实质提交从没进过任何 CHANGELOG 节 ——
直接发出去等于把一个完整的 M.O. 运行时悄悄发布到 npm。

补四节:
- 🆕 新增 8 条:M.O. 写侧(执行窗口 + 运行账 + 归属候选)、会话事件
  翻成观察、P1/P2/P3 三级、步骤 assert 与 optional、R1/R2 提议、
  沉淀链草稿挖掘、人格定义页 v1.2
- 🐛 修复 6 条:#460 检查更新把成功报成失败、#450 向量写入回执与行级
  模型出处、#458 账本 ids 跨块引用被 catch 吞、candidates.js 双 CR 行尾、
  peer 范围、effective 键计数锁
- 🎨 面板 1 条:#448 三轮 UX 复检
- 📚 文档 2 条:#466 门面、#467 SECURITY.md
- 🧪 内部与测试 2 条:注释裸行号改符号名 + 零消费者代码清理

节序按功能面重排(新增 / 修复 / 面板 / 文档 / 安全 / 发版与文档 /
仓库结构 / 内部与测试),[Unreleased] 仍留空。

同时补上三处人写内容:
- 根 README 的 News 表中英各两行(M.O. 写侧、人格页 v1.2)
- 根 README 路线图 v0.9 行状态改成「已发布(至 v0.9.1)」并补写侧主题
- 子 README 版本历史 v0.9.1 行填上主题

验证:npm test 2173 tests / 2172 pass / 0 fail / 1 skip;check-sync
72 文件一致;security-doc + release-notes + release-docs + changelog-prep
+ workflow-guards 共 49 条全过;Release 正文渲染 39752 字符,默认可见
38 行 / 10334 字符(v0.9.0 是 60 行 / 29921 字符)。

* docs(readme): 路线图状态格退回 v0.9.0,别在打 tag 之前宣布 v0.9.1 已发布

CodeRabbit 指出中英文路线图的 v0.9 行写成了「已发布(至 v0.9.1)」,而本 PR
只是发版准备,tag 要等合并之后才打。这条与 scripts/release-docs.mjs 里既有的
取舍一致:脚本刻意不改写「已发布(v0.9.0)」,因为它在打 tag 之前跑,改了就等于
提前宣布一个还没发出去的版本,PR 若被放弃那行立刻变成谎话。手写时违反了这条。

只退状态格,v0.9 行的主题描述(本次新补的写侧面)保持不动。

---------

Co-authored-by: modusensus <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants