Retry the release attach, and stop signatures outliving their files - #18
Merged
Conversation
`gh release upload` sends each file in turn and gives up on the first
rejection with part of the set already attached. A single HTTP 502 from
api.github.com did exactly that to v0.5.0:
HTTP 502: Server Error (.../releases/assets/545028939)
PyPI had the package, and the release page kept the sdist and every
`.sigstore.json` while losing the wheel and the SBOM -- so it carried
signatures for two files it did not have. A signature beside no artifact
is worse than an empty release: it reads as something published and
verified that is merely hard to find.
The attach is retried with backoff now. Uploading is idempotent under
`--clobber`, so the whole set is simply sent again rather than
reconstructed, and the job fails with nothing half-done that a reader
would mistake for complete.
The repair path gains the same retry, and drops an SBOM signature whose
SBOM is gone. Repair deliberately does not rebuild one -- today's
dependency closure is not the release's -- so the signature has nothing
left to sign, and absent is the honest state. A release holding both is
left alone.
`sign-and-upload` now checks out, for the attach script only, with no
credentials persisted. It was deliberately checkout-free so that nothing
fetched from a registry runs beside the signing identity; a script from
the repository under a credential-less checkout does not reintroduce
that.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dhi1SLuFiEseRhH9iLMv8Q
This was referenced Sep 4, 2026
Retry the release attach, and stop signatures outliving their files
provide-io/provide-foundation#14
Merged
Merged
Merged
Retry the release attach, and stop signatures outliving their files
provide-io/pyvider-components#16
Merged
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
v0.5.0 shipped to PyPI and then lost half its release page to a single transient error:
gh release uploadsends each file in turn and gives up on the first rejection, with part of the set already attached. The release kept the sdist and every.sigstore.json, while losing the wheel and the SBOM — so it carried signatures for two files it did not have.That is worse than an empty release. A
.sigstore.jsonbeside no artifact reads as something published and verified that is merely hard to find.What changes
The attach is retried with backoff. Uploading is idempotent under
--clobber, so the whole set is resent rather than reconstructed piecemeal. Uploading each file in its own command would still leave a partial set when the retries ran out; this way the release either gets everything, or the job fails with nothing half-done that a reader would mistake for complete.The repair path gains the same retry, and drops an orphaned SBOM signature. Repair deliberately does not rebuild an SBOM — today's dependency closure is not the release's, and an SBOM confidently wrong about what shipped is the failure this ecosystem has already had once. That reasoning is unchanged and left in place. But it means a partially-failed run leaves a signature with nothing to sign, and absent is the honest state. A release holding both is left alone.
sign-and-uploadnow checks out, for the attach script only, withpersist-credentials: false. It was deliberately checkout-free so nothing fetched from a registry runs beside the signing identity; a script from this repository under a credential-less checkout does not reintroduce that, and the comment says so.Both scripts live in
scripts/, not inline in the YAML.Not fixed here
sbom-python.cdx.json.sigstore.json. The repair path restored the wheel — verified byte-identical to PyPI by sha256 — but cannot restore the SBOM. Re-running repair once this merges will drop the stray signature.release.ymlis duplicated across the provide-io Python repositories. The same single-shot attach is in every one of them, so every one can lose part of a release to one 502. This PR fixes the repository where it actually happened; the others want the same change.🤖 Generated with Claude Code
https://claude.ai/code/session_01Dhi1SLuFiEseRhH9iLMv8Q