Merge pull request #45 from dan-claude-bot/fix/release-suite-stamped-tree

fix: the release suite accepts the ceremony's own tree
This commit is contained in:
Daniel Marin 2026-07-19 15:22:15 +01:00 committed by GitHub
commit 219b0fbd72
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 28 additions and 6 deletions

View file

@ -8,6 +8,18 @@ on the way to cutting its first release, and this file starts there.
### Fixed
- **The release suite accepts the ceremony's own tree** (#44) —
`test/release.sh` demanded a literal `## Unreleased` heading in the real
`CHANGELOG.md`, extracting non-empty and containing `#32`. All three are
false by construction on the `release: X.Y.Z` tree the ceremony's own PR
produces (it stamps that heading into `## X.Y.Z — date`), so the first
real release PR turned CI red and the flow blocked itself — invisible to
both fork rehearsals, which tag a branch (`release.yml` runs; `ci.yml`
never does). The guard now asserts what it was for: whatever the TOP
`## ` section is — `Unreleased` between releases, the stamped version on
and right after one — the exact `changelog_section` the workflow runs
extracts it non-empty. The rotting issue-number grep is gone.
- **Headless credential prompts refuse loudly instead of dying silently**
(#42) — the interactive credential prompts (`TS_AUTHKEY` in `bootstrap`,
`RUNNER_TOKEN` in `runner install`, `RUNNER_REMOVE_TOKEN` in

View file

@ -89,12 +89,22 @@ check "changelog: an unknown version yields NOTHING (the refusal signal)" 0 "" \
check "changelog: a date-stamped heading never matches by date" 0 "" \
absent "$FIXCH" 2026-07-18
# ...and the SHIPPED changelog fits the extractor: an Unreleased section the
# release PR will stamp, extractable by the exact function release.yml runs.
check "CHANGELOG.md: has an Unreleased section" 0 "" \
grep -qx "## Unreleased" "$ROOT/CHANGELOG.md"
check "CHANGELOG.md: Unreleased extracts non-empty (the format fits the tool)" \
0 "#32" changelog_section "$ROOT/CHANGELOG.md" Unreleased
# ...and the SHIPPED changelog fits the extractor. The real file has two
# legitimate states, and the old check knew only one (#44, found the day the
# first release PR turned CI red): BETWEEN releases there is an `## Unreleased`
# section feature PRs append to; on a `release: X.Y.Z` tree — and on main
# right after it, until the next feature PR — that section IS the stamped
# `## X.Y.Z — date`. Demanding the literal heading (or, worse, an issue
# number inside it) made the release PR of the ceremony unshippable by
# construction. What the guard is FOR is format drift: whatever the top
# section is called, the exact function release.yml runs must extract it
# non-empty.
# shellcheck disable=SC2016 # the $-refs are the inner bash -c's, deliberately
check "CHANGELOG.md: has a top section (Unreleased or a stamped release)" 0 "" \
bash -c '[ -n "$(grep -m1 "^## " "$1")" ]' _ "$ROOT/CHANGELOG.md"
# shellcheck disable=SC2016 # same: positional args resolve inside the inner shell
check "CHANGELOG.md: the top section extracts non-empty (the format fits the tool)" 0 "" \
bash -c '. "$2/.github/scripts/release-lib.sh"; [ -n "$(changelog_section "$1" "$(grep -m1 "^## " "$1" | awk "{print \$2}")")" ]' _ "$ROOT/CHANGELOG.md" "$ROOT"
# --- release.yml: the pins ---------------------------------------------------
# The workflow itself runs only on a tag push upstream, so pin its