diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6d9ca3c..cf37c93 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -35,7 +35,11 @@ on: branches: [main] permissions: - contents: write + contents: write # tag ref + gh release create + the bump push + # Two consumers (a declared permissions: block zeroes every unspecified + # scope): the decide step's label read (commits//pulls) and the bump + # fallback's `gh pr create --label`. + pull-requests: write jobs: release: diff --git a/CHANGELOG.md b/CHANGELOG.md index d1862bb..27383db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,19 +36,24 @@ on the way to cutting its first release, and this file starts there. ### Added -- **Merging a release-labeled PR IS the release** (#47) — the rig twin of - heavy-duty/box#96, born of the ceremony retro: the tag was a separate, - manual, silent-when-forgotten step, and a forgotten tag produces no red - X. `release.yml` now also fires when a PR into main closes, gated on - merged AND the `release` label, and asserts in order — fail-loud, - creating nothing: `VERSION` at the merge commit is non-`-dev`; `VERSION` - *changed in this PR* (the interlock that fails a mislabeled ordinary PR); - the changelog section for that version extracts non-empty via the same - `changelog_section`; no tag or release exists yet. Then, in the same job, - it API-creates the tag at the merge commit and publishes the release with - the extracted notes. A `GITHUB_TOKEN`-created tag never fires the - tag-push trigger, so the paths cannot double-publish — and that tag-push - path survives intact as the documented manual fallback and backfill. +- **Merging a release-labeled PR IS the release — and the release re-arms + main itself** (#47) — the rig twin of heavy-duty/box#96, born of the + ceremony retro: the tag was a separate, manual, silent-when-forgotten + step, and a forgotten tag produces no red X. `release.yml` now fires on + pushes to main (fork-sourced ceremony PRs get a read-only token on + `pull_request` events), reading the transition from the push itself: + `event.before` to the pushed head. A decide step answers four states — + release-flow *work* merged under the `release` label (`-dev` endstates, + the post-release window) no-ops green with a NOTICE; the two genuinely + ambiguous bare states refuse loudly; a true transition then requires a + merged, `release`-labeled PR behind the commit (read via the API — the + label is the operator's declared intent). Then, in the same job, it + API-creates the tag at the merge commit, publishes with the extracted + notes — and bumps main to `X.Y.(Z+1)-dev` itself, direct push with a + loud open-a-PR fallback, so no follow-up bump PR exists on the paved + road. A `GITHUB_TOKEN`-created tag never fires the tag-push trigger, so + the paths cannot double-publish — and that tag-push path survives intact + as the documented manual fallback and backfill. - **Tagged releases, and an installer that installs them** (#32) — the rig half of the flow designed in heavy-duty/box#83, near-verbatim. A release diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 384277d..ecccb28 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -61,9 +61,12 @@ top of #32/box#83's tag flow): box's tag scheme) and publishes the GitHub release with that section as the body. No assets — the source tarball for the tag is the package `install.sh` downloads. -3. A follow-up (or the next feature PR) bumps main's `VERSION` to - `X.Y.(Z+1)-dev`, so a dev install never impersonates the release in the - `versions/` layout. +3. The release re-arms main itself: the same workflow run bumps `VERSION` + to `X.Y.(Z+1)-dev` and pushes the commit straight to main — no + follow-up PR (it opens one only if branch protection refuses the + direct push, loudly). A dev install therefore never impersonates the + release in the `versions/` layout. On the *manual* tag path the + bump stays yours: open the one-line PR after publishing. Manual fallback (and backfill): if the merge-path run fails, fix what it named, then tag the merge commit `X.Y.Z` by hand and push the tag — the