010 — Goreleaser preflight before the push (#33)

Status: shipped (v0.7.0)

Why

Two releases in two days tagged, pushed to every remote, and then failed in goreleaser: pta2svg because .goreleaser.yaml had no release: block so goreleaser defaulted to GitHub, where the repo does not exist (#33); godocs-watcher because no token reached goreleaser, the project having no task-plus.local.yaml and so no secrets_provider (#34). Both faults were knowable before anything was pushed — the target mismatch was even printed as a warning — but tp release only finds out when goreleaser runs, which is after the rollback boundary, so the person is left to publish the assets by hand. tp release -dry-run reports success in both states.

What changes

  • A goreleaser preflight in the check phase of tp release (after the deploy validation, before Execute), run whenever goreleaser will run, dry-run included. It reads .goreleaser.yaml and compares it with the release remote; any finding aborts the run with the fix spelled out. Findings: the release target's forge differs from the release remote's; release.<target>.owner/name differ from the remote, or are missing when the release remote is not origin (goreleaser infers them from origin); for a Forgejo target, gitea_urls.api/download missing or on another host; the token goreleaser will read is empty — GITHUB_TOKEN, GITLAB_TOKEN, or for Forgejo GITEA_TOKEN and the release remote's token_env chain. The token message says when secrets_provider is not configured, since that is why the vault was never asked.
  • tp check, Goreleaser section: the same config findings as errors, the token finding as a warning (it depends on the shell), checked against the release remote rather than any configured remote.
  • The post-push "goreleaser publishes releases to X but the release remote is Y" warning goes: the preflight has already failed the run.
  • docs/release-workflow.md (phase 4), README.md (goreleaser config for a Forgejo release remote).

Acceptance

Release remote origin is https://git.bytestone.uk/hum3/proj.git (Forgejo) unless stated. "Aborts" means tp release stops before Execute and tp check reports an error.

.goreleaser.yaml Shell Outcome
no release: block — aborts: publishes to github, remote is forgejo
release.github — aborts: publishes to github, remote is forgejo
release.gitea hum3/proj, gitea_urls on git.bytestone.uk, GITEA_TOKEN set passes
same, no GITEA_TOKEN BYTESTONE_FORGEJO_TOKEN set (token_env) passes: tp passes it as GITEA_TOKEN
same neither set, no secrets_provider aborts: names both variables, says secrets_provider is not configured
same neither set, secrets_provider: bitwarden aborts: names both variables
release.gitea hum3/proj, no gitea_urls token set aborts: gitea_urls.api and .download missing, wants https://git.bytestone.uk/api/v1 and https://git.bytestone.uk
gitea_urls.api on codeberg.org token set aborts: host differs from the remote
release.gitea other/proj token set aborts: owner differs from the remote
release.gitea with no owner/name, release remote is origin token set passes: goreleaser infers from origin
release.gitea with no owner/name, release remote is forgejo (not origin) token set aborts: owner/name missing
release remote github is git@github.com:drummonds/proj.git, release.github drummonds/proj GITHUB_TOKEN set passes
same GITHUB_TOKEN unset aborts: GITHUB_TOKEN unset
any of the above, -dry-run — same outcome: dry-run no longer reports success
goreleaser declined or not a binary project — preflight skipped

Out of scope

  • Writing the release:/gitea_urls block (tp check --setup or an init command): tp never rewrites .goreleaser.yaml; the message shows the block to paste.
  • force_token: gitea in the file: tp release already forces GORELEASER_FORCE_TOKEN to the target, so the file need not.
  • Reading secrets_provider from a per-machine file so the token is there in the first place: story 011 (#34).
  • Unrelated dirty files swept into the release commit: #35.

Decisions

None — no fork; the hard stop is what #33 asks for.

Done when

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