020 — Plan-first ask: the release shows every default and asks once (#77)

Status: shipped (v0.25.0) Roadmap: #77

Why

The Ask phase of tp release is an interview: version, comment, then a yes/no for each publishing step, each with a default that is almost always taken. A release is eight or nine Enters, and the plan is only shown once the last question is answered — so a wrong answer early (the version, say) is found late. The run should lead with the plan it would execute, with every default filled in, and ask one question: proceed, stop, or edit. Only the edit path walks the questions one by one, as the interview does today.

What changes

  • tp release Ask: every default is decided up front — version (suggested), comment (--comment > [Unreleased] summary bullet > .tp-release-comment), roadmap items counted done, and each publishing step that applies to the project (push, goreleaser, PyPI, cleanup, install, deploy). The plan is printed, then one prompt: Proceed? [Y/n/e].
    • Y (or Enter) executes the plan as shown.
    • n ends the run with nothing done, exit 0, "Nothing done."
    • e walks the questions one by one, each defaulting to its value in the plan; the plan is printed again and the prompt repeats.
  • The plan lists each publishing step that applies, as yes or no, so a step declined in the walk is visible rather than merely absent. Steps fixed by config (install:, pypi: true) and derived steps (post-release commands) are shown as before and not asked.
  • --yes accepts the plan without the prompt, as it accepted every default before.
  • Pull request mode's prepare run (no merge_wait) keeps its two questions — version and comment — in the walk; the plan and prompt are the same.
  • internal/prompt: ConfirmDefault(msg, def) (a yes/no whose default may be no) and Proceed(msg) (yes / no / edit).
  • docs/release-workflow.md Ask section and flowchart; README's --yes line.

Acceptance

--yes Answer to Proceed? Walk answers Outcome
yes not asked — plan with every default; Check and Execute follow
no Y or Enter — plan with every default; Check and Execute follow
no n — "Nothing done.", exit 0; no commit, push, tag or pull request
no e Enter to each plan unchanged; prompt repeats; Y proceeds
no e push n plan shows Push: no; Y proceeds without pushing
no e version v0.3.0 plan shows Version: v0.3.0
no e then e push n, then Enter second walk defaults push to no; it stays no
no e version nonsense error, as today
no EOF — as n
no other text — prompt repeats
Step Applies when Default Asked in the walk
Version not fixed by a prepared or merged release suggested yes
Comment always --comment > [Unreleased] bullet > saved file yes
Roadmap #N done item's stories all shipped yes yes, one per item
Push always; fixed yes on a prepare run without merge_wait yes yes
Goreleaser binary project with .goreleaser.yaml yes yes
PyPI Python project, package named, pypi: unset yes yes
PyPI pypi: true yes no
Cleanup releases to delete on a forge yes yes
Install binary, release:install task, with install: unset yes yes
Install install: set its value no
Deploy docs pages_deploy here or in the docs sibling yes yes
Post-release post_release set and pushing derived no

Out of scope

  • Editing a single step by name (e push): the walk is linear.
  • A -prepare run (#80) and timings (#76).
  • Changing which steps exist or their order (#46).

Decisions

  • n ends the run rather than meaning "skip every step": a plan the human will not execute as shown is edited or abandoned, and the previous way to abandon was Ctrl-C.
  • After a walk the plan is shown again and the prompt repeats, so the walk's effect is confirmed the same way as the defaults.

Done when

  • tests express the acceptance table and pass
  • spec updated (docs/release-workflow.md, README)
  • changelog entry
  • issue closed with a link to the release