Skip to content

fix: reject reuse of a failed release publication run at closeout - #1319

Merged
jeremi merged 2 commits into
mainfrom
fix/publish-closeout-identifiers
Sep 23, 2026
Merged

jeremi merged 2 commits into
mainfrom
fix/publish-closeout-identifiers

Conversation

@jeremi

@jeremi jeremi commented Sep 23, 2026

Copy link
Copy Markdown
Member

Problem

release/OPERATIONS.md's failure-handling table said that when identifier
dispatch, deployment, or live smoke fails after publication, rerunning
registry-release publish --plan <candidate-plan.json> --wait makes the
already-public release "take the exact closeout path and republish the
same tag, source commit, and catalog digest." That is not what the tool
does, and the doc's claim is false for a run whose identifier-catalog job
failed.

Evidence

For v0.33.0, release.yml run 35766749442 succeeded overall except the
publish-identifiers job ("Publish exact identifier catalog"). Rerunning
registry-release publish --plan <candidate-plan.json> --wait did not
dispatch a new release.yml run and did not redeploy identifiers: it
reattached to run 35766749442, waited for the (successful) docs run, ran
verify-public, and printed status: complete with exit 0. The only thing
that actually recovered the identifier catalog was gh run rerun 35766749442 --failed.

Root cause

In release/scripts/registry-release, publish_candidate_plan's
already-published branch looks for an active (in-progress) publication run
first. When none is active, it calls reusable_docs_publication_run to find
the latest release.yml run correlated to a healthy docs-pages.yml run,
and reuses that pairing without ever checking the publication run's own
status/conclusion. Since verify_public_release.verify() only checks the
GitHub Release, its tag, and the published images, and the identifier catalog
is published by a separate publish-identifiers job on that same release.yml
run, a release.yml run that failed overall (because that job failed) but
whose docs job still succeeded was accepted as "reusable" and the whole
operation was reported complete.

Fix

reusable_docs_publication_run now raises ReleasePlanError naming the run
and the exact recovery command when the correlated publication run completed
with a non-success conclusion, instead of silently treating it as reusable.
This mirrors the same function's existing invariant checks (e.g. the
"resolved to multiple workflow runs" raise) and does not change behavior for
the already-tested case where no docs run exists at all for a failed
publication run. release/OPERATIONS.md's failure-handling row is corrected
to describe what the tool does: recover the bound release.yml run directly
with gh run rerun <run> --failed, then rerun publish --wait to verify.

No new gates or workflows were added; this only makes an existing check
honest about a run it was already inspecting.

Verification

Added two unit tests to release/scripts/test_registry_release.py, written
first to confirm they fail against the old code:

  • test_docs_recovery_rejects_reuse_of_failed_publication_run: calls
    reusable_docs_publication_run directly with a failed publication run
    paired with a healthy docs run, and expects ReleasePlanError naming the
    run ID and gh run rerun 88 --failed.
  • test_publish_reports_failed_publication_run_instead_of_false_completion:
    drives publish_candidate_plan end to end for an already-published release
    in this exact shape, and expects exit 1 with the recovery command on
    stderr, and no docs or publication redispatch.
python3 -m unittest release/scripts/test_registry_release.py

Ran 97 tests, all passing, clean output.

Test plan

  • python3 -m unittest release/scripts/test_registry_release.py (97 passed)
  • New tests fail against the pre-fix code and pass after the fix

Publishing an already-public release picked the latest workflow_dispatch
release.yml run correlated to a healthy docs run and reused it without
checking its own conclusion. A publication run whose overall conclusion
was failure (for example because its identifier catalog job failed
downstream of a successful docs deployment) was silently treated as
reusable, so `registry-release publish --plan ... --wait` reported
status complete and exit 0 without redispatching anything.

Raise instead, naming the run and the exact recovery command
(`gh run rerun <run> --failed`), when the correlated publication run
completed with a non-success conclusion. Update the OPERATIONS.md
failure-handling row, which claimed the closeout path republishes the
tag, source commit, and catalog digest; it never redispatches
release.yml, so the accurate recovery is to rerun the failed run
directly.

Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
@jeremi
jeremi merged commit 037767d into main Sep 23, 2026
42 checks passed
@jeremi
jeremi deleted the fix/publish-closeout-identifiers branch September 23, 2026 01:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant