Skip to content

feat(release-prep): manually-triggered GHA workflow to draft prep PRs#110

Merged
be0x74a merged 7 commits into
mainfrom
feat/release-prep-workflow
Jun 3, 2026
Merged

feat(release-prep): manually-triggered GHA workflow to draft prep PRs#110
be0x74a merged 7 commits into
mainfrom
feat/release-prep-workflow

Conversation

@be0x74a
Copy link
Copy Markdown
Member

@be0x74a be0x74a commented Jun 3, 2026

What this adds

A manually-triggered GHA workflow that opens a "release: vX.Y.Z prep" PR — modeled exactly on PR #105 (the v0.3.2 prep). The workflow does the mechanical work (CHANGELOG section insertion, Chart.yaml bump, doc version-string bumps, categorized PR-list comment). The human keeps every judgment call: whether to release, what version, what CHANGELOG prose, and the tag push after PR merge.

Why

Every release so far has involved the same hand-work: bump six files, write a section header, look through merged PRs to draft notes. Automating it removes the friction without surrendering the editorial decisions. Concretely, the workflow:

  • Proposes via PR, doesn't cut end-to-end. Preserves the no-direct-push-to-main invariant and gives a review checkpoint on the CHANGELOG prose.
  • Bump via dropdown (patch | minor | major) rather than typed version string — computes the next tag from the latest stable one.
  • Drafts the CHANGELOG scaffold + PR-list comment, not the prose. Each merged PR is grouped by conventional-commit prefix (feat/fix/build(deps)/chore(deps)/docs/refactor/test/ci/build/chore/other) including !: breaking-change variants.
  • Soft-warns when every PR since last tag is deps-only. Doesn't block — a security-bump release is exactly the legitimate case for a deps-only patch — but surfaces the question.
  • Dry-run is the default. Defaults are safe; you opt into pushing.

What stays manual (deliberately)

  • Whether to release (you read the PR-list preview, decide).
  • The CHANGELOG prose (workflow leaves empty Added/Changed/Fixed scaffolds).
  • The merge decision (PR review like any other).
  • The tag push (git tag vX.Y.Z main && git push origin vX.Y.Z) — existing release.yml + helm-release.yml publish from the pushed tag, unchanged.

Architecture

  • .github/workflows/release-prep.ymlworkflow_dispatch orchestrator (59 lines)
  • hack/release-prep.sh — single-file logic, runnable locally for debugging (322 lines)

Workflow grants contents: write (push the release/v*-prep branch) + pull-requests: write (open PR + comment). Never writes to main.

Safety guardrails baked in

  • Tag collision check against origin — protects against the goreleaser force-retag failure mode.
  • "HEAD at latest tag" refusal — nothing merged means nothing to release.
  • Strict > boundary on gh pr list --search "merged:>$latest_tag_date" — excludes the prior release-prep PR (whose mergedAt matches the tag commit's date).
  • sed_strict fail-on-no-match — any expected doc-version-string pattern that doesn't match aborts the run. Drift in install pins is caught loudly.
  • Branch-already-exists refusal in live mode — operator must explicitly delete origin's release/v*-prep before re-cutting.

Verification

Static checks: YAML parses; bash -n clean on the script.

Local dry-run against current main (latest tag v0.3.2, 4 PRs merged since: #106#109, all build(deps)):

latest tag: v0.3.2
next tag:   v0.3.3 (bump=patch)
PRs merged since v0.3.2 (2026-05-19T00:18:47+02:00):
  found 4 PR(s)

===== PR comment (dry-run preview) =====
## PRs merged since v0.3.2

> [!WARNING]
> All PRs since the last tag are dependency bumps. Consider whether this release
> is warranted — per Keep a Changelog, transitive bumps have no user-facing
> effect and are typically omitted from the CHANGELOG. If you're cutting this
> patch specifically because of a security advisory in a bumped dep, say so
> in the `### Changed` section below.

### build(deps)
- #109 — build(deps): bump docker/setup-qemu-action from 4.0.0 to 4.1.0 in the gh-actions group
- #108 — build(deps): bump github.com/prometheus/common from 0.67.5 to 0.68.0 in the go-deps group
- #107 — build(deps): bump the gh-actions group with 4 updates
- #106 — build(deps): bump the pip group across 1 directory with 2 updates
===== end preview =====

The file mutations match PR #105's diff shape modulo target version — CHANGELOG scaffold above ## [0.3.2], Chart.yaml version/appVersion bumped, charts/projection/README.md image tag bumped, README.md + docs/getting-started.md --version and install.yaml URLs bumped, docs/security.md both cosign verify lines bumped. PR #105 reference: 6d350cf.

Sample of the CHANGELOG mutation:

+## [0.3.3] - <today>
+
+### Added
+
+### Changed
+
+### Fixed
+
 ## [0.3.2] - 2026-05-18

What this PR does NOT cover

  • Live-mode integration test. workflow_dispatch workflows aren't triggerable from a non-default branch, so the first real release cut after this merges IS the integration test. The risk surface is small: live mode is a mechanical cp of the same $workdir files that dry-run diffs against, so a CI-only divergence is unlikely.
  • release label auto-creation. gh pr create --label release will fail the first time if the label doesn't exist on the repo. One-off gh label create release --color BFD4F2 solves it.
  • Documentation of the end-to-end release ritual. Worth a follow-up RELEASING.md once the workflow has been exercised live once.

How to use, once merged

  1. Go to Actions → "Release prep" → "Run workflow"
  2. Pick the bump (patch/minor/major)
  3. Leave dry_run on true the first time — read the step summary, confirm the diff and PR comment look right
  4. Re-run with dry_run: false to actually open the prep PR
  5. Edit the CHANGELOG prose in the prep PR, merge
  6. git tag vX.Y.Z main && git push origin vX.Y.Z — existing release pipeline takes over

@be0x74a be0x74a merged commit f105668 into main Jun 3, 2026
15 checks passed
@be0x74a be0x74a deleted the feat/release-prep-workflow branch June 3, 2026 20:15
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