Make release-orchestrate's recovery advice match what it can see

Merged
JE
2mo ago
+710-88

release-orchestrate polls each release-<lang>.yml with gh run list --event=push and matches the tag by headBranch. When a language fails it told the operator to gh workflow run release-<lang>.yml — a workflow_dispatch run the poller filters out by construction, and one every seed release-<lang>.yml.tmpl treats as a dry-run rehearsal. Following the advice publishes nothing and the orchestrator times out. MAKEFILE-CONVENTION.md § Failure Recovery gave the same instruction.

What changes

  • The recovery message now names the runs that failed and the command that works on them: gh run rerun <id> --failed (same run, same push event, so the poller sees it), followed by re-running the orchestrator. Languages that never produced a push run are reported separately from ones that failed, with a note that a dispatch is invisible here and that a re-run executes the workflow file as of the tag.
  • MAKEFILE-CONVENTION.md § Failure Recovery says the same.
  • The logic moves from an inline run: to orchestrate.sh, fed by env: instead of ${{ inputs.* }} template expansion (zizmor: the action goes from 5 template-injection findings to none). Inputs are unchanged.
  • languages accepts rust (it always accepted any <lang> with a release-<lang>.yml; the description says so now). Entries are whitespace-trimmed; an empty list or an entry that cannot name a workflow fails immediately instead of polling release-.yml for 30 minutes.
  • A transient gh run list failure is logged as a warning and retried, rather than silently read as "no run yet".
  • bats actions/release-orchestrate/test runs the script against a stubbed gh (15 cases): success, polling until a run completes and no re-querying of languages that already succeeded, failure with run ids, a workflow_dispatch run being invisible both alone and next to a failed push run, timeout, a still-running run at timeout, transient gh errors, v-prefix handling, languages parsing, and a failed gh release create.

Consumer reach

Referenced live at @main by hey-sdk (release-github.yml, languages: go) and by the seed's release-github.yml.tmpl. For hey-sdk the happy path is byte-for-byte the same gh run list query and the same gh release create v<x> --title v<x> --generate-notes --latest; outputs (status, release-url) keep their names and values. What hey-sdk would see differently: a failure now prints usable recovery text, and a malformed languages value fails fast. $GITHUB_ACTION_PATH is set for composite actions, so the subpath reference resolves to the same checkout the action ran from.

Gates

No workflows run in this repo. Locally: bats actions/release-orchestrate/test 15/15, shellcheck clean on the script and stubs, zizmor actions/release-orchestrate no findings.

Part of the Rust seed work — templates for seed/rust/** and release-rust.yml.tmpl come separately once the basecamp-sdk crate lands.