Skip to content

Phase 6g: add publish-nodejs to release.yml (npm via OIDC)#28

Merged
joaoh82 merged 1 commit intomainfrom
feat/publish-nodejs
Apr 24, 2026
Merged

Phase 6g: add publish-nodejs to release.yml (npm via OIDC)#28
joaoh82 merged 1 commit intomainfrom
feat/publish-nodejs

Conversation

@joaoh82
Copy link
Copy Markdown
Owner

@joaoh82 joaoh82 commented Apr 24, 2026

Summary

Adds two new jobs to release.yml that build + publish the sqlrite Node.js package to npm on every release, authenticating via OIDC trusted publishing (no NPM_TOKEN).

Job Cells Role
build-nodejs-binaries 4 (Linux x86_64/aarch64, macOS aarch64, Windows x86_64) napi-rs builds .node binaries
publish-nodejs 1 Aggregate all binaries + JS dispatcher, atomic npm publish --provenance, cut sqlrite-node-v<V> GitHub Release

Bundled-binaries architecture

The main sqlrite npm package ships every platform's .node binary inside one tarball (~15 MiB). napi-rs's generated index.js picks the right one at require time via process.platform + process.arch. The alternative — an @sqlrite/linux-x64-gnu + @sqlrite/darwin-arm64 + ... optional-deps pattern used by @napi-rs/*, sharp, @swc/core — is more efficient (users download only the one binary they need) but means maintaining N+1 npm packages. For an MVP, one package beats five. We can always pivot later without a breaking change.

Why build/publish split (same pattern as Phase 6f)

If each matrix cell ran npm publish independently, a partial failure would put some-but-not-all binaries on npm with no clean rollback. Aggregator downloads all four .node files into sdk/nodejs/ alongside the napi-generated index.js dispatcher (only the Linux x86_64 cell uploads that — it's identical across build platforms), then does one npm publish --provenance.

Matrix choices

Mirrors publish-ffi / publish-desktop / publish-python — one consistent OS/arch pattern across all publish jobs:

OS napi triple Output
ubuntu-latest linux-x64-gnu sqlrite.linux-x64-gnu.node
ubuntu-24.04-arm linux-arm64-gnu sqlrite.linux-arm64-gnu.node
macos-latest darwin-arm64 sqlrite.darwin-arm64.node
windows-latest win32-x64-msvc sqlrite.win32-x64-msvc.node

Authentication + provenance

OIDC trusted publishing via permissions: id-token: write + the release GitHub environment. Zero NPM_TOKEN anywhere.

The --provenance flag attaches a sigstore-signed attestation linking the published package to this exact GitHub Actions workflow run. Users can verify it with npm audit signatures. This is npm's equivalent of the PEP 740 attestations that worked first-try in the v0.1.4 canary (see the .publish.attestation files on sqlrite-py-v0.1.4).

Wiring

  • tag-all → now pushes sqlrite-node-v<V>
  • finalize.needs → extended with publish-nodejs
  • Umbrella release body → 🟢 Node.js entry with npm + per-product release links

Name availability

sqlrite is available on npmcurl -o /dev/null -w "%{http_code}" https://registry.npmjs.org/sqlrite returns 404. package.json already has name: "sqlrite", no rename dance needed.

Test plan

  • cargo check -p sqlrite-nodejs — clean
  • python3 -c "import yaml; yaml.safe_load(open('.github/workflows/release.yml'))" — YAML parses
  • npm name availability verified (404 on registry)
  • CI on this PR (existing nodejs-sdk matrix jobs re-exercise the SDK)
  • After merge: ONE-TIME NPM SETUP REQUIRED — log into npmjs.com, reserve the sqlrite package name by configuring a trusted publisher pointing at this repo / release.yml / environment release. Documented in docs/release-secrets.md.
  • After that: dispatch release-pr.yml at 0.1.5 → review → merge → approve release env gates (now 10 total: 1 crate + 4 ffi + 3 desktop + 1 python + 1 nodejs) → verify sqlrite 0.1.5 on npm + sqlrite-node-v0.1.5 GitHub Release.

Not in scope

  • Phase 6h (publish-wasm, also on npm but as a separate package named sqlrite-wasm)
  • Phase 6i (publish-go — git tag + FFI tarball attachment)

Each lands as its own PR.

🤖 Generated with Claude Code

Two new jobs following the Phase 6f pattern:

  - build-nodejs-binaries (matrix, 4 cells)
  - publish-nodejs        (aggregate + npm publish + GitHub Release)

**Bundled-binaries architecture**: the `sqlrite` npm package ships
every platform's `.node` binary inside one tarball (~15 MiB),
picked at require time by napi's generated `index.js` dispatcher
based on process.platform / process.arch. Simpler than managing
N+1 npm packages (main + one per platform) — the cost is a bigger
download, acceptable for a database driver people install once.

**Why build/publish split**: same reason as publish-python — if
each matrix cell ran `npm publish` independently, a mid-matrix
failure would leave npm with some-but-not-all binaries and no
clean rollback. Aggregator downloads every platform's `.node`
binary into sdk/nodejs/ alongside the napi-generated `index.js`
dispatcher (uploaded by the Linux x86_64 cell only — it's
identical across build platforms), then does one atomic
`npm publish --provenance`.

**Matrix** mirrors publish-ffi / publish-desktop / publish-python
so all publish jobs share one consistent OS/arch pattern:

  ubuntu-latest     → linux-x64-gnu    (sqlrite.linux-x64-gnu.node)
  ubuntu-24.04-arm  → linux-arm64-gnu  (sqlrite.linux-arm64-gnu.node)
  macos-latest      → darwin-arm64     (sqlrite.darwin-arm64.node)
  windows-latest    → win32-x64-msvc   (sqlrite.win32-x64-msvc.node)

**Authentication via npm OIDC trusted publishing** — zero
long-lived NPM_TOKEN. The publish-nodejs job has `permissions:
id-token: write` and lives in the `release` GitHub environment.
npm-side config is one-time trusted-publisher registration on
npmjs.com (docs/release-secrets.md). `--provenance` flag attaches
a sigstore-signed attestation linking the published package to
this exact GitHub Actions run — npm's equivalent of PyPI's
PEP 740 attestations that worked first-try in the v0.1.4 canary.

**Wiring:**

  - tag-all   → pushes sqlrite-node-v<V>
  - finalize  → needs publish-nodejs
  - umbrella release body → 🟢 Node.js link with npm + per-product
    release pointers

Verified locally: `cargo check -p sqlrite-nodejs` clean,
release.yml parses as valid YAML, npm name `sqlrite` available
(404 on registry.npmjs.org). Existing package.json already names
it `sqlrite` and has the `sqlrite.*.node` glob in `files`, so no
SDK source changes needed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@joaoh82 joaoh82 merged commit 03a4972 into main Apr 24, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant