test/release.sh demands an Unreleased section — the release PR of the ceremony can never pass CI #44

Closed
opened 2026-07-19 13:46:51 +00:00 by dan-claude-bot · 0 comments
dan-claude-bot commented 2026-07-19 13:46:51 +00:00 (Migrated from github.com)

Found while opening the real release: 0.1.0 PR after the 2026-07-19 drills (both of which rehearsed the ceremony by tagging a fork branch — a path that runs release.yml but not ci.yml, which is exactly why this stayed invisible until the real PR).

test/release.sh:94-97 asserts, against the REAL CHANGELOG.md:

  1. a literal ## Unreleased heading exists, and
  2. changelog_section CHANGELOG.md Unreleased extracts non-empty and contains #32.

Both are false by construction on the release: X.Y.Z tree — the ceremony's own release PR stamps ## Unreleased## X.Y.Z — date (CONTRIBUTING "Releasing") — so the release PR turns CI red and the flow blocks itself. They are also false on post-release main until the next feature PR re-adds the section (the -dev bump commit doesn't touch the changelog — box precedent 7044f8e).

The guard's real intent (its own comment): the shipped changelog fits the extractor. That property should hold in both legitimate tree states: whatever the TOP ## section is — Unreleased between releases, X.Y.Z — date on and right after a release — the exact function release.yml runs must extract it non-empty. The hardcoded #32 content-grep adds nothing to that and rots with every release.

Fix PR follows. cast has the identical trap (test/release.test.ts:148-152, hardcoding #96) — filed separately; box's suite pins fixtures and already-released sections only, and is not affected.

🤖 Filed from the release-drill session.

Found while opening the real `release: 0.1.0` PR after the 2026-07-19 drills (both of which rehearsed the ceremony by tagging a fork branch — a path that runs `release.yml` but not `ci.yml`, which is exactly why this stayed invisible until the real PR). `test/release.sh:94-97` asserts, against the REAL `CHANGELOG.md`: 1. a literal `## Unreleased` heading exists, and 2. `changelog_section CHANGELOG.md Unreleased` extracts non-empty **and contains `#32`**. Both are false by construction on the `release: X.Y.Z` tree — the ceremony's own release PR stamps `## Unreleased` → `## X.Y.Z — date` (CONTRIBUTING "Releasing") — so the release PR turns CI red and the flow blocks itself. They are also false on post-release main until the next feature PR re-adds the section (the `-dev` bump commit doesn't touch the changelog — box precedent `7044f8e`). The guard's real intent (its own comment): *the shipped changelog fits the extractor*. That property should hold in both legitimate tree states: whatever the TOP `## ` section is — `Unreleased` between releases, `X.Y.Z — date` on and right after a release — the exact function `release.yml` runs must extract it non-empty. The hardcoded `#32` content-grep adds nothing to that and rots with every release. Fix PR follows. cast has the identical trap (`test/release.test.ts:148-152`, hardcoding `#96`) — filed separately; box's suite pins fixtures and already-released sections only, and is not affected. 🤖 Filed from the release-drill session.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: heavy-duty/rig#44
No description provided.