Skip to content

feat(release)!: settle releases from branch state, not from a settle-PR merge - #56

Merged
Troublor merged 10 commits into
mainfrom
ci/release-settle-redesign
Oct 28, 2026
Merged

Troublor merged 10 commits into
mainfrom
ci/release-settle-redesign

Conversation

@Troublor

Copy link
Copy Markdown
Contributor

What this does

Settlement stops being "merge a settle PR" and becomes a decision read from repository state. A release branch nobody touched produces no settle PR at all, and an explicit versioned workflow_dispatch tags the candidate PR's merge commit - the commit that already sits on the default branch - behind the review-gated publish environment. When the branch does carry fixes, today's settle PR remains and merging it is still the approval.

Shape

Behaviour Before After
Clean branch a dated entry re-committed, plus an --allow-empty settlement commit and a PR settled=false; identity, notes and PR steps all skipped
Tag placement always on the settle merge commit on the candidate merge commit when the branch is unchanged
Changelog heading dated at settle undated; the Release body is the tagged tree's section verbatim
Dispatch refreshed settle PRs only, never published publishes on clean/resume, refreshes otherwise, skips when already published
Stale entry undetectable --section-matches makes a stale section needs-settle-pr; publish refuses to tag one
Candidate drift nothing refreshed it stage: refresh merges the PR's own base (never rebases) and re-drafts
Credentials app credentials inside release repository scope; only the tag/Release and upload jobs sit behind publish
Lint L2 required environment: release exact file allowlist for the release workflows; L2' + unchanged L1/L3/L4/L6

Verification

Local only - no workflow has executed this code:

  • python3 -m unittest discover -s .github/actions/release-tools - 84 tests OK
  • python3 -m unittest discover -s .github/scripts - 85 tests OK
  • action_docs.py --check - documentation up to date
  • app_token_lint.py --repo my-repo workflow-templates/ - 5 files clean
  • route() driven end to end with the payload the route action emits: clean -> publish with pr_number, resume -> publish at the tagged SHA, open settle PR -> refresh, published -> skip, push -> never publish

Known gaps, deliberately not hidden

  • The plan's acceptance tests for the clean-state no-op, the publish verification and the refresh stage are not written yet (audit R1). This is why the plan's F1 audit still fails.
  • actions-test.yml has never run - no act on the authoring host.
  • No live release has been attempted: megaeth-labs/test-release-pipeline is unreachable (404), so cases A-D and the adversarial probes are unproven.
  • Route's dispatch path does not compute section_matches; a stale section there is refused loudly at publish, not routed to refresh.
  • The publish environment still needs its one required reviewer (owner console action).

Consumer impact

Nothing changes for a repo until it copies these templates. release-v2.3.0 and PR #2551 in mega-reth are untouched by this branch and publish through the existing marker path.

Adds settle_state(), the settle-state subcommand and the route dispatch mapping plus the sweep filter that keeps a tag-without-Release branch eligible. Unit tests run under unittest discovery.
Generates an undated note section, computes the settlement state before touching anything, and skips the ensure-PR step entirely when the branch is unchanged. Empty changelog_file is now legal.
Adds settle_source=dispatch, which verifies the merged candidate PR's merge SHA, head, dual base, author and live release-branch tip, re-running that whole check inside the tagging step. Resumes a tag whose branch has moved on. Publishes the changelog section verbatim.
A versioned dispatch now gathers the merged candidate PR (normalising an app login from app/<name> to <name>[bot]), the ancestry of its merge commit, whether a settle PR is open, the published tag SHA and whether a Release exists, and emits pr_number.
Adds stage: refresh, which merges the PR's own base and re-drafts the entry as a fast-forward push, plus the workflow job that refreshes trunk candidates only. Documents that a refresh clears approvals.
The settle publish job and on-release's binary job are the only jobs behind the review-gated publish environment; every PR-creating job reads the app credentials from repository scope and declares no environment.
Replaces L2's environment requirement with a file allowlist for the release workflow files and aligns L5, keeping L1, L3, L4 and L6 unchanged.
Rewrites the releasing guide and the shared action guide for the undated entry, the dispatch settlement, the publish environment and the candidate refresh.
Updates the shell fixtures and the template-copy tests for the new layout, and regenerates the action documentation catalogue.
… shell steps

A consumer that omits the newer inputs, or a harness that extracts these steps without the action input defaults, hit "SETTLE_SOURCE: unbound variable" under set -u. Default them at the top of both steps so an omitted input means the old pr behaviour.
@Troublor
Troublor merged commit d2a90ab into main Oct 28, 2026
13 checks passed
@Troublor
Troublor deleted the ci/release-settle-redesign branch October 28, 2026 12:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant