Skip to content

ci: cut the GitHub Release, and fix the Windows registry rename race - #3

Merged
Vieeeeeee merged 2 commits into
mainfrom
ci/cut-github-release
Aug 27, 2026
Merged

Vieeeeeee merged 2 commits into
mainfrom
ci/cut-github-release

Conversation

@Vieeeeeee

Copy link
Copy Markdown
Owner

仓库首页一直写着 Latest: v0.2.0 · 3 days ago,而 npm 上早就有 0.3.0 / 0.4.0 / 0.5.0 了。

原因:发布流程只做 npm publish,从来没有创建 GitHub Release 的步骤。标签推上去了,Release 没建。落到访客眼里就是一个停更三天的项目——而且代码里 checkSelfUpdate 给用户的 releaseUrl 指的正是这个页面。

(0.3.0 / 0.4.0 / 0.5.0 三条 Release 已手动补齐,这个 PR 是把坑堵上,以后不用再补。)

改了什么

在 npm publish 之后加一步 gh release create:

  • 放在 publish 之后 → Release 绝不会宣告一个还装不到的版本
  • 说明取自 CHANGELOG 里对应版本那一节(标签存在之前就写好了)
  • 抽不到内容就让这一步失败,而不是发一个空说明的 Release
  • --verify-tag 拒绝远端不存在的标签
  • 新增权限只有 contents: write 一项

验证

awk 抽取逻辑在真实 CHANGELOG 上跑过:

版本 抽出行数 是否串到下一节
0.5.0 48 否
0.4.0 44 否
0.3.0 25 否
9.9.9(不存在) 0 — 会让步骤报错退出

YAML 无 tab 缩进。

🤖 Generated with Claude Code

Vieeeeeee and others added 2 commits August 27, 2026 11:50
The publish workflow only ran npm publish. Tags for 0.3.0, 0.4.0 and 0.5.0
existed and all three were on npm, but the repository page still advertised
v0.2.0 as Latest — three days stale, and reading like an abandoned project to
anyone landing on it. The in-app update check points at that same page.

The step runs after npm publish, so a Release never announces a version nobody
can install yet. Notes come from the CHANGELOG section for the tag's version,
which is written before the tag exists; an empty section fails the step rather
than publishing a Release with nothing in it. --verify-tag refuses a tag that
is not on the remote.

contents: write is the one permission this adds.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
CI on windows-latest failed 2 runs out of 12 with

  EPERM: operation not permitted, rename '...tmp' -> 'registry.json'

Every command rebuilds registry.json after releasing the override lock, so two
concurrent `describe` calls race on that one rename. POSIX swaps the inode and
always lands; Windows refuses to rename onto a file another process has open.
The command then reported failure for a write that had already succeeded.

Short bounded retries, because nothing holds this file for long. A lock is the
heavier answer for a file that is a rebuildable cache — and overrides.json, the
one holding data that cannot be rebuilt, already has one.

The existing "parallel metadata writes keep every edit" test is the regression
test; it is the one that was failing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@Vieeeeeee Vieeeeeee changed the title ci: cut the GitHub Release after npm accepts the package ci: cut the GitHub Release, and fix the Windows registry rename race Aug 27, 2026
@Vieeeeeee

Copy link
Copy Markdown
Owner Author

补一个提交:CI 在 windows-latest 上挂了,查出来是长期存在的间歇性竞态,不是这个 PR 引入的(近 12 次 CI 里挂过 2 次)。

EPERM: operation not permitted, rename '...tmp' -> 'registry.json'

每条命令跑完都会重建 registry.json,而这一步在 override 锁释放之后。两个并发的 describe 就会撞在这一次 rename 上。POSIX 直接换 inode 永远成功;Windows 不允许 rename 到一个被别的进程打开着的文件。结果是:写其实成功了,命令却报失败。

改法是有上限的短重试——这个文件没人会长时间持有。加锁是更重的答案,而且对一个可重建的缓存不值得;真正不可重建的 overrides.json 早就有锁了。

回归测试就是那条挂掉的 parallel metadata writes keep every edit,不需要新增。

本地 98/98,ops.test.mjs 连跑 5 轮全绿。

@Vieeeeeee
Vieeeeeee merged commit 6d9a7ba into main Aug 27, 2026
9 checks passed
@Vieeeeeee
Vieeeeeee deleted the ci/cut-github-release branch August 27, 2026 04:04
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.

1 participant