Skip to content

ci: auto-cut a release when a new CHANGELOG version lands on main#9

Merged
REPPL merged 1 commit into
mainfrom
ci/auto-release-on-changelog
Jul 8, 2026
Merged

ci: auto-cut a release when a new CHANGELOG version lands on main#9
REPPL merged 1 commit into
mainfrom
ci/auto-release-on-changelog

Conversation

@REPPL

@REPPL REPPL commented Jul 8, 2026

Copy link
Copy Markdown
Owner

Auto-cut a release when a new CHANGELOG version lands on main

Implements release automation the reusable-workflow way (no PAT).

How it works

  • release.yml becomes callable (workflow_call + a required tag input) alongside its existing tag-push trigger.
  • New auto-release.yml (on: push: main): detect the newest dated CHANGELOG version → if it has no tag, tag it at github.sha (built-in token) → release by calling release.yml (uses: ./.github/workflows/release.yml). Calling it explicitly sidesteps GitHub's "a GITHUB_TOKEN-pushed tag doesn't trigger a workflow" rule — so no PAT, no standing credential.

Security (reviewed — PASS)

Every release.yml invariant is preserved: both jobs still check out github.sha, never the tag name (anti-tag-move); persist-credentials: false; the record-and-assert-remote-tip-unchanged tripwire; check-plan-shipped, build-provenance attestation (+ fail-closed verify — ferry is public), and prune. The derived TAG is only ever a name (version stamp / release title / prune), never a checkout ref. auto-release floors at contents: read, escalates only the tag job to contents: write (pushes a new vX.Y.Z only — can't move a tag or push a branch), and the version is regex-bounded to digits/dots (no injection). Idempotent: a no-op if the newest version is already tagged.

⚠️ Merging this cuts the v0.7.3 release

On merge (a push to main), the workflow sees the newest CHANGELOG version 0.7.3 untagged → tags v0.7.3 at HEAD → release.yml builds the four binaries + checksums.txt + provenance and publishes a public GitHub Release. That's the intended first cut. Every future CHANGELOG-bumping merge then releases hands-free.

Backlog note (by design)

v0.7.0v0.7.2 stay untagged — auto-release only ever tags the newest version, because tagging older versions at the current HEAD would permanently mis-point immutable tags at v0.7.3's code. They were same-day dev milestones superseded on main. If you want their tags for history, I can create them at their real merge commits as a one-time manual step.

Known operational limit (not a regression)

If a release run fails verification, the tag is already pushed and that version won't auto-retry — delete the remote tag to retry. This mirrors ferry's existing manual tag-push model.

Assisted-by: Claude:claude-opus-4-8

Make release.yml callable via workflow_call (a required 'tag' input) in addition
to its tag-push trigger, and add auto-release.yml which, on a push to main, tags
the newest un-released CHANGELOG version and invokes release.yml to build and
publish it — no PAT, using the built-in token (a GITHUB_TOKEN-pushed tag would
not trigger the tag event, so release.yml is called explicitly instead).

release.yml's security posture is preserved: both jobs still check out github.sha
(never the tag name), persist-credentials stays false, the no-branch-push tripwire
and check-plan-shipped/attestation/prune gates are unchanged; the derived TAG is
only ever a name (version stamp, release title, prune), never a checkout ref.

auto-release tags only the NEWEST version (tagging the backlog at HEAD would
mis-point immutable tags at the wrong code), is idempotent (no-op if that version
is already tagged), and floors permissions at contents: read, escalating only the
tag job to contents: write and granting the release call exactly the write scopes
release.yml needs.

Security-reviewed: PASS (anti-tag-move, tripwire, permission capping, injection,
token, fail-closed attestation, idempotency all verified).
@REPPL REPPL merged commit b8d0369 into main Jul 8, 2026
12 checks passed
@REPPL REPPL deleted the ci/auto-release-on-changelog branch July 8, 2026 14:35
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