Skip to content

feat(release): overhaul release process — manual dispatch with auto-bump suggestion#12

Merged
j7an merged 2 commits intomainfrom
feat/publish-github-release
Apr 11, 2026
Merged

feat(release): overhaul release process — manual dispatch with auto-bump suggestion#12
j7an merged 2 commits intomainfrom
feat/publish-github-release

Conversation

@j7an
Copy link
Copy Markdown
Owner

@j7an j7an commented Apr 11, 2026

Summary

Overhauls the release process so a release happens on an operator's cadence, not per-merge. Two related changes landing together:

  1. auto-tag.ymltag-release.yml — trigger switches from "every merged PR" to workflow_dispatch with a bump dropdown (auto | patch | minor | major, default auto). Merged PRs batch on main until an operator clicks Run workflow.
  2. release.yml — gets a new Publish GitHub Release step that fires on every v*.*.* tag push (idempotent via gh release view pre-check). Also renames display name to Publish Release. Filename unchanged to preserve any external references.

The conventional-commit heuristic (feat: → minor, BREAKING CHANGE → major, else patch) is preserved — it powers the auto default. Explicit picks override it; the step summary shows a warning when the override contradicts the analysis.

Why

Release-per-merge was wasteful. A week of 4 dependabot PRs used to become 4 tags, 4 Releases, 4 floating-tag force-pushes. The semver contract (bumps are deliberate compatibility statements) got diluted into "every merge is a patch."

Empty Releases page (separate defect, same logical fix): 7 pre-existing semver tags had zero corresponding GitHub Releases. Backfilled out-of-band during implementation — all 7 Releases now live at https://github.com/j7an/shared-workflows/releases with original tag dates in titles and notes banners.

Design doc

docs/superpowers/specs/2026-04-11-release-process-overhaul-design.md — full design, failure modes, rationale for manual dispatch over release-please / semantic-release, and backfill approach.

Files changed

  • .github/workflows/auto-tag.yml.github/workflows/tag-release.yml — renamed and rewritten (content similarity <50% so git shows delete+add)
  • .github/workflows/release.yml — new Publish GitHub Release step, display name renamed to "Publish Release"
  • docs/superpowers/specs/2026-04-11-release-process-overhaul-design.md — new design spec

Safety gates in tag-release.yml

  • if: github.ref == 'refs/heads/main' at job level — refuses to run from non-main branches (workflow_dispatch lets the operator pick any branch)
  • concurrency.group: tag-release with cancel-in-progress: false — serializes parallel dispatches instead of killing in-flight ones (a half-cancelled tag-push is worse than a queued second dispatch)
  • Empty-delta guard — explicit error if no commits since last tag
  • permissions: contents: write — minimum scope for tag push

Test plan

  • Ran the analysis logic locally against v1.2.4..HEAD on this branch — correctly picked minor from the feat(release): commit
  • Backfilled all 7 pre-existing semver tags (v1.0.0v1.2.4) via local gh loop; v1.2.4 correctly got the "Latest" badge from GitHub's semver ordering
  • Post-merge validation (single manual dispatch proves the entire flow end-to-end):
    1. Merge this PR
    2. Actions → Tag ReleaseRun workflow → leave bump=autoRun
    3. Workflow should compute v1.3.0 (minor, driven by this PR's feat: commit)
    4. release.yml should fire automatically on the tag push
    5. v1.3.0 Release should appear on the Releases page with auto-generated notes
    6. Floating v1 and v1.2 tags should force-push to v1.3.0
  • Post-merge: confirm auto-tag.yml no longer appears in .github/workflows/ and no Auto-Tag on Merge runs are scheduled

Rollback plan

If the new flow misbehaves:

  1. git revert this PR's merge commit on main
  2. git push origin :v1.3.0 (or whatever tag was created)
  3. gh release delete v1.3.0

Everything is reversible in under a minute.

j7an added 2 commits April 11, 2026 10:45
release.yml already fires on v*.*.* tag push to update the floating
v1/v1.2 pointers; extend it to also publish a GitHub Release via
`gh release create --generate-notes --verify-tag`, with an idempotent
pre-check so re-runs (or manual tag re-pushes) don't error.

Rename the workflow from "Update Floating Version Tags" to "Publish
Release" — the file stays release.yml to preserve any external
references, only the display name and job id change to reflect the
broader responsibility.

Also commit the design spec under docs/superpowers/specs/ documenting
the rationale, failure modes, and the GitHub API limitation that
prevents retroactive `published_at` timestamps on backfilled Releases.
…ump suggestion

Two orthogonal-but-related changes landing together:

1. Replace merge-triggered tagging with operator-initiated dispatch.
   `auto-tag.yml` → `tag-release.yml`, trigger switches from
   `pull_request.closed` → `workflow_dispatch` with a `bump` choice input
   (auto/patch/minor/major, default auto). Merged PRs accumulate on main
   and ship in one coherent release when the operator decides, rather
   than one release per merge.

   The conventional-commit heuristic (feat → minor, BREAKING → major,
   else patch) is preserved — it now powers the `auto` default. Explicit
   picks override the heuristic; the step summary flags the override so
   mismatches are visible.

   Safety gates: `if: github.ref == 'refs/heads/main'` at job level,
   `concurrency.group: tag-release` with `cancel-in-progress: false`,
   explicit error + step summary when no commits exist since the last
   tag (no ghost releases).

2. Publish GitHub Release on every `v*.*.*` tag push.
   `release.yml` (display name renamed to "Publish Release") gains a
   final `gh release create --title --generate-notes --verify-tag` step,
   idempotent via a `gh release view` pre-check. Fires regardless of how
   the tag got there (tag-release.yml dispatch, manual push, backfill
   loop, future migrations).

Backfill of the 7 pre-existing semver tags (v1.0.0 → v1.2.4) was executed
out-of-band via a local `gh` loop — not committed as a workflow, since it's
a one-time operation and a dedicated file would sit unused afterward.

Design spec added at
docs/superpowers/specs/2026-04-11-release-process-overhaul-design.md.
@j7an j7an changed the title feat(release): publish GitHub Release on every semver tag push feat(release): overhaul release process — manual dispatch with auto-bump suggestion Apr 11, 2026
@j7an j7an merged commit 8cfed1d into main Apr 11, 2026
2 checks passed
@j7an j7an deleted the feat/publish-github-release branch April 11, 2026 18:08
j7an added a commit that referenced this pull request Apr 12, 2026
feat(release): overhaul release process — manual dispatch with auto-bump suggestion
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