Wait up to 5.5 hours for reviewer-approved publishes before the GitHub release

Draft
JE
15d ago
+70-10

release-github.yml now waits up to 5.5 hours for the release workflows, instead of the shared orchestrator's 30 minutes, because release-crates requires a reviewer from sip or cli. This ports basecamp/fizzy-sdk#201's approach (at 8896f5e).

Why: release-crates requires approval now (sip or cli, with self-review prevented), but release-github.yml called basecamp/sdk/actions/release-orchestrate with its default timeout: 1800. An approval that came after 30 minutes failed the GitHub release even though the crate published.

What changes

  • A new "Wait for release workflows" step does the waiting:
    • It makes one request per poll: actions/runs?head_sha=<tagged commit>&event=push. The shared action makes one or two gh run list requests per language per poll. Over hours that outruns GITHUB_TOKEN's 1,000 requests an hour.
    • Each language's run is matched by path with any @ref suffix stripped, plus head_branch == <tag>, newest first.
    • Long wait: it waits up to 19,800s (5.5 hours), and the job gets timeout-minutes: 340.
    • Transient-error retry: a failed listing logs a warning and retries on the next poll instead of ending the wait.
    • It stops early on the first failed run.
  • The shared action still creates the release, now with timeout: '1' and poll-interval: '1', so it takes a single pass after the wait. Release creation (--generate-notes --latest), the failure summary and the recovery advice stay shared with the other SDK repos. Nothing else about it changes.
  • Manual dispatch still works. The step polls the commit the tag was checked out at, not GITHUB_SHA. That keeps gh workflow run release-github.yml -f tag=vX.Y.Z working as the recovery path. fizzy-sdk#201 skips the wait on dispatch; hey-sdk's dispatch already relies on the shared action seeing the tag's push runs, so this keeps that.
  • CONTRIBUTING.md and the release-rust.yml comment said release-crates has "no required reviewers". They now say what it is: approval by sip or cli, not by whoever pushed the tag, and that a late approval needs a re-run of the orchestrator.

Not in this PR

  • release-go, release-npm and release-github-packages already exist with the same reviewers and the same v* policy, but no workflow references release-go or release-github-packages yet. Gating the Go module tag and the Kotlin publish the way fizzy-sdk does is a separate change. release-npm is used, but TypeScript publishing is off (.github/typescript-publish-enabled is false).
  • The shared action's own polling. Fixing its per-language loop in basecamp/sdk would cover every SDK repo at once and would make the inline step unnecessary. That's a cross-repo call, so I left it for whoever owns basecamp/sdk.

Verified

  • actionlint and zizmor --offline find nothing in release-github.yml.
  • I ran the run-matching jq against the real runs for v0.32.1. All five release workflows matched as success, and the main push runs on the same commit were ignored.
  • typescript/tests/release-workflow.test.ts's assertions on release-github.yml still hold: workflow_sha, release-languages.sh and the languages: input are unchanged.
  • The wait step only runs on a tag push or a dispatch, so this PR's CI can't exercise it. The first real exercise is the next tag.

Summary by cubic

Waits for reviewer-approved publish workflows before creating the GitHub release, instead of the shared orchestrator's 30-minute timeout.

  • release-github.yml polls the tag's push runs every 30 seconds for up to 5.5 hours, stopping early on the first failed run or when all succeed.
  • The shared release-orchestrate action now runs a single pass with timeout: '1' and poll-interval: '1'; it still reports failures and creates the release.
  • Manual dispatches poll the tag's commit, so gh workflow run recovery still works.
  • Updated CONTRIBUTING.md and the release-rust.yml comment to describe release-crates's approval requirement (reviewer from sip or cli, not the tag's author) and how to handle approvals arriving after the wait ends.