008 — Release waits for the merge and completes in one run (#31)

Status: shipped (v0.5.0)

Why

In pull request mode a release is two tp release runs (ADR 0001): one opens the pull request, a human merges it, and a second run on main tags and publishes. For a one-person project the human is the same person who ran the first command: the merge is a click in the forge within a minute or two, and the second run is pure ceremony — switch to main, pull, type tp release again, answer the publishing questions. Forgetting it leaves a merged version heading with no tag until the next release notices. gobank and task-plus hit this on every release since story 005.

What changes

  • merge_wait: 10m in task-plus.yml (a Go duration; absent or 0 keeps the two-run behaviour). With it set, a tp release that opens or updates a pull request stays running and polls the forge every 15 s for up to that long.
  • The publishing questions (push, goreleaser, cleanup, install, deploy) are asked before the pull request is opened, so the tag happens unattended once the merge lands. The plan summary names the wait.
  • Merged in time: the run fetches, checks out the base branch (the story branch case), fast-forwards, runs the check commands again on the merged base branch, then does exactly what the tag run does: tag, publish, steps 7 to 13, release branch deleted.
  • Not merged in time, closed without merging, or Ctrl-C during the wait: the run ends as it does today, pull request URL printed, nothing tagged, exit 0. A later tp release on the base branch is still the tag run.
  • internal/forge: GetPullRequest(number) on the Forgejo repo.
  • docs/release-workflow.md gains a "Waiting for the merge" section; README.md names the key.

Acceptance

merge_wait Run During the wait Outcome
unset any — as before: two runs
set release PR opened from the base branch merged same run: fast-forward, tag, publish; release branch deleted; released = true
set story PR opened or updated from the story branch merged same run: checkout base, fast-forward, tag, publish; work ends on the base branch
set either still open at the deadline PR URL printed; nothing tagged; exit 0; next run on base is the tag run
set either closed without merging says so; nothing tagged; exit 0
set either Ctrl-C stops waiting; PR stays open; exit 0
set either forge unreachable on a poll retried until the deadline; the error is reported with the timeout
set either, merged check fails on the merged base error naming the merged PR; the next run on base tags it
set --dry-run — says it would wait; no polling

Out of scope

  • Waiting on a run that only finds an existing open release PR (PendingPR): it prints the URL and exits as before. That path has no Ask phase, so the publishing questions would need a home first.
  • Waiting for CI on the pull request, or merging it: the human merges.
  • A --wait flag: the setting is per project, where the merge habit lives.

Decisions

ADR 0003: a bounded, opt-in wait on top of the two-run model, not a return to one run that waits indefinitely.

Done when

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