CI/CD for a wasm-pack Library with GitHub Actions
Run wasm-pack tests in a headless browser, build the npm package, and publish on a tag.
This recipe builds a Rust library compiled to WebAssembly with wasm-pack. CI runs wasm-pack test in headless Chrome and Node, builds the npm-ready package, and publishes it to npm on a version tag.
What the pipeline does
- install the Rust toolchain and wasm-pack
- run wasm-pack test in headless Chrome and Node
- build the package with wasm-pack build
- on a tag, publish to npm
- use npm provenance via OIDC
The workflow
wasm-pack test --headless --chrome runs wasm-bindgen tests in a real browser. wasm-pack build --target bundler emits an npm package; npm publish ships it on a tag.
name: CI
on:
push:
branches: [main]
tags: ["v*"]
pull_request:
jobs:
build:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
- run: wasm-pack test --headless --chrome
- run: wasm-pack test --node
- run: wasm-pack build --target bundler
- if: startsWith(github.ref, 'refs/tags/v')
uses: actions/setup-node@v4
with:
node-version: 20
registry-url: https://registry.npmjs.org
- if: startsWith(github.ref, 'refs/tags/v')
run: npm publish --provenance --access public
working-directory: pkg
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}Caching and speed
Swatinem/rust-cache caches the wasm build artifacts. Compiling to wasm32 plus headless browser tests is heavy; cheaper managed runners such as Latchkey (around 69% cheaper than GitHub-hosted) keep the suite fast and auto-retry a flaky browser-driver or crates.io fetch.
Release output
wasm-pack build emits the package into pkg/. npm publish --provenance attaches a signed provenance statement via OIDC. Store NPM_TOKEN as a secret; the package ships with the .wasm binary and generated JS bindings.
Key takeaways
- Run wasm-pack test in both headless Chrome and Node for full coverage.
- Build with --target bundler for an npm-consumable package.
- Publish with --provenance so consumers can verify the build origin.