This document describes the complete release and delivery pipeline for node-liblzma.
graph LR
subgraph "Standard Release"
R[release.yml<br><i>bump, tag, changelog</i>] --> BA[build-artifacts.yml<br><i>Linux, macOS, Windows</i>]
BA --> P[publish.yml<br><i>3 npm packages + OIDC</i>]
end
subgraph "Emergency"
MR[manual-release.yml<br><i>existing tag</i>] --> BA2[build-artifacts.yml]
BA2 --> P2[publish.yml]
end
subgraph "Standalone"
PR[pre-release.yml<br><i>alpha / beta / rc</i>]
end
style R fill:#4CAF50,color:#fff
style MR fill:#FF9800,color:#fff
style PR fill:#2196F3,color:#fff
Workflow: release.yml (manual trigger via GitHub Actions UI)
This is the primary release path. It handles everything end-to-end.
First-time bootstrap (only once per new package). OIDC trusted publishing requires the package to already exist on npm before
publish.ymlcan publish it via the workflow. For a brand-new package (e.g. when introducing@oorabona/nxz), the maintainer must run a one-time manual publish locally that mirrorspublish.yml's pack-then-publish flow:# From the repo root pnpm install --frozen-lockfile pnpm build && pnpm -r --filter './packages/*' run build # root + all workspace pkgs (a workspace pkg's build depends on root lib/) TARBALL=$(cd packages/<pkg-dir> && pnpm pack --pack-destination /tmp | tail -1) npm publish "$TARBALL" --access public # may prompt for OTPThe
pnpm packstep is essential: it rewritesworkspace:protocol dependencies to concrete versions in the tarball. A barenpm publishfrom the package directory would publish broken metadata. After the publish succeeds, configure the trusted publisher on npmjs.com (Repository: oorabona/node-liblzma,Workflow: publish.yml). Subsequent releases of that package then flow throughrelease.yml→ OIDC normally.
sequenceDiagram
participant M as Maintainer
participant R as release.yml
participant BA as build-artifacts.yml
participant P as publish.yml
participant NPM as npm registry
M->>R: workflow_dispatch (patch/minor/major)
R->>R: release-it: bump version + CHANGELOG
R->>R: GPG-sign commit + tag
R->>R: Push to master
R->>R: Create GitHub Release
R->>BA: Build prebuilds (3 platforms)
BA-->>R: Upload to GitHub Release assets
R->>P: gh workflow run publish.yml
P->>NPM: Publish node-liblzma (OIDC)
P->>NPM: Publish tar-xz (OIDC)
P->>NPM: Publish @oorabona/nxz (OIDC)
| Input | Type | Description |
|---|---|---|
increment |
choice: patch / minor / major | Semver bump type |
skip_npm |
boolean | Skip npm publish (dry run) |
- Bump version —
release-it-presetupdatespackage.jsonandCHANGELOG.mdfrom conventional commits - GPG-sign commit — Version bump committed with GPG signature (key:
B98806DCD4E29D4D) - Create tag — GPG-signed tag
vX.Y.Z - Push — Commit and tag pushed to
master - GitHub Release — Created automatically with generated release notes
- Build prebuilds — Cross-platform native binaries via
build-artifacts.yml - Publish to npm — All 3 packages via
publish.yml(OIDC provenance)
- Go to Actions → Release → Run workflow
- Select the semver increment (patch / minor / major)
- Optionally check "Skip npm publish" for a dry run
- Click Run workflow
Workflow: manual-release.yml (manual trigger)
Use this when a tag already exists but the release pipeline failed partway through (e.g., GitHub Release wasn't created, prebuilds weren't built, or npm publish failed).
release.ymlpartially failed after creating the tag- You created a tag manually and need to complete the release
- You need to re-run build + publish for an existing tag
| Input | Type | Description |
|---|---|---|
tag |
string | Existing git tag (e.g., v3.2.0) |
skip_npm |
boolean | Skip npm publish |
- Checks out the given tag
- Creates GitHub Release
- Builds prebuilds for all platforms
- Triggers
publish.yml
Workflow: pre-release.yml (manual trigger)
For publishing alpha, beta, or release candidate versions.
| Input | Type | Description |
|---|---|---|
prerelease-type |
choice: alpha / beta / rc | npm dist-tag |
version |
string | Full version (e.g., 3.3.0-alpha.1) |
- Runs tests and type-check
- Builds N-API prebuilt binaries (Node-version-independent) for linux-x64, macOS-arm64, win32-x64
- Publishes to npm with the appropriate dist-tag (
--tag alpha) - Creates GitHub pre-release
npm install node-liblzma@alpha # or @beta, @rcIf npm publish fails partway through, simply re-run publish.yml manually via Actions → Publish → Run workflow with the same tag. The workflow is idempotent — already-published packages are skipped.
Three packages are published in dependency order:
| # | Package | npm name | Description |
|---|---|---|---|
| 1 | root | node-liblzma |
Core XZ/LZMA2 bindings (native + WASM) |
| 2 | packages/tar-xz | tar-xz |
tar.xz streaming library |
| 3 | packages/nxz | @oorabona/nxz |
CLI tool for XZ compression |
- Authentication: OIDC trusted publishing (no npm token needed)
- Node.js: v24+ required in
publish.yml(npm >= 11.5.1 for OIDC) - Provenance: All packages published with
--provenanceattestation - Idempotent: Already-published versions are skipped (safe re-runs)
- Workspace protocol:
pnpm packresolvesworkspace:dependencies beforenpm publish
| Workflow | Trigger | Purpose |
|---|---|---|
ci.yml |
Push, PR, nightly | Tests, lint, coverage. Smart smoke/full matrix selection |
build-artifacts.yml |
Called by release/manual-release | Cross-platform prebuilds (Linux, macOS, Windows × x64) |
check-xz-updates.yml |
Weekly (Monday 3 AM UTC) | Monitors upstream XZ Utils, auto-PRs compatible updates |
docs.yml |
Release published, doc changes | Builds and deploys docs to GitHub Pages |
build-wasm.yml |
WASM file changes | Isolated WASM build with size gate (< 100KB gzipped) |
Runs weekly to detect new XZ Utils releases:
- Queries GitHub API for latest XZ release
- Compares with
xz-version.json - If new version: runs full test suite against it
- If tests pass: creates PR with auto-merge enabled
- If tests fail: creates issue for manual review
| Secret | Required | Used in | Purpose |
|---|---|---|---|
GPG_PRIVATE_KEY |
Yes | release, check-xz-updates | GPG-sign commits and tags |
GITHUB_TOKEN |
Auto | All workflows | GitHub API access |
CODECOV_TOKEN |
Yes | ci (coverage) | Upload coverage reports |
Normal releases use npm OIDC trusted publishing — no npm token is stored as a secret. This requires:
id-token: writepermission in the workflowregistry-url: 'https://registry.npmjs.org'in setup-node- Node.js 24+ (npm >= 11.5.1)
- Each package must be configured for trusted publishing on npmjs.com
All release commits and tags are signed with GPG key B98806DCD4E29D4D. The crazy-max/ghaction-import-gpg action configures git to use the key automatically. Committer identity: Olivier ORABONA <oorabona@users.noreply.github.com>.
- Verify
id-token: writepermission is set - Ensure Node.js version is 24+ (npm OIDC requires >= 11.5.1)
- Publish workflow must be triggered via
workflow_dispatch(notworkflow_call) — the OIDC token includes the workflow filename, andworkflow_callmakes the caller appear in the token instead
- Verify
prebuilds/is listed inpackage.json"files"array - Check that
build-artifacts.ymlcompleted successfully and uploaded assets to the GitHub Release - Run
npm pack --dry-run | grep prebuildsto verify tarball contents
Actions performed by GITHUB_TOKEN don't trigger other GitHub workflows. This is why:
release.ymlusesgh workflow run(creates a new workflow_dispatch event) instead of relying on release eventsmanual-release.ymlexists as a fallback for when automated chains break