fix(napi): prevent prepublish uploads to immutable releases - #83
Merged
Conversation
The `native-publish` job's `@akua-dev/native` publish runs its `prepublishOnly` hook (`napi prepublish`), which — beyond injecting the per-platform `optionalDependencies` and copying addons — attempted to upload the per-platform `.node` files as assets to the already-cut, immutable GitHub Release (`POST releases/<id>/assets`). During the 0.8.25 recovery GitHub rejected each upload with HTTP 400, so the Release survived intact — but it failed safe by luck, not by design. Disable only the Release-write at its source with `--no-gh-release` in the `prepublishOnly` script. This keeps the essential optionalDependencies injection (the published meta's 7 optionalDeps do not exist in the committed package.json, so `--ignore-scripts` — the sdk-publish pattern — would ship a meta with no native binary and break installation). Add a guard comment in the workflow and an AGENTS.md note so the hook is never "fixed" back to `--ignore-scripts`.
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.
Intent
Harden the Akua release-publish workflow so the @napi-rs/cli prePublish hook can never attempt to write to an immutable GitHub Release again (captain-approved follow-up to the 0.8.25 recovery, akua#71). During 0.8.25 the meta-package @akua-dev/native publish invoked napi prepublish, which tried to upload per-platform .node files as assets to the already-cut immutable Release via POST releases//assets; GitHub rejected each with HTTP 400 so the Release survived by luck, not by design. The intended fix was to add --ignore-scripts to the meta publish (mirroring sdk-publish), BUT I verified that would break the package: the published @akua-dev/native@0.8.25 carries 7 optionalDependencies that are absent from the committed package.json and are injected by the napi prepublish hook at publish time, so --ignore-scripts would ship a meta with no native binary and break installation. Instead, per the task's pre-authorized tightly-scoped alternative (a napi config option that disables ONLY the Release-write), I changed the prepublishOnly script in crates/akua-napi/package.json from 'napi prepublish -t npm' to 'napi prepublish -t npm --no-gh-release'. --gh-release defaults on in CI; --no-gh-release disables only the immutable-Release asset upload while preserving the essential optionalDependencies injection + addon copy. Added a guard comment in .github/workflows/release-publish.yml explaining why the meta publish must NOT use --ignore-scripts like sdk-publish, and a matching AGENTS.md release-section note so the hook is never reverted to --ignore-scripts. Scope is workflow/packaging hardening only: no version changes, no publishing, no Release/GHCR actions, and no publish workflow was dispatched (0.8.25 is already published; validation is by review/CI only).
What Changed
@akua-dev/nativeprepublish with--no-gh-release, preventing immutable GitHub Release asset uploads while preserving platformoptionalDependenciesgeneration.--ignore-scriptsfor native publishing.Risk Assessment
✅ Low: The supported flag correctly prevents GitHub Release creation/uploads while preserving dependency injection; only a minor documentation inaccuracy remains.
Testing
After baseline change inspection, the focused red/green workflow guard, intercepted real prepublish comparison, packed-manifest verification, and clean consumer install/load all succeeded: the hardened hook made no GitHub API request, preserved seven optional native dependencies, and produced a loadable package; no workflow, publish, Release, or GHCR action was dispatched.
Evidence: Hardened-hook network evidence
Target: NO OUTBOUND FETCH ATTEMPT RECORDEDEvidence: Legacy-hook negative control
Legacy control: FETCH POST https://api.github.com/repos/akua-dev/akua/releasesEvidence: Published meta-package manifest
Generated publish manifest containing all seven injected platform optionalDependencies.Evidence: Packed native meta-package
Source: Packed native meta-package (local file:
/var/folders/1y/cjgf53nj31n_dxsspqnjfjvc0000gn/T/no-mistakes-evidence/01KY1ZANZQ9WWWTCRE2H7E31BB/akua-dev-native-0.8.8.tgz)Evidence: Consumer install/load smoke test
Clean installation selected @akua-dev/native-darwin-arm64 and successfully loaded the native addon exports.Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
.github/workflows/release-publish.yml:280- Correct the guard comment:napi prepublishdoes not copy addons; the earliernapi artifactsstep does. The hook is load-bearing here for platform-version andoptionalDependenciessynchronization. The current wording misstates the release invariant. See the NAPI-RS prepublish documentation.✅ **Test** - passed
✅ No issues found.
bash scripts/check-release-workflows.shbefore and after adding the focused regression guardbash scripts/check-release-workflows.shafter temporarily removing--no-gh-release(expected failure), then after restorationbash scripts/check-release-workflows.shafter temporarily adding--ignore-scriptsto the native meta publish (expected failure), then after restorationbun install --frozen-lockfileincrates/akua-napiCI=true GITHUB_ACTIONS=true GITHUB_REPOSITORY=akua-dev/akua ... npm run prepublishOnlywith an outbound-fetch blocker/loggerCI=true GITHUB_ACTIONS=true GITHUB_REPOSITORY=akua-dev/akua ... bunx napi prepublish -t npmas the legacy negative controlnpm pack --ignore-scripts --pack-destination <evidence-dir> --jsonand packed-manifest inspectionnpm install --prefix <evidence-dir>/install-smoke <packed-tarball> --ignore-scripts --package-lock=falsenode -e "require('@akua-dev/native') ..."in the clean consumer fixtureFresh post-cleanup workflow-guard, network-log, packed-manifest, tarball-content, consumer-load, and worktree-residue checks✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.