006 — The release is prepared in the story's pull request; main only takes a tag

Status: shipped (v0.4.1)

Why

Story 005 made tp release work on a protected main, but at the cost of a second pull request per story: the story's own PR, then a "Release vX.Y.Z" PR carrying the rolled CHANGELOG, each merged by hand, with tp release run twice around the second. gobank shipped v0.5.0 and v0.6.0 that way and asked for one PR and one review per story. The shape 005 named as a later option is the fix: the version heading lands in the story's own pull request, so once it is merged a release is only a tag.

What changes

  • tp release on a branch other than the base branch (the release remote's default branch, main unless the remote's HEAD says otherwise), in pull request mode, is the prepare run: steps 1 to 5 and 7 (dirty tree committed, version update, README markers, CHANGELOG rolled to the chosen version, WASM build) happen on that branch; it is pushed to the release remote; if no open pull request has it as head, one is opened against the base branch, titled by the release comment and bodied by the version's CHANGELOG section. No tag. Exit 0 with the PR URL.
  • Run again on the same branch (review changes), the prepare run sees the branch already carries that version's heading with no tag: it suggests that version, does not roll the CHANGELOG again, pushes, and reports the existing PR.
  • tp release on the base branch in pull request mode checks, in order: a merged release PR with no tag (005's second run, unchanged); a CHANGELOG on the remote base branch whose latest heading names a version with no tag (this story's tag run: fast-forward, confirm the heading, tag HEAD, steps 8 to 13); otherwise 005's first run, which cuts release/vX.Y.Z and opens a release PR, kept for a release with no story branch.
  • The tag run takes the version from the heading and the release comment from the section; neither is prompted for.

Acceptance

Branch Pull request mode state tp release
story branch no open PR from it prepare run: release commits on the branch, pushed, PR opened (title = release comment); exit 0; no tag; base untouched
story branch open PR from it prepare run: pushed; PR reported, not reopened
story branch, heading for vX already there, no tag any suggests vX, skips the CHANGELOG roll, pushes
base merged release PR, no tag 005 second run (tag, publish, release branch deleted)
base remote base CHANGELOG's latest heading untagged tag run: fast-forward, tag, publish; no branch, no PR
base remote base CHANGELOG's latest heading untagged, tree dirty error: commit or stash before tagging
base nothing merged or prepared 005 first run: release/vX.Y.Z and its PR

Out of scope

  • Merging the PR (the human's, as in 005).
  • Choosing a different version on the tag run than the heading names: edit the CHANGELOG in the story PR.
  • A tp pr command: the prepare run opens the story's pull request, so the roadmap's tp pr is subsumed.

Decisions

  • ADR 0002: the release is prepared in the story's PR and main only takes a tag, rather than a second release PR per story.
  • The base branch is the remote's default branch, read from refs/remotes/<remote>/HEAD, main when the clone has not recorded it; it is no longer "the branch tp release runs on".

Done when

  • tests express the acceptance table and pass
  • spec updated (docs/release-workflow.md)
  • ADR written if a fork was resolved (ADR 0002)
  • roadmap ticked and stamped; changelog entry
  • issue closed with a link to the release (v0.4.1)