From e6cb82bee5a398f6078ef1c39bfecfc473439790 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 5 Aug 2026 13:09:19 +0000 Subject: [PATCH] fix(ci): Check Changeset stops prescribing the empty changeset that stalled the release (#5292) The gate's failure message offered "an empty changeset" and the `skip-changeset` label as two equal ways out, and the comment above the counter called them "on par". They are equal to THIS gate's counting, but not downstream: the label is a gate-level exemption that produces no input for changesets/action, while an empty-frontmatter changeset is a real input to it. When every pending changeset is empty the action takes its `hasChangesets && !hasNonEmptyChangesets` branch, prints "All changesets are empty; not creating PR" and returns in 0 seconds -- no version PR, no publish, Release run green. That is #4898, which stalled 17.0.0-rc.2. The message was therefore an active mis-prescription: it handed a known release-stalling input to whoever had just hit the wall. Rewritten to three ranked routes, with the label preferred and the empty changeset demoted to a warned last resort that names #4898. The counting logic is untouched: an empty changeset still counts, so today's precedent (#5453 / #5454, both merged behind empty changesets) stays valid. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01GX3sL71LFq8m2usg6VqTSE --- .github/workflows/pr-automation.yml | 50 ++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pr-automation.yml b/.github/workflows/pr-automation.yml index b1e2f7060e..e3f3ff78fd 100644 --- a/.github/workflows/pr-automation.yml +++ b/.github/workflows/pr-automation.yml @@ -99,13 +99,55 @@ jobs: # never go red. #3373 merged a real spec/api-surface fix with no # changeset while this step happily reported "Found 104 changeset(s)". # Diffing against BASE_SHA ignores that residue and sees only what the - # PR itself introduced. An empty-frontmatter changeset still counts — - # it is the sanctioned "this PR releases nothing" declaration, on par - # with the skip-changeset label. + # PR itself introduced. + # + # An empty-frontmatter changeset still COUNTS here, and that is + # deliberate and unchanged — it remains a legal "this PR releases + # nothing" declaration. What #5292 corrected is the PRESCRIPTION, not + # the count: this comment used to call it "on par with the + # skip-changeset label", and the failure message below used to offer + # the two as equals. They are not equal downstream. The label is a + # gate-level exemption that produces no input for changesets/action; + # an empty changeset is a real input to it. See the message for the + # consequence. ADDED=$(git diff --name-only --diff-filter=A "$BASE_SHA" HEAD -- '.changeset/*.md' \ | grep -v '/README\.md$' | wc -l | tr -d '[:space:]') if [ "$ADDED" -eq 0 ]; then - echo "::error::This PR adds no changeset. Run 'pnpm changeset' (an empty changeset is fine for changes that release nothing), or apply the 'skip-changeset' label if it does not need one." + # The full comparison goes to the job log — that is what an author + # reading `gh run view --log-failed`, or expanding this step in the + # UI, actually sees. The ::error:: annotation after it is the + # one-line version for the Checks tab. Both lead with the label. + # Terminator sits at this block's base indentation on purpose: YAML + # strips that much from every line, so `MSG` lands in column 0 of + # the generated script. Do not re-indent it. + cat <<'MSG' + This PR adds no changeset. There are three ways forward, and they are NOT + equivalent. Pick by what the PR actually releases: + + 1. It releases something + -> run 'pnpm changeset' and name the packages it releases. + + 2. It releases nothing (.github/, .claude/, docs/, content/, examples/, + tests-only, and the like) + -> apply the 'skip-changeset' label. <<< PREFERRED + The label is a gate-level exemption. It produces NO input for + changesets/action, so it cannot affect a release. + + 3. An empty-frontmatter changeset also satisfies this gate and stays + legal -- but it is a LAST RESORT, not the quick way past a red check. + Unlike the label it is a REAL INPUT to changesets/action: when every + pending changeset is empty, the action takes its + "hasChangesets && !hasNonEmptyChangesets" branch, prints + "All changesets are empty; not creating PR", and returns in 0 seconds + -- no version PR, no publish, and the Release run still goes GREEN. + That is #4898, which silently stalled 17.0.0-rc.2. It also buys you + nothing the label does not: an empty changeset names no package, so + its body reaches no CHANGELOG. + + If you are unsure, take route 2. A wrong 'skip-changeset' label is caught by + review; a wrong empty changeset is caught by nobody. + MSG + echo "::error::This PR adds no changeset. If it releases nothing, apply the 'skip-changeset' label (preferred); otherwise run 'pnpm changeset' and name the packages. An empty-frontmatter changeset also passes this gate, but it is NOT equivalent to the label -- it is a real input to changesets/action, and an all-empty set stalls the release silently and greenly (#4898). Full comparison in this step's log." exit 1 fi echo "This PR adds $ADDED changeset(s)."