From 2574be9528d4196f223a590b8cc81277105518c6 Mon Sep 17 00:00:00 2001 From: William Aaron Cheung Date: Wed, 9 Sep 2026 14:58:12 +0800 Subject: [PATCH 1/3] ci(release): settle directly, gated by the `release` environment The settle dispatch is now the settlement decision: the `release` environment's required reviewers approve the run, the action checks the dispatcher's admin permission (settlers: admin), and the job commits the changelog to the release branch and publishes the tag and Release itself; on-release.yml and the Artifact Registry archives follow the tag as before. No settle branch or PR any more, which also removes the force-push the ban-force-push ruleset rejected today. release-publish.yml stays for PR mode only and its header says so. Co-Authored-By: Claude Fable 5.1 --- .github/workflows/release-publish.yml | 5 +++++ .github/workflows/release-settle.yml | 22 +++++++++++++++++----- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release-publish.yml b/.github/workflows/release-publish.yml index 4ab64b42..b5ad3e1d 100644 --- a/.github/workflows/release-publish.yml +++ b/.github/workflows/release-publish.yml @@ -8,6 +8,11 @@ name: Release Publish # # This file must exist on the release branch (it does, when the branch is cut # from a default branch that has it). +# +# Only settlement by PR reaches this workflow. release-settle.yml settles +# directly (`settle_mode: direct`, gated by the `release` environment) and +# publishes from its own job, so nothing here fires unless this repo goes +# back to PR mode; the job gate rejects any settle PR the app did not open. on: pull_request: diff --git a/.github/workflows/release-settle.yml b/.github/workflows/release-settle.yml index 6f13dcc3..96cc42a7 100644 --- a/.github/workflows/release-settle.yml +++ b/.github/workflows/release-settle.yml @@ -1,10 +1,19 @@ name: Release Settle -# Propose settling a release candidate. Dispatch from any branch with the +# Settle a release candidate. Dispatch from the default branch with the # version and the full SHA of the release-branch tip; the shared action # verifies it, generates release notes from the commits since the previous -# tag, writes them to the changelog, and opens a settle PR onto the release -# branch. Merging that PR is the settlement decision (release-publish tags it). +# tag, commits them to the changelog on the release branch, and publishes: +# annotated tag at that commit, GitHub Release with the notes (on-release.yml +# then attaches the binaries; release.yaml / release-tracing.yaml archive to +# Artifact Registry on the tag push). +# +# The dispatch is the settlement decision, gated twice: the `release` +# environment on the job (its required reviewers approve the run before it +# starts; its deployment branch policy allows only the default branch) and +# `settlers` in the action (the dispatching actor must be a repository +# admin). The app is a bypass actor on the release-branch and `v*` tag +# rulesets, which is what lets the settle commit and the tag land. on: workflow_dispatch: @@ -18,8 +27,8 @@ on: required: true type: string -# One settle per version: two dispatches for the same version would both -# force-push the same settle branch. Queue, never cancel. +# One settle per version: two dispatches for the same version would race on +# the release branch. Queue, never cancel. concurrency: group: ${{ github.workflow }}-${{ inputs.version }} cancel-in-progress: false @@ -30,6 +39,7 @@ permissions: jobs: settle: runs-on: ubuntu-latest + environment: release steps: - uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3 id: app-token @@ -50,3 +60,5 @@ jobs: version_file: Cargo.toml version_pattern: toml changelog_file: CHANGELOG.md + settle_mode: direct + settlers: admin From 3d825e0544fb7cccefc813a8b6c3c9e2d651a238 Mon Sep 17 00:00:00 2001 From: William Aaron Cheung Date: Wed, 9 Sep 2026 15:18:40 +0800 Subject: [PATCH 2/3] docs(release): describe direct settlement in on-release.yml and the changelog preamble Co-Authored-By: Claude Fable 5.1 --- .github/workflows/on-release.yml | 9 +++++---- CHANGELOG.md | 5 +++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/on-release.yml b/.github/workflows/on-release.yml index a3a98c0b..74f8c69a 100644 --- a/.github/workflows/on-release.yml +++ b/.github/workflows/on-release.yml @@ -2,8 +2,8 @@ name: On Release # Publish target for a stateless-validator release: the two binaries as # downloads on the GitHub Release page, with a SHA256SUMS file. Runs when the -# release pipeline publishes the Release (release-publish creates it after -# the tag), and on demand for a rehearsal on a tag ref: +# release pipeline publishes the Release (release-settle creates it right +# after the tag), and on demand for a rehearsal on a tag ref: # gh workflow run on-release.yml --ref vX.Y.Z -f dry_run=true # The tag being released is always the run's own ref; there is no tag input. # @@ -11,8 +11,9 @@ name: On Release # workflow from the tagged commit's tree, not from the default branch, and the # tag sits on the release branch. A branch cut from a default branch that has # this file carries it; a branch cut before it landed needs it cherry-picked -# (via its own PR — the `release-*` ruleset requires one) before the settle PR -# merges, or the Release publishes with nothing attached and no failed run. +# (via its own PR — the `release-*` ruleset requires one) before release-settle +# is dispatched, or the Release publishes with nothing attached and no failed +# run; release-settle warns when the tip lacks a workflow main has. # A rehearsal likewise only works on a tag whose tree has this file. # # The internal archive to Artifact Registry stays in release.yaml and diff --git a/CHANGELOG.md b/CHANGELOG.md index 40474843..974a1ab2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,9 @@ # Changelog All notable changes to stateless-validator are recorded here, newest first. -Entries are generated by the release flow from merged PR titles; edit an -entry in its release candidate or settle PR if the wording needs work. +Entries are generated by the release flow from merged PR titles. Fix wording +in the release candidate PR while it is open, or, after it merges, by a PR +onto the release branch before settlement is dispatched. ## v2.0.18 From ee10d311fb1cf56e20a3cc899c1007a47b8bf1c0 Mon Sep 17 00:00:00 2001 From: William Aaron Cheung Date: Wed, 9 Sep 2026 15:31:51 +0800 Subject: [PATCH 3/3] docs(changelog): one sentence per line in the preamble Co-Authored-By: Claude Fable 5.1 --- CHANGELOG.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 974a1ab2..43876d9f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,8 @@ # Changelog All notable changes to stateless-validator are recorded here, newest first. -Entries are generated by the release flow from merged PR titles. Fix wording -in the release candidate PR while it is open, or, after it merges, by a PR -onto the release branch before settlement is dispatched. +Entries are generated by the release flow from merged PR titles. +Fix wording in the release candidate PR while it is open, or, after it merges, by a PR onto the release branch before settlement is dispatched. ## v2.0.18