This document describes the release path for every EdgeParse distribution asset: Rust crates, Python wheels, Node.js packages, the WASM SDK, CLI archives, Homebrew, and Docker images.
Publishing is driven by six GitHub Actions workflows, all triggered by pushing a semantic version tag:
git tag v0.2.2
git push origin v0.2.2vX.Y.Z tag
├─ release-rust.yml -> crates.io (pdf-cos, edgeparse-core, edgeparse-cli)
├─ release-python.yml -> PyPI (edgeparse wheels + sdist)
├─ release-node.yml -> npm (edgeparse + 5 platform packages)
├─ release-wasm.yml -> npm + GitHub Packages + GitHub Releases (edgeparse-wasm)
├─ release-cli.yml -> GitHub Releases (5 CLI archives) + Homebrew tap
└─ release-docker.yml -> GHCR + Docker Hub (linux/amd64, linux/arm64)
Shared verification happens in ci.yml on pushes and pull requests:
- Rust build, test, clippy, and fmt checks
- Python wheel build and SDK tests
- Node.js addon build and SDK tests
- WASM target compilation check
- Docker image smoke build
- Cargo audit and cargo-deny
Each GitHub Release includes:
| Archive | Platform |
|---|---|
edgeparse-X.Y.Z-aarch64-apple-darwin.tar.gz |
macOS Apple Silicon |
edgeparse-X.Y.Z-x86_64-apple-darwin.tar.gz |
macOS Intel |
edgeparse-X.Y.Z-x86_64-unknown-linux-gnu.tar.gz |
Linux x86_64 (glibc >= 2.17) |
edgeparse-X.Y.Z-aarch64-unknown-linux-gnu.tar.gz |
Linux ARM64 (glibc >= 2.17) |
edgeparse-X.Y.Z-x86_64-pc-windows-gnu.zip |
Windows x86_64 |
| Platform | Python versions |
|---|---|
| Linux x86_64 | cp310, cp311, cp312, cp313 |
| Linux ARM64 | cp310, cp311, cp312, cp313 |
| macOS Intel | cp310, cp311, cp312, cp313 |
| macOS Apple Silicon | cp310, cp311, cp312, cp313 |
| Windows x86_64 | cp310, cp311, cp312, cp313 |
| Source distribution | sdist |
| Secret | Used by | Purpose |
|---|---|---|
CARGO_REGISTRY_TOKEN |
release-rust.yml |
Publish crates to crates.io |
NPM_TOKEN |
release-node.yml, release-wasm.yml |
Fallback token — not needed when Trusted Publisher (OIDC) is configured for the package |
DOCKERHUB_TOKEN |
release-docker.yml |
Push Docker images to Docker Hub |
HOMEBREW_TAP_TOKEN |
release-cli.yml |
Push edgeparse.rb to the Homebrew tap |
| Environment | Used by | Notes |
|---|---|---|
npm |
release-node.yml, release-wasm.yml |
Optional protection rules for npm release jobs |
pypi |
release-python.yml |
Required for PyPI Trusted Publishing |
-
crates.io: create a token with
publish-newandpublish-update -
npm (Trusted Publisher — recommended): configure via OIDC so CI publishes without any token:
- Go to the package settings page on npmjs.com
- Under Trusted Publisher, set Publisher = GitHub Actions,
org/user =
raphaelmansuy, repository =edgeparse, workflow filename = the publishing workflow (see table below), environment = (leave blank) - Add
id-token: writepermission to the publishing job (already done in bothrelease-node.ymlandrelease-wasm.yml) - Use
npm publish --provenance --access public— noNODE_AUTH_TOKENenv var needed
npm package Workflow filename edgeparserelease-node.ymledgeparse-wasmrelease-wasm.ymlFor
edgeparse-wasm: the package must exist on npm before the Trusted Publisher entry can be saved. Publish the first version manually with--otp, then configure the Trusted Publisher entry — all subsequent releases use OIDC. -
npm (Classic token — fallback): if Trusted Publisher is not yet configured, create a Classic Automation token at https://www.npmjs.com/settings/raphaelmansuy/tokens and store it as
NPM_TOKEN. Granular Access Tokens cannot create new packages and will fail withE404. -
PyPI: configure Trusted Publishing for
release-python.ymlin environmentpypi -
Docker Hub: create a read/write access token for account
rmansuy -
Homebrew tap: create a PAT with
contents: writeonraphaelmansuy/homebrew-edgeparse
- Ensure the working tree is clean.
- Update versioned manifests:
- root
Cargo.toml crates/edgeparse-cli/Cargo.tomlsdks/node/package.jsonsdks/node/package-lock.jsonsdks/node/npm/*/package.jsoncrates/edgeparse-wasm/pkg/package.json
- root
- Update release notes:
CHANGELOG.mdREADME.md- this document when the release surface changes
- Run local release-prep verification.
- Push the release branch and open a PR.
- Merge the PR.
- Tag the merge commit and push the tag.
- Watch all six release workflows complete.
Run the checks that correspond to shipped assets before tagging:
cargo test
cargo check -p edgeparse-wasm --target wasm32-unknown-unknown
docker build -f docker/Dockerfile .
cd sdks/node
npm ci
cargo build --manifest-path ../../crates/edgeparse-node/Cargo.toml --release
# Copy the host-specific addon into the matching local package before testing.
# Example shown here for Apple Silicon:
cp ../../target/release/libedgeparse_node.dylib npm/darwin-arm64/edgeparse-node.darwin-arm64.node
npm install --no-save file:./npm/darwin-arm64
npm run build:ts
npm test
cd ../..
cd benchmark
uv run python run.py --check-regression
cd ..Optional dry runs:
make publish-rust-dry
make publish-python-dry
make publish-node-dry
make publish-wasm-dry
make publish-cli-dry
make publish-brew-dry# 1. Commit and push the release-prep branch
git add -A
git commit -m "chore: prepare 0.2.4 release"
git push origin <branch>
# 2. Open and squash-merge the PR
gh pr create --base main --head <branch> --title "chore: prepare 0.2.4 release"
gh pr merge <pr-number> --squash --delete-branch
# 3. Tag the merge commit on main
git checkout main
git pull --ff-only origin main
git tag v0.2.4
git push origin v0.2.4The tag must match v[0-9]+.[0-9]+.[0-9]+. The Rust and WASM release
workflows verify that the tag version matches the workspace version and fail
fast on mismatches.
| Job | Coverage |
|---|---|
rust |
cargo build, cargo test, cargo clippy, cargo fmt --check |
python |
Build wheel with maturin and run SDK tests |
node |
Build native addon, compile TypeScript, run SDK tests |
wasm |
cargo check -p edgeparse-wasm --target wasm32-unknown-unknown |
docker |
docker build -f docker/Dockerfile . |
security |
cargo audit and cargo deny check |
- Verifies tag/version consistency
- Publishes
pdf-cos, thenedgeparse-core, thenedgeparse-cli - Waits for crates.io index propagation between dependent crates
- Creates or updates the GitHub Release notes
- Builds wheel artifacts for Linux, macOS, and Windows
- Builds an sdist
- Publishes to PyPI via OIDC Trusted Publishing
- Builds native
.nodebinaries for five targets - Syncs the package version from the tag
- Publishes five platform packages and the main
edgeparsepackage using npm Trusted Publisher (OIDC) — noNPM_TOKENneeded - Adds provenance attestation (
--provenance) to every published package - Treats "already published" as idempotent rather than fatal
- Builds the browser-targeted WASM package with
wasm-pack - Syncs the npm package metadata (version, exports, files, provenance) from the tag
- Publishes
edgeparse-wasmto npm using npm Trusted Publisher (OIDC) — noNPM_TOKENneeded - Adds provenance attestation (
--provenance) so the package appears as verified on npmjs.com - Publishes
@raphaelmansuy/edgeparse-wasmto GitHub Packages (secondary) using the built-inGITHUB_TOKEN— no extra secret required - Uploads the tarball to the GitHub Release (
--clobberfor idempotent re-runs) - Both publish steps treat "already published" as non-fatal
| Permission | Purpose |
|---|---|
id-token: write |
Mint OIDC token for npm Trusted Publisher |
packages: write |
Push to GitHub Packages |
contents: write |
Create / update GitHub Releases |
One-time setup — after the first manual publish creates the package on npm:
- Go to https://www.npmjs.com/package/edgeparse-wasm → Settings → Trusted Publisher
- Publisher:
GitHub Actions - Organization or user:
raphaelmansuy - Repository:
edgeparse - Workflow filename:
release-wasm.yml - Environment name: (leave blank)
- Click Save changes
All future tag releases will publish via OIDC with no token required.
After updating, re-trigger without retagging:
gh workflow run release-wasm.yml --repo raphaelmansuy/edgeparse \
--field tag_name=v0.2.4- Builds five CLI archives
- Uploads them to the GitHub Release
- Regenerates and pushes the Homebrew formula
- Builds and pushes a multi-arch container image
- Publishes to GHCR and Docker Hub
- Generates provenance and SBOM metadata
- Runs a Trivy vulnerability scan
The Makefile mirrors the registry release flow for manual publishing:
make publish-rust
make publish-python
make publish-node
make publish-wasm
make publish-cli
make publish-brew
make publish-allmake publish-all covers crates, Python, Node.js, the WASM SDK, CLI archives,
and Homebrew. Docker publishing remains CI-driven through release-docker.yml.
Crates.io versions are immutable. Bump the version and retag.
Use a Classic Automation token for NPM_TOKEN. Granular tokens often miss one
or more package names and produce E403 Forbidden.
This happens when either:
-
Wrong token type — A Granular Access Token was used instead of a Classic Automation token. Granular tokens cannot create brand-new package names on npm. Solution: replace
NPM_TOKENwith a Classic Automation token (see Configuring NPM_TOKEN above). -
Package name not yet claimed —
edgeparse-wasmhas never been published before, so npm has no record of the package. This is normal on first release; a Classic Automation token will create it automatically.
After fixing the secret, re-trigger the workflow without retagging:
gh workflow run release-wasm.yml --repo raphaelmansuy/edgeparse \
--field tag_name=v0.2.4The workflow treats "already published" as idempotent, so re-running is safe.
The PyPI Trusted Publisher entry must match:
- project:
edgeparse - owner:
raphaelmansuy - repository:
edgeparse - workflow:
release-python.yml - environment:
pypi
Re-run the specific workflow. release-cli.yml and release-wasm.yml upload
assets with --clobber, so the release can be repaired without retagging.
Use cargo-zigbuild plus zig. The release workflows already do this for the
Linux ARM64 and Windows targets.