Repository navigation
Commit c4ef17a
ci(release): the Version PR lane reads the v3
Fixes #23282
Clause-②: no (release CI)
One file, one job: `.github/workflows/release.yml`, the `version-pr` job
(Version PR maintenance). No publish-lane line is touched.
## What broke, measured
- The scheduled `Release` run 38395962884 failed in `Version PR
maintenance` at the PR step with `ENOENT ... .changeset/pre/changes.md`.
The job log shows `changesets/action@v1` resolved to
`a45c4d594aa4e2c509dc14a9f2b3b67ba3780d0d`, which is the v1.9.0 tag.
- The repository's own CLI is fine. `pnpm changeset status` exits 0 on
`main`. In the same failing run, the "Render the post-version tree" step
ran `pnpm run version` (changeset v3.0.3) to completion.
- The failing reader is the action's own copy. v1.9.0 bundles
`@changesets/read` 0.6.7. Its legacy v1 reader treats every directory
under `.changeset/` as an old folder changeset and opens
`DIR/changes.md` and `DIR/changes.json`. Since the 18.0.0-next.0 cut,
`.changeset/pre/` is such a directory.
- **Reproduced with the same code:** the v1.9.0 bundle, run on a scratch
copy of `main` at `9c7cfbf0a9` (local mock API, no remote), fails at the
same point (`setting GitHub credentials`) with the same error. The
workflow-shaped replay of the base workflow fails the same way.
## What this changes
1. **PR step: `changesets/action` v2.1.2, pinned by commit**
(`ae32849d5ba541f9ae29e40e22a623bc13562f51`). v2 is the major upstream
pairs with `@changesets/cli` v3. It bundles `@changesets/read` 1.0.0,
which reads `.changeset/pre/`. In `pre` mode, `readChangesetState`
leaves `pre/` ids out of `hasChangesets`; in `exit` mode it keeps them.
The inputs move to v2's names: `github-token`, `version-script`,
`commit-message`, `pr-title`. v2 throws on each v1 name instead of
ignoring it. `push-with-git-cli: true` keeps v1's git-CLI push.
`create-github-releases: false` stays, and `push-git-tags: false` is
added; both only matter if a publish script were ever added. The
`GITHUB_TOKEN` env is dropped, because v2 takes the token only through
`github-token`.
- It is a commit and not `@v2` because upstream `v2` is a branch. A
moving ref would change the bundled reader without any diff here.
2. **The card's pin: a read rehearsal on the post-version tree.** Three
new steps go between "Validate the post-version tree" and "Restore the
pre-version tree". They copy the rendered `.changeset/` (plus the root
`package.json`, `pnpm-workspace.yaml` and a `node_modules` link) to a
directory outside every git work tree. They run the **same pinned
action** there with no credential, then require `has-changesets` ==
`false`.
- The rendered tree is the tree the next cut lands on `main`. A reader
that cannot read what the CLI writes now goes red while the Version
Packages PR is still open, not on the first refresh after it merges.
- **It cannot write.** The only path out of a "pending" read is
`runVersion`, and its first act is `git checkout`. In a directory that
is not a repository, that fails before any push or API call.
3. **Bounded in-place fix, same defect class:** the lane's pending count
treated `.changeset/pre/*.md` as pending in every mode. In `pre` mode
those changesets are consumed (the CLI's `getRelevantChangesets`), so
they are now counted only on `pre exit`.
- Measured on the post-version tree, which is the tree right after
next.1 merges with nothing new: the old count reads `539` pending, the
version pass moves `0` paths, and "Validate the post-version tree" goes
red with `changesets were pending but the version step moved no path`.
That would have been the first scheduled tick after next.1.
- The same count fix is made in the Restore step. There the mode is read
from the restored tree, because a `pre exit` version deletes `pre.json`.
- All four in-place conditions hold: same class (a lane reader that does
not know the v3 `pre/` layout), a mechanical fix whose shape the CLI
pins, no other claim on the file, and no new verification surface.
## #6170: this lane still cannot publish
The pinned v2.1.2 `src/index.ts` branches on `hasPublishScript =
!!core.getInput("publish-script")`:
- With no changesets and no publish script, it returns.
- With changesets, it runs `runVersion`, the PR path only.
- `runPublish` needs a `publish-script`, and neither invocation passes
one.
The rehearsal invocation also runs in a non-repository directory with no
token. The publish job, the environment gate and the tag push are
untouched. Measured: every replay below reports `published=false`.
## Evidence
All runs were local, on scratch copies of `main` (an independent `git
init` repo, its `origin` a scratch bare repo, the API a local mock). The
real action bundles ran with the runner's `INPUT_*` and `GITHUB_*`
contract. Nothing was dispatched and nothing reached GitHub.
| run | workflow | result |
|---|---|---|
| S1 | this PR, `main` (32 new changesets + 507 consumed) | job green.
Render `pending_before=32`; rehearsal `has-changesets=false`; restore
`32 = 32`; PR step: `git push --force` of `chore: version packages
(next)` by `github-actions[bot]`, then the GraphQL update of the
existing PR (title `chore: version packages (next)`, body 4319 chars,
the same length as #21988's). Rehearsal API requests: 0. |
| S1 content | (the pushed commit) | 32 R100 renames `.changeset/X.md`
to `.changeset/pre/X.md` (exactly the 32 new ones), 168 M (79
`package.json`, 79 `CHANGELOG.md`, 10 `SKILL.md`), `@objectstack/spec`
`18.0.0-next.0` to `18.0.0-next.1`. **The 507 consumed changesets: 0
blob mismatches, 0 missing.** |
| S2 | base (`main` at `9c7cfbf0a9`) | reverse control. PR step fails
with ENOENT on `.changeset/pre/changes.json`. Which of the two parallel
reads rejects first varies; CI showed `changes.md`. |
| S4 | this PR, rehearsal ref swapped to `@v1` | pin's reverse control.
The rehearsal fails with ENOENT on `.changeset/pre/changes.md`, the PR
step is skipped, and the standing PR keeps its last validated content.
This is with `setupGitUser: false`. With v1's default it fails one call
earlier, on `git config` in the non-repository directory. Red either
way, before the cut. |
| S3 | this PR, zero-pending tree (post-version commit as `main`) | job
green. `pending_before=0`, the rehearsal is skipped, and the PR step
logs `No changesets present ... publish-script is not set.` |
| S3 base | base, same tree | the latent red. `pending_before=539`, then
`Validate` fails with `changesets were pending but the version step
moved no path`. |
| probe | v2.1.2 rehearsal on the PRE-version copy |
`has-changesets=true`, then exit 1 at `git checkout` (`not a git
repository`), 0 API requests. |
| exit | v2.1.2 bundled reader vs the lane count, `pre exit` scratch
tree | both count 541 (34 + 507). `pre` mode, post-version: both 0.
`pre` mode, pre-version: both 32. |
## Options weighed (the four axes)
- **(a) chosen: action v2.1.2 by commit, plus the read rehearsal.**
- Real need: it opens next.1, and the rehearsal pins the exact failure.
- Long-term: this is the upstream-sanctioned pairing for CLI v3, not a
workaround. The second reader stays, but it is pinned and rehearsed on
every refresh.
- AI-proofing: a CLI or action bump that desyncs the readers goes red
before the cut, and the pin makes the reader a reviewed diff.
- Scope: one job, no new workflow, job or `check:*` script.
- **(b) a repo-owned version-PR script on the repo's CLI** (`pnpm run
version`, commit, force-push, `gh pr create|edit`, PR body).
- It has one reader by construction and no third-party code holding a
write token.
- It also replaces a maintained upstream component with new in-house PR
machinery that only the live tick can fully verify. That is more surface
on a p1 release lane.
- Worth revisiting if the action and the CLI drift again.
- **(c) stay on v1 and keep `.changeset/pre/` away from it.** Ruled out
by the card: no moving or deleting the consumed changesets, no
`pre.json` edit, no skipped steps.
## The 2026-08-19 hold on v2 (#9208)
The maintainer kept v1 then (「同意 9208」). The recommendation was that a
safety pin must not be upgraded before the property it encodes is read
in v2's source. Its stated reopen path was: *read v2's source for the
publish property and for the bundled reader*. Both are read above at the
pinned commit, and the bundle was run end to end on the next.0-shaped
tree. The other premise, "no measured pull", no longer holds: v1 cannot
read the layout the repo's CLI writes. This PR reverses that hold, so it
needs the maintainer's word as well as the Tier H approval.
## Verification
- Derived gates (`node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack`): 40 families, all run, **all exit 0**, at
`838bc026b5` (the final commit). `--ran` reconciliation: 40 derived, 40
run, 0 NOT-MEASURED, 0 UNRUN. The four artifact-roster gates whose
roster lives under `.github/` were also run: all exit 0.
- **NOT MEASURED: the Validate step's content gates**
(create-objectstack suite, release-notes gates and the rest). Reason:
unchanged by this diff, so the emulation stubbed that step. The live
tick runs them.
- **NOT MEASURED: GitHub-side behaviour** of v2's git-CLI push auth
header and the PR create/update. Reason: only a live run measures it,
and this lane is not dispatched while the PD15 question on #23193 is
open. The local replay exercised the same code against a bare remote and
a mock API.
- **NOT MEASURED: actionlint.** Reason: not installed here. The YAML
parses, and `check:workflow-status-functions` and
`check:workflow-step-name-quoting` scanned it green.
- **Live check after merge:** the next 6-hourly scheduled `Release`
tick. Expected log lines: `Rehearse the version-PR changeset read ...`
gives `No changesets present ...`; the assertion step gives
`has-changesets=false`; and a `chore: version packages (next)` PR opens.
## Acceptance notes (not filed)
- #20562 landed nothing: it was closed `not_planned`, and the maintainer
kept it closed on 2026-09-30. The scheduled rehearsal this pin extends
is the `version-pr` job's own post-version render and validation.
- objectui's `changeset-release.yml` runs `changesets/action@v1` with
`@changesets/cli` ^3.0.0. It would meet the same reader the first time a
pre-mode version pass writes `.changeset/pre/` there. objectui has no
`pre.json` today, so this is dormant. Carrier: none.
- The lane's README exclusion mirrors `@changesets/read` 0.x. Read 1.x
also ignores `AGENTS.md`, `CLAUDE.md` and `GEMINI.md` under
`.changeset/`. Dormant: no such file exists.
## Changeset
None. This needs `skip-changeset`, and the label is left to the seat.
The only changed path, `.github/workflows/release.yml`, belongs to no
workspace package, so it is in no package's `files[]`. Positive control:
`packages/spec/src/index.ts` resolves to `@objectstack/spec` (public),
one of the 82 workspace packages (71 public).
## 维护者速读(草稿)
### 改了什么
只改了发版工作流里"维护 Version Packages PR"这一个定时任务:
- 把它用的第三方 Action(changesets/action)从 v1 换成 v2.1.2,并按提交固定版本;
- 新增一次只读预演:每次刷新时,先用同一个 Action 去读"版本提交之后"的目录,读不懂就当场变红;
- 修正了"待发布 changeset"的计数:prerelease 模式下,`.changeset/pre/` 里已被消费的
changeset 不再算作待发布。
### 为什么改
18.0.0-next.0 切版后,已消费的 507 个 changeset 被移进 `.changeset/pre/`。v1
自带的旧读取器把这个目录当成 v1 时代的旧格式去读,每 6 小时一次的刷新都报 ENOENT。结果是 next.1 的 Version
Packages PR 开不出来,next.1 无法发版。已在本地用同一份 Action 代码复现,并验证 v2.1.2 能正确开出
PR:只消费 next.0 之后的 32 个新 changeset,507 个旧的一字未动。计数修正针对的是 next.1 合入后、尚无新
changeset 时必然出现的一次误报变红。
### 风险与代价(含回滚)
- "此车道不能发布"(#6170)不变:两处调用都不传 `publish-script`,v2
源码里没有发布脚本就走不到发布分支。预演在非仓库目录、无凭据下运行,写不出任何东西。
- v2 是大版本升级,推送方式与 PR 更新代码和 v1 不同。本地已用真实 Action 代码对着本地仓库和模拟 API 跑通,但
GitHub 侧行为要等合入后第一次定时运行才算实测。
- 这推翻了 2026-08-19「同意 9208」时保留 v1 的决定;当时写明的重开条件(读 v2 源码确认两条性质)已满足。
- 回滚:revert 本 PR 即可,不涉及任何仓库设置。
### 席位意见
### 你要做的
1. 审阅并批准本 PR:受管面 Tier H,且推翻了 #9208 当时的保留决定,需要你的明确同意。
2. 合入后无需任何操作:下一次 6 小时定时运行即是实测,应看到预演步骤输出 `has-changesets=false`,并开出
`chore: version packages (next)` PR。之后照常由你决定何时合并。
---
_Generated by [Claude
Code](https://claude.ai/code/session_012zwsLMxQBwHUYJgPyrpEvx)_
Co-authored-by: Claude <noreply@anthropic.com>.changeset/pre/ layout (changesets/action v2.1.2, pinned by commit) and rehearses that read before the cut (#23313)1 parent 3d830b7 commit c4ef17a
1 file changed
Lines changed: 152 additions & 23 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
43 | 43 | | |
44 | 44 | | |
45 | 45 | | |
46 | | - | |
| 46 | + | |
47 | 47 | | |
48 | 48 | | |
49 | 49 | | |
| |||
496 | 496 | | |
497 | 497 | | |
498 | 498 | | |
| 499 | + | |
| 500 | + | |
| 501 | + | |
| 502 | + | |
| 503 | + | |
| 504 | + | |
| 505 | + | |
| 506 | + | |
| 507 | + | |
| 508 | + | |
| 509 | + | |
| 510 | + | |
| 511 | + | |
| 512 | + | |
| 513 | + | |
| 514 | + | |
499 | 515 | | |
500 | 516 | | |
501 | 517 | | |
502 | 518 | | |
503 | | - | |
| 519 | + | |
| 520 | + | |
| 521 | + | |
| 522 | + | |
| 523 | + | |
504 | 524 | | |
505 | 525 | | |
506 | 526 | | |
| |||
729 | 749 | | |
730 | 750 | | |
731 | 751 | | |
| 752 | + | |
| 753 | + | |
| 754 | + | |
| 755 | + | |
| 756 | + | |
| 757 | + | |
| 758 | + | |
| 759 | + | |
| 760 | + | |
| 761 | + | |
| 762 | + | |
| 763 | + | |
| 764 | + | |
| 765 | + | |
| 766 | + | |
| 767 | + | |
| 768 | + | |
| 769 | + | |
| 770 | + | |
| 771 | + | |
| 772 | + | |
| 773 | + | |
| 774 | + | |
| 775 | + | |
| 776 | + | |
| 777 | + | |
| 778 | + | |
| 779 | + | |
| 780 | + | |
| 781 | + | |
| 782 | + | |
| 783 | + | |
| 784 | + | |
| 785 | + | |
| 786 | + | |
| 787 | + | |
| 788 | + | |
| 789 | + | |
| 790 | + | |
| 791 | + | |
| 792 | + | |
| 793 | + | |
| 794 | + | |
| 795 | + | |
| 796 | + | |
| 797 | + | |
| 798 | + | |
| 799 | + | |
| 800 | + | |
| 801 | + | |
| 802 | + | |
| 803 | + | |
| 804 | + | |
| 805 | + | |
| 806 | + | |
| 807 | + | |
| 808 | + | |
| 809 | + | |
| 810 | + | |
| 811 | + | |
| 812 | + | |
| 813 | + | |
| 814 | + | |
| 815 | + | |
| 816 | + | |
| 817 | + | |
| 818 | + | |
| 819 | + | |
| 820 | + | |
| 821 | + | |
| 822 | + | |
| 823 | + | |
| 824 | + | |
| 825 | + | |
| 826 | + | |
732 | 827 | | |
733 | 828 | | |
734 | 829 | | |
735 | | - | |
736 | | - | |
737 | | - | |
738 | | - | |
| 830 | + | |
| 831 | + | |
| 832 | + | |
| 833 | + | |
| 834 | + | |
739 | 835 | | |
740 | 836 | | |
741 | 837 | | |
| |||
758 | 854 | | |
759 | 855 | | |
760 | 856 | | |
| 857 | + | |
| 858 | + | |
| 859 | + | |
| 860 | + | |
| 861 | + | |
| 862 | + | |
| 863 | + | |
761 | 864 | | |
762 | 865 | | |
763 | | - | |
| 866 | + | |
| 867 | + | |
| 868 | + | |
| 869 | + | |
| 870 | + | |
764 | 871 | | |
765 | 872 | | |
766 | 873 | | |
| |||
793 | 900 | | |
794 | 901 | | |
795 | 902 | | |
796 | | - | |
| 903 | + | |
| 904 | + | |
| 905 | + | |
| 906 | + | |
| 907 | + | |
| 908 | + | |
| 909 | + | |
| 910 | + | |
| 911 | + | |
| 912 | + | |
| 913 | + | |
| 914 | + | |
797 | 915 | | |
798 | | - | |
| 916 | + | |
799 | 917 | | |
800 | 918 | | |
801 | | - | |
802 | | - | |
| 919 | + | |
| 920 | + | |
| 921 | + | |
803 | 922 | | |
804 | 923 | | |
805 | 924 | | |
806 | | - | |
807 | | - | |
| 925 | + | |
| 926 | + | |
808 | 927 | | |
| 928 | + | |
| 929 | + | |
809 | 930 | | |
810 | 931 | | |
811 | 932 | | |
812 | 933 | | |
813 | 934 | | |
814 | | - | |
815 | | - | |
816 | | - | |
817 | | - | |
818 | | - | |
819 | | - | |
| 935 | + | |
| 936 | + | |
| 937 | + | |
| 938 | + | |
| 939 | + | |
| 940 | + | |
| 941 | + | |
| 942 | + | |
| 943 | + | |
| 944 | + | |
| 945 | + | |
| 946 | + | |
| 947 | + | |
820 | 948 | | |
821 | 949 | | |
822 | | - | |
823 | | - | |
824 | | - | |
825 | | - | |
| 950 | + | |
| 951 | + | |
| 952 | + | |
| 953 | + | |
| 954 | + | |
826 | 955 | | |
827 | 956 | | |
828 | 957 | | |
| |||
0 commit comments