Repository navigation
fix(publish): pass the tarball as a path, and make the label one-shot - #203
Merged
Merged
Conversation
The first experimental publish failed, and not on authentication:
npm error command git --no-replace-objects ls-remote \
ssh://git@github.com/artifacts/strapi-community-plugin-rest-cache-0.0.0-experimental.ff1018e.tgz.git
npm error git@github.com: Permission denied (publickey).
npm parses a bare relative path containing a slash as a GitHub shorthand -
owner/repo - so `artifacts/x.tgz` sent it looking for a git remote rather than
reading the tarball. It reads like an OIDC failure and is nothing of the sort;
trusted publishing was never reached.
Reproduced and fixed locally with --dry-run:
npm publish artifacts/x.tgz -> the same git ls-remote error
npm publish ./artifacts/x.tgz -> reads the tarball, resolves the name, and
is rejected only by "cannot publish over
the previously published versions: 5.0.0"
This would have broken the 5.1.0 release identically, which is what the
experimental dry run existed to find out.
Also: remove the trigger label once the run finishes. The label is a request to
publish one build, not a mode the PR sits in - it used to also fire on
`synchronize`, so every later push republished silently for as long as the
label was still attached. `synchronize` is dropped and a separate `unlabel` job
takes the label back off, `always()` so a failed publish cannot leave it behind
and make the next attempt look like a no-op.
That job is separate because it needs `pull-requests: write`, and the build job
- the one that may run unreviewed code - must keep `contents: read` and nothing
else.
Co-Authored-By: Claude <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.
The experimental publish failed — and not on auth
Run 31760869448.
Build and packsucceeded;Publish to npmdied:That looks like an OIDC/trusted-publishing failure. It isn't — npm never
contacted the registry. It parses a bare relative path containing a slash as
a GitHub shorthand (
owner/repo), soartifacts/x.tgzsent it looking for agit remote instead of reading the tarball.
This would have broken the 5.1.0 release in exactly the same way. Finding
it is precisely what the experimental dry run was for.
Reproduced and fixed locally, with
--dry-runThe leading
./is what makes it unambiguously a path.Second change: the label is now one-shot
Per @derrickmehaffy — the run now removes
publish-experimentalwhen itfinishes, so the label means "publish a build now" rather than "this PR is in
experimental mode". To cut another build after pushing, add it back.
synchronizeis dropped from the trigger. It was the mechanism that made everysubsequent push republish silently for as long as the label happened to still
be attached; with the label removed after each run it would only ever fire in
the window before cleanup.
Three details worth reviewing:
unlabelis a separate job. It needspull-requests: write, and thebuildjob — the one that may execute unreviewed branch code — must keepcontents: readand nothing else.unlabelchecks out nothing and runs onlythis file, from the default branch.
always(), so a failed publish still clears the label. Otherwise thenext person to add it sees nothing happen, because it is already there.
removeLabelis swallowed — someone removing it by hand producesthe desired end state, not a failure.
The PR comment and
.claude/skills/cut-a-release/SKILL.mdboth promisedrepublish-on-push, so both are updated.
Note
Touches
.github/workflows/publish.yml, so it needs a maintainer to merge.And because
pull_request_targetruns the workflow from the defaultbranch, this fix has no effect until it is on
main— re-labelling #201before then will fail the same way.
🤖 Generated with Claude Code