ci(release): fail PRs that regress the beta cycle in .changeset/pre.json (#3486)
## Problem PR #3472 resolved a `.changeset/pre.json` rebase conflict against a copy predating the v0.76.0 stable: | | at `v0.77.0-beta.1` | after #3472 | |---|---|---| | `initialVersions["@runfusion/fusion"]` | `0.76.0` | `0.75.1` | | consumed ledger | 67 entries | 158 (the pre-0.76.0 cycle's) | Nothing failed at PR time. Days later `pnpm release` saw the cycle anchored below the shipped `v0.76.0`, fired its stale-cycle re-anchor (`pre exit` → rewrite all 36 `package.json` → `pre enter`), and proposed **`0.77.0-beta.0`** — below the already-published `0.77.0-beta.1`. The re-anchor guard exists to stop a beta numbering under a stable; fed a stale anchor it caused exactly that. `pre.json` is generated by changesets, hand-edited by nobody, and conflicts in nearly every long-lived branch — so a wrong resolution is invisible until release day. This moves the failure to the PR that causes it. ## The check `scripts/check-pre-json-anchor.mjs`, three invariants: - **`anchor-below-stable`** — `initialVersions` must not sit below the newest `v*` stable tag. This is the exact predicate `evaluateBetaCycleAnchor` keys on in `release.mjs`, so green here means the release will *not* re-anchor. - **`ledger-regression`** — the consumed ledger must stay a **superset** of the last `chore(release):` commit's. Deliberately not a count test: #3472's ledger *grew* 67 → 158 while dropping all 67 real entries, so a size comparison would have passed it. - **`dangling-ledger-entry`** — every consumed entry keeps its `.changeset/*.md`, which pre-mode needs to aggregate notes into the eventual stable release. Skips cleanly outside pre-mode (the stable track deletes `pre.json`). ## Wiring Added to the **Lint** job and `pretest`. Job names are unchanged, so no branch-protection update is needed. The Lint checkout takes `fetch-depth: 200` + `fetch-tags` rather than a full 486MB clone — releases land every few days, so that always reaches a baseline; out of range the ledger rule reports `SKIPPED` rather than passing vacuously, and the two local rules still run. ## Verification - Reproducing #3472's exact `pre.json` in the tree → **exit 1** on all three rules, with the 67 dropped entries named. - Clean `main` → exit 0. - 11 unit tests (`scripts/__tests__/check-pre-json-anchor.test.mjs`), including an explicit assertion that the ledger *grew* in the regression case. - `eslint` clean; workflow YAML parses; job names still `Lint, Typecheck, Build, Gate`. No changeset: CI config only, no `@runfusion/fusion` behavior change. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added automated validation for beta release-cycle metadata. * Checks anchor versions, consumed changeset records, and corresponding changeset files. * Provides clear success or error messages and skips checks when release history is unavailable or not applicable. * **Chores** * Pull request checks now run the beta-cycle validation automatically. * Added comprehensive coverage for valid, invalid, and skipped validation scenarios. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
20
.github/workflows/pr-checks.yml
vendored
20
.github/workflows/pr-checks.yml
vendored
@@ -37,6 +37,16 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
# The pre.json anchor check needs the newest `chore(release):` commit
|
||||
# that touched .changeset/pre.json (its ledger baseline) and the `v*`
|
||||
# stable tags. Bounded depth, not fetch-depth: 0 — releases land every
|
||||
# few days, so 200 commits always reaches one, and a full 486MB clone
|
||||
# on every PR is not worth it. The check falls back to `git ls-remote
|
||||
# --tags` for the tags and reports the ledger rule SKIPPED (never
|
||||
# silently passed) if the baseline is out of range.
|
||||
fetch-depth: 200
|
||||
fetch-tags: true
|
||||
|
||||
- name: Setup Node.js and pnpm
|
||||
uses: ./.github/actions/setup-node-pnpm
|
||||
@@ -47,6 +57,16 @@ jobs:
|
||||
- name: Changeset format
|
||||
run: pnpm check:changesets
|
||||
|
||||
# PR #3472 resolved a .changeset/pre.json rebase conflict against a copy
|
||||
# predating the v0.76.0 stable. Nothing failed at PR time; days later
|
||||
# `pnpm release` saw the cycle anchored below the shipped stable, fired its
|
||||
# stale-cycle re-anchor, and proposed 0.77.0-beta.0 — below the published
|
||||
# 0.77.0-beta.1. pre.json is generated, hand-edited by nobody, and conflicts
|
||||
# in nearly every long-lived branch, so a wrong resolution is invisible
|
||||
# until release day. ~50ms.
|
||||
- name: Beta cycle anchor (pre.json)
|
||||
run: pnpm check:pre-json
|
||||
|
||||
- name: Dashboard route modularity
|
||||
run: pnpm check:routes-modular
|
||||
|
||||
|
||||
Reference in New Issue
Block a user