Repository navigation
fix(release): refuse a Version Packages PR whose queue build lands behind main; mark next.2's 11 missed changesets - #23833
Conversation
…hind main `release-pending-publish.mjs queue-guard` judges a merge-queue build: it finds each version commit on the first-parent chain of base..head and takes the `unconsumed` measurement AT that commit, refusing (exit 1) when any changeset is left over -- the PR was cut from a base that main, or a queue entry ahead of it, has since passed by a changeset. The existing `unconsumed` report reads the same thing only after the landing and only warns; the 18.0.0-next.2 push run carried that warning for all 11 changesets. Self-test: six new batteries (28 total, 111 cases), including the next.2 shape in v3 pre mode, the refreshed-cut control, an ordinary build, a batch, the non-pre shape, and the refusals for a missing/foreign base and a shallow clone. Claude-Session: https://claude.ai/code/session_016PVjjuVPte5XEJvaQx1E4t Co-authored-by: Claude <noreply@anthropic.com>
… a CHANGELOG entry The Version Packages PR for 18.0.0-next.2 landed behind main, so these 11 changesets' code shipped in next.2 while they stayed unconsumed. Each body gains one lead line saying so; the next Version Packages PR lists them under next.3 with that line as the entry's first line. Frontmatter (packages and bump types) is unchanged, and each one's breaking classification under the ADR-0087 gate is unchanged. Claude-Session: https://claude.ai/code/session_016PVjjuVPte5XEJvaQx1E4t Co-authored-by: Claude <noreply@anthropic.com>
… pull_request build Measured: a scheduled refresh starts no pull_request build (#23825's head carries zero check runs), and a dispatched one does (#23481's head carries 45), but either way that build judges the PR against the base it was cut from. Only the merge-queue build sees the tree that lands. Claude-Session: https://claude.ai/code/session_016PVjjuVPte5XEJvaQx1E4t Co-authored-by: Claude <noreply@anthropic.com>
席位核对 · PATCH ROUND · PR #23833 (draft, head
|
One step in the `Lint · CI, release & engine gates` lane runs `release-pending-publish.mjs queue-guard` with the event name and the merge group's base and head shas from the event payload. On merge_group it refuses a version commit that would land a changeset it did not consume; on every other event it says "not a merge-queue build" and exits 0. The lane verdict reads the step's outcome from its roster (continue-on-error + id), so no roster edit is needed. The guard now takes the head from the payload too: a merge_group build with no full head sha is refused rather than read off the checkout. Self-test: 113 cases across 28 batteries. Claude-Session: https://claude.ai/code/session_016PVjjuVPte5XEJvaQx1E4t Co-authored-by: Claude <noreply@anthropic.com>
维护者速读 · #23833 ·
|
⛔ Approval request withdrawn: do not approve this head ·
|
…ed, instead of refusing the queue Withdraws the merge-queue refusal. main takes a changeset-bearing landing about every twenty minutes (77 of 111 landings in a day), so a Version Packages PR almost never reaches the queue current, and refusing it would block nearly every release to protect a CHANGELOG line. `release-pending-publish.mjs annotate-shipped` runs first in the root `version` script (joined with `;`, so it cannot stop the pass). It finds the last version commit, takes the changesets that sat unconsumed in its tree, and gives each one still pending the lead line `**Shipped in VERSION**, whose CHANGELOG missed this entry; listed here one prerelease late.` -- frontmatter byte-unchanged, idempotent (a body already led by `**Shipped in` is left as it is), and only when VERSION is on npm. A shallow clone is deepened in bounded rounds; anything it cannot decide is a ::warning:: with nothing written, and it exits 0 on every path. The queue-guard mode, its batteries and the lint.yml step are removed; lint.yml is back to its merge-base bytes. Self-test: 112 cases across 28 batteries. Claude-Session: https://claude.ai/code/session_016PVjjuVPte5XEJvaQx1E4t Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016PVjjuVPte5XEJvaQx1E4t Co-authored-by: Claude <noreply@anthropic.com>
… this diff Claude-Session: https://claude.ai/code/session_016PVjjuVPte5XEJvaQx1E4t Co-authored-by: Claude <noreply@anthropic.com>
席位核对 · ACCEPT · PR #23833 (draft, head
|
Fixes #23818
Clause-②: no
What this PR does
Each Version Packages cut now records, by itself, what the previous cut shipped without a CHANGELOG entry. It never refuses or holds a release.
New mode
annotate-shippedinscripts/release-pending-publish.mjs.It finds the last version commit and the changesets that sat unconsumed in its tree.
Each one still pending gets this lead line:
**Shipped in VERSION**, whose CHANGELOG missed this entry; listed here one prerelease late.changeset versionthen renders that line as the entry's first line under the next version.One
package.jsonline. The rootversionscript runs the step first, joined with;so it cannot stop the version pass:node scripts/release-pending-publish.mjs annotate-shipped; changeset version && ...Every caller of
pnpm run versiongets it with no workflow edit.The merge-queue refusal is withdrawn. The
queue-guardmode, its batteries and thelint.ymlstep are gone, andlint.ymlhas no diff againstmain. This PR is not governed:check-governed-merges --branchreads 0 of 2 paths.The 11 next.2 entries already landed in docs(changeset): mark the 11 changesets 18.0.0-next.2 shipped without a CHANGELOG entry #23835 (
3c080a65c). This branch mergedmain, so its diff is 2 files:package.json(+1 / -1) and the script (+501 / -26). That is 529 changed lines.Root cause: why #21373's guard did not catch next.2
#21373 added
release-pending-publish.mjs unconsumed.release.yml'srelease-integrityjob runs it in the push that carries the version commit..changeset/*.mdin that commit's tree thatpre.jsondoes not record as consumed.::warning::and a job-summary section.On next.2 it measured correctly. Run 38841989023 (the push of
e5136ff10f, 02:44Z) carried the warning11 changeset(s) from 10 commit(s) are still in the tree of the version commit e5136ff10f .... The publish job started at 02:47:48Z. The miss was about timing, not pre mode:.changeset/pre/, andpre.jsonlists no ids, so the top-level read is right in pre mode.The card's premises, checked in a full-history clone:
e5136ff10f(exit 0) and not of the PR's base4fe8b3def0(exit 1). Control leg: root against4fe8b3def0gives exit 0..changeset/pre/ate5136ff10f.## 18.0.0-next.2section names any of them.Why not refuse the landing
The maintainer asked, verbatim: 「23833 做的对吗?发版本的时候 main 上的队列就是不停在合并的」
The seat measured it (record
6211287288on this PR):maintook 111 first-parent landings, and 77 of them added a changeset: about 3.2 an hour, with at least one in every hour.The detection was right; refusing was the wrong remedy. This PR keeps the detection and moves the remedy to the next cut.
The annotate step
select's definition: the CLI version differs from the first parent's.unconsumedreports. They are read from that commit's tree alone (pendingChangesetsAt, whichunconsumednow shares), so the step needs history only back to that commit's parent.**Shipped inis left as it is. That covers a second run and the hand-written lines from docs(changeset): mark the 11 changesets 18.0.0-next.2 shipped without a CHANGELOG entry #23835. The step's text differs from docs(changeset): mark the 11 changesets 18.0.0-next.2 shipped without a CHANGELOG entry #23835's only by docs(changeset): mark the 11 changesets 18.0.0-next.2 shipped without a CHANGELOG entry #23835's card number.;keeps even a crash from stoppingchangeset version.::warning::and writes nothing. That covers no version commit, unreachable history, an unreadable tree orpre.json, and npm unreadable.git fetch --no-tags --deepen=N origin HEAD-SHAwith N = 100, 200, 400, 800, 1600, until the version commit and its parent are both present. It stops early, with a warning, when a round gains nothing.--no-deepenturns the fetch off.Proof
Self-test.
node scripts/release-pending-publish.mjs --self-testpasses 112 cases across 28 batteries. The six annotate batteries:pre/are untouched. A CRLF changeset keeps its line endings, and a changeset with no fence is unparseable;originunreachable it warns, writes nothing, and the CLI exits 0. With--no-deepenit is undecided;pre.json. Nothing is written in any of them.Ablation.
scripts/ablation-replace.mjsreplaced the writewriteFileSync(w.abs, w.next);withvoid w.next;(anchor 1 -> 0, blob4bfd5209005c->9566045703cc). The self-test went red on 5 cases: byte-exact, second run, hand-annotated, non-pre, depth-1. Restore: the blob equals HEAD andgit diff HEADis empty.Real history. The script is this branch's. Each clone below was made the way
actions/checkoutmakes the version-pr job's (depth 1, sha-pinned) unless stated otherwise.origin/main3fed1eb00, before #23835 landede5136ff10f(next.1 -> next.2); exactly the 11 annotated; exit 0(#23818)card numberaf52476f33c080a65c(#23835 landed; the base of the seat's 08:45Z re-cut of #23825, run 38875444505)dedc6fe388The CHANGELOG renders the line once.
pnpm run version, in a full-history clone oforigin/main3fed1eb00with this branch's script andversionline committed locally (never pushed): exit 0 in 14.5 s. The step annotated the 11, and next.3 carries the line on 19 entries across 12 packages, none twice.dedc6fe388(built from docs(changeset): mark the 11 changesets 18.0.0-next.2 shipped without a CHANGELOG entry #23835's hand lines): 19 entries carry the line, none twice.Every caller of
pnpm run version, measuredrelease.ymlversion-pr job, render stepcheck:docs-image-tag,check:docs-image-tag-sync,check:template-version-sync,check:release-index-currency-sync,check:skill-compatibility,check:nul-bytes,check:release-notes,check:release-page-status,check-release-section-coverage.mjs,check:published-readme-linksrelease.ymlrestore step, thenchangesets/actionversion-script(same job)git reset --hardgit checkout -- .puts the annotated files back with everything else; the 230-path set above is unchangedcut-rc.ymlfetch-depth: 0pnpm run version; afterwards it stages.changesetwholesale, so the annotated files move topre/with the restdocs/releases-maintenance.md).changeset/filesWhat to do about #23825 (next.3) now
#23825 was re-cut at 08:45Z from
3c080a65c, so it carries the 11 entries correctly.mainhas moved since (66d456d01, #23840), so as cut it is behind again.Land this PR before the next.4 cut, then merge #23825 whenever the maintainer chooses. Whatever #23825 ships unlisted when it lands, the next cut annotates as "Shipped in 18.0.0-next.3". Nothing needs freezing or refreshing at merge time.
Acceptance notes
None of these is filed. The seat decides at landing.
0c52e43075(chore: version packages (next) #23382) left 6 changesets unconsumed:23268-external-sharing-model-retired,23268-skills-lint-rules-row,23357-page-component-view-data-api-refused,23387-two-master-names-release,23397-ceremony-builtin-positions,23399-ceremony-not-declared-column-drop. They shipped in next.1 and are listed in the published next.2 sections with no note: 0 next.1-section hits for each add commit. This is the same family as this card. This step covers every cut from here on; a published entry is corrected only by a docs-only amendment.pre exit, the GA CHANGELOG re-lists every prerelease changeset, so an annotated one carries "listed here one prerelease late" into the GA section too. The docs(changeset): mark the 11 changesets 18.0.0-next.2 shipped without a CHANGELOG entry #23835 lines do the same.check-adr-0087-registration's pass line counts inherited-breaking changesets as "non-breaking". Its inheritance exemption also does not re-ask an edited, already-breaking changeset for its disposition. This is read off the code.unconsumed's post-landing warning still says "Name them in the VERSION release notes". With this step, the next cut does that.Local gates (final head
1cdd9d114, merge base66d456d01)node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderived 38 families. Each was run with its exit code captured before any pipe. All 38 exit 0. These include:release-pending-publish.mjs --self-test;check-self-test-wiredandcheck-self-test-workflow-commands;check:merge-driverandcheck:turbo-task-graph;check:dts-closure,check:dual-build-cjs-loads,check:lean-entry-closureandcheck:sourcemap-no-sources-content, after a closure build under the verify lock (74/74 tasks,VERDICT command-exit 0);pnpm check:pm-dispatch-gates(fast tier).--ranreports 38 derived, 38 run, 0 NOT-MEASURED.eslint --no-inline-config scripts/release-pending-publish.mjsexits 0.check-governed-merges --branchreports 0 of 2 paths governed, 529 changed lines (+502 / -27).lint.ymlhas no diff againstorigin/main.Generated by Claude Code