feat(release): rehearse a vendored publication with a prerelease

release:vendor --prerelease rc.1 appends the identifier to the version each
package would take, so a first publication can be thrown away instead of holding
the stable dist-tag: publish already routes any version with a prerelease
segment to --tag next.

A prerelease does not consume its release numbers, so the stable release that
follows takes the same ones rather than skipping a patch. Deciding that needs
semver precedence, which git's version sort does not provide — it places
4.0.1-rc.1 above 4.0.1 — so the newest published version is chosen by comparing
versions here, numeric prerelease fields numerically.
This commit is contained in:
imccyu
2026-08-11 02:36:28 +08:00
parent 1af1eb84a4
commit 9840d39ba0
5 changed files with 136 additions and 21 deletions

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/process/2026-08-10-npm-release-sequences.md
2026-08-10-npm-release-sequences.md: d51054b90aa0acd82d252cdb6e97dc1f3c0e51b5
2026-08-10-npm-release-sequences.zh.md: 8c2b7b048af407a79f62c5842f0bd04790a61c9a
2026-08-10-npm-release-sequences.md: df81756ab84163b21996b5e2f12c5c8db994d9a5
2026-08-10-npm-release-sequences.zh.md: 03269aeb987509034564bd0cac92f5d26c7f9b58

View File

@@ -50,7 +50,7 @@ The vendored packages are decoupled from upstream by their scope but keep their
| `@deepseek-ai/cordis-plugin-group` | 1.0.0 | 1.0.1 |
| `@deepseek-ai/cordis-plugin-logger-console` | 1.0.0 | 1.0.1 |
Taking the last published version as the baseline is what survives a re-sync: upstream restoring `4.0.0-rc.8` after this repository published `4.0.1` would otherwise compute `4.0.1` again and collide.
Taking the last published version as the baseline is what survives a re-sync: upstream restoring `4.0.0-rc.8` after this repository published `4.0.1` would otherwise compute `4.0.1` again and collide. `--prerelease rc.1` publishes a rehearsal instead, which takes `--tag next` and leaves the release numbers free: a prerelease has lower precedence than the release it precedes, so `4.0.1` still follows `4.0.1-rc.1`. That ordering is computed here rather than read from `git tag --sort=v:refname`, which places a prerelease above its release.
Only changed packages publish, and the change judgement adds no state file: **each package has its own tag, and that tag records the commit it last published from**. For each package, bump reads the newest `vendor-<package>-v*` tag and diffs the package directory against it. A path counts when the manifest's `files` selects it, when npm publishes it regardless (`package.json`, `README*`, `LICENSE*`), or — for a package whose `files` selects `lib/` — when it is a build input (`src/**`, `tsconfig*.json`, a build config). That last rule exists because a built payload is not tracked by git: without it, a real source change reads as "nothing changed" and the next publication fails on a version whose bytes moved.

View File

@@ -50,7 +50,7 @@ vendor 九包加了 scope 之后与上游脱钩,但保留各自的版本线。
| `@deepseek-ai/cordis-plugin-group` | 1.0.0 | 1.0.1 |
| `@deepseek-ai/cordis-plugin-logger-console` | 1.0.0 | 1.0.1 |
以「上次发布版本」为基线才扛得住重同步:本仓发过 `4.0.1` 之后上游把版本恢复成 `4.0.0-rc.8`,只看 manifest 会再算出 `4.0.1` 并撞上已发版本。
以「上次发布版本」为基线才扛得住重同步:本仓发过 `4.0.1` 之后上游把版本恢复成 `4.0.0-rc.8`,只看 manifest 会再算出 `4.0.1` 并撞上已发版本。`--prerelease rc.1` 则发一次排练版:它进 `--tag next`,而且不占用那组数字——预发布的优先级低于它所先行的正式版,所以 `4.0.1` 仍然接在 `4.0.1-rc.1` 之后。这个次序由脚本自己算,不读 `git tag --sort=v:refname`——git 会把预发布排在正式版之前。
只发改动过的包,而变更判据不引入新的状态文件:**每包一个 tagtag 就是「上次发布到哪个 commit」的记录**。bump 对每个包取最新的 `vendor-<包名>-v*` tag拿包目录与它做 diff。一条路径算命中的条件是manifest 的 `files` 选中它,或 npm 无论如何都会发布它(`package.json``README*``LICENSE*`),或者——当该包的 `files` 选中 `lib/` 时——它是构建输入(`src/**``tsconfig*.json`、构建配置)。最后那条规则的存在理由是构建产物不在 git 里:没有它,真实的源码改动会读成「没变化」,而下一次发布会在一个字节已变的版本上失败。