ci(jfrog): refuse to overwrite a published version - #76
Merged
Merged
Conversation
lab-npm-*-local are mutable - blackedOut is false and no repository immutability setting exists on an Artifactory local repo, all 64 config fields checked. Re-publishing a version overwrites the bytes silently, including a version already promoted with status Released. That happened during the evaluation: a promoted artifact's bytes changed 17 minutes after promotion and the build-info was left pointing at a digest no longer in the repository. For npm it breaks consumers rather than merely confusing them, since npm ci verifies the lockfile integrity hash. Fails rather than skips, unlike the Cargo pilot's equivalent guard: this job only runs from a version tag, so an existing version means the tag was moved or re-cut, and continuing would either overwrite released bytes or promote a build whose artifact someone else published. This is a convention, not an enforced boundary. Repository immutability is the real fix and needs platform admin (Lab271/labs-jfrog-poc#4). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
Part of the JFrog evaluation (Lab271/labs-jfrog-poc#4). Generalises the guard already shipped on the Cargo pilot in Lab271/sqlite-rs#684.
Why
lab-npm-dev-localandlab-npm-prod-localare mutable.blackedOut: false, and no repository immutability setting exists on an Artifactory local repo — all 64 config fields were checked. Re-publishing a version overwrites the bytes silently, with no error, including a version already promoted with statusReleased.That is not hypothetical. During the evaluation a promoted artifact was overwritten exactly this way: the bytes changed 17 minutes after promotion and the build-info was left pointing at a digest that no longer existed in the repository.
For npm it also breaks consumers rather than merely confusing them —
npm civerifies the lockfile's integrity hash, so anyone pinning the overwritten version gets an integrity mismatch.Why it fails rather than skips
The Cargo pilot's equivalent guard warns and skips, because that job runs on every push. This one only runs from a
v*.*.*tag, so an existing version means the tag was moved or re-cut. Continuing would either overwrite released bytes or promote a build whose artifact someone else published — both worse than a red run.What this is not
It is a convention, not an enforced boundary. Repository immutability is the real fix and needs platform admin we do not have (Lab271/labs-jfrog-poc#4). Anything holding the CI token can still overwrite by calling Artifactory directly; this only stops the accident that actually happened.
Verification
The check is a
jf rt curlagainst/api/storage/...for the exact tarball path, confirmed against the live repository layout (lab-npm-prod-local/slidecue/-/slidecue-0.7.4.tgz). Workflow YAML parses. The guard cannot run on a PR — this workflow is tag-triggered — so it is exercised on the next release.🤖 Generated with Claude Code