ci(napi): gate the release PR on a real native build - #89
Merged
Conversation
0.5.22 was cut, failed, and could not be repaired — the tag existed but nothing reached npm. Two changes so that is less likely and less final. Prevention: run the 6-target matrix and its load checks on release-please's PR, before the merge that cuts the tag. #85 broke the loader at 17:09 and release-please refreshed its PR branch at 17:10, so this gate would have caught that exact regression with a CI run instead of a burned version. Guarded per-job on github.head_ref (`branches:` filters the base, not the head); every other PR already builds the addon natively on all three hosts via ci.yml's `pnpm build`, so what this adds is the cross-compiled targets. `publish` stays gated on the `publish` input, which no PR event can set. Recovery: a `source_ref` input, because a workflow_dispatch always reads its own definition from the ref it targets — so a workflow bug that reaches a tag cannot be fixed for that tag from main. `--ref main -f source_ref=<tag>` runs main's workflow against the tag's source. All three checkouts honour it; the publish job's especially, since it never builds and takes the version from package.json, so a mismatch would ship one ref's binaries under another's version. This only recovers the native package. RELEASING.md documents why the SDK and CLI halves cannot be republished for an existing tag, and that rolling forward remains the answer. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Member
Author
|
Exclusion half of the guard confirmed on this PR itself: |
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.
Follow-up to #86. That fixed the bug that broke 0.5.22; this addresses why a broken release was unrecoverable and had to be rolled forward to 0.5.23.
Prevention — the part that matters
release-please cuts the tag the moment its PR merges, so today the first proof that the native build works arrives after the version is spent. This runs the 6-target matrix and its load checks on the release PR, while the version can still be not-released.
It would have caught this exact regression: #85 broke the loader at 17:09 on Jul 28, and release-please refreshed its PR branch at 17:10. A gate there fails on
MODULE_NOT_FOUND, #80 never merges, and 0.5.22 is never cut.Scoped per-job on
github.head_ref, becausebranches:underpull_requestfilters the base branch, not the head. Every other PR already builds the addon natively on all three hosts through ci.yml'spnpm build→napi build --platform --release; what this adds for a release PR is the cross-compiled targets and therequire()checks.testandpublishneed no matching guard — theyneeds:the build job, and a skipped dependency skips its dependents.No publish path opens up.
publishstays gated on thepublishinput, which nopull_requestevent can set.The cost is building twice per release — once as the gate, once for real after merge. Reusing the PR's artifacts would make the provenance attest a run that merely repacked binaries it never built, so the double build is the honest price.
Recovery —
source_refA
workflow_dispatchalways reads its own definition from the ref it targets, and this workflow had no way to separate the two. So a workflow bug that reaches a tag cannot be fixed for that tag by any later commit on main — which is precisely why 0.5.22 could not be retried.gh workflow run napi-build.yml --ref main -f publish=true -f source_ref=<tag>now runs main's workflow against the tag's source.All three checkouts honour it. The publish job's matters most: it never builds, and takes the version straight from
package.json, so a mismatch there would ship one ref's binaries under another ref's version number.This recovers the native package only.
release.yml's publish job — which ships the SDK and CLI — ison: pushgated onrelease_created, and release-please will not re-create a released version; re-running the old run fails too, since its native-build watch waits on a run id that is already a completed failure. With noNPM_TOKEN(publishing is token-less OIDC), there is no manual path either. RELEASING.md now documents this, and that rolling forward stays the answer.Verification
A CI-only change can't be tested locally, and this PR's own branch name deliberately won't match the guard — so I opened a throwaway PR from a
release-please---prefixed branch (#88, closed) to exercise the new path for real:NAPI Buildtriggered on thepull_requesteventhead_refguard admitted it — all 6/6 build jobs instantiated rather than skippingrefs/pull/N/mergesuccessfully, which is the genuinely new code path here (this workflow had never run on a PR event, and I changed every checkout to an explicitref:)Cancelled once those three were confirmed rather than burning 6 runners for 7 minutes — the compilation itself was proven by the 0.5.23 release run earlier today.
actionlintis clean on both changed workflows. The oneSC2086note it reports pre-exists on main (the deliberately-unquoted$TAG_ARG, which must word-split to nothing).Not verified: that the gate blocks a genuinely broken build — that needs a real breakage, and the #85 timeline above is the argument instead.
🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.