GitHub Action for building and maintaining npm package distribution branches.
# .github/workflows/build-dist.yml
name: Build dist branch
on:
workflow_dispatch:
jobs:
build-dist:
permissions:
contents: write
uses: runsascoded/npm-dist/.github/workflows/build-dist.yml@v1# .github/workflows/build-dist.yml
name: Build dist branch
on:
workflow_dispatch:
jobs:
build-dist:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: runsascoded/npm-dist@v1- Checks out your source code at the specified ref (or repository default branch)
- Auto-detects package manager from lock files (
pnpm-lock.yaml,yarn.lock,package-lock.json,bun.lockb) - Sets up the detected package manager and Node.js, installs dependencies
- Runs your build command (default:
<detected-pm> run build) - Creates/updates the dist branch with built artifacts at root
- Creates merge commits linking dist to source (two parents: previous dist + source)
- Pushes to the dist branch
- Outputs the dist SHA and install commands (in logs and as workflow annotations)
On first run (no dist branch exists), it auto-generates package.json by transforming paths from source (./dist/index.js → ./index.js). On subsequent runs, it preserves the dist branch's package.json.
After the workflow runs, you can install the package directly from the dist branch:
pnpm add github:owner/repo#<dist-sha>Or use pnpm-dep-source to manage switching between local, GitHub, and npm sources:
pds github <dep> dist| Input | Description | Default |
|---|---|---|
prebuilt_dir |
Path to pre-built output (skips checkout/setup/build) | '' |
source_ref |
Source ref to build from | Repository default branch |
node_version |
Node.js version | '20' |
pnpm_version |
pnpm version (only if pnpm detected) | '10' |
build_command |
Build command to run | Auto-detect |
dist_branch |
Name of dist branch | 'dist' |
build_dir |
Directory created by build command | 'dist' |
source_dirs |
Comma-separated directories to include (e.g., "src,types") |
'' |
extra_files |
Additional files to include (e.g., "README.md,LICENSE") |
'' |
version_suffix |
Add -dist.<sha> suffix to version |
'true' |
pkg_include |
package.json fields to include from source | (see below) |
pkg_exclude |
package.json fields to exclude | '' |
pkg_kvs |
JSON object of package.json overrides | '' |
Default pkg_include fields: name,description,keywords,repository,author,license,homepage,bugs,exports
For non-JS builds (Rust/WASM, Go, etc.) where you handle the build yourself, use prebuilt_dir to skip all setup and just manage the dist branch:
# Rust/WASM example
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: Swatinem/rust-cache@v2
- uses: jetli/wasm-pack-action@v0.4.0
- run: wasm-pack build --target web
- uses: runsascoded/npm-dist@v1
with:
prebuilt_dir: pkgWhen prebuilt_dir is set, npm-dist skips checkout, Node.js setup, dependency installation, and build command—it only manages the git operations for the dist branch.
For packages that don't use a dist/ output folder (e.g., pure ESM packages with generated types), use source_dirs to specify which directories to include:
- uses: runsascoded/npm-dist@v1
with:
source_ref: master
build_command: pnpm run build:types
source_dirs: src,typesThis preserves the specified directories as-is instead of moving dist/* to root.
- use-url-params (workflow)
- use-hotkeys (workflow)
- og-lambda (workflow)
- hyparquet (workflow) - uses
source_dirsmode - shapes (workflow) - Rust/WASM, uses
prebuilt_dirmode
- npm-dist (GitLab) - GitLab CI version of this tool
- pnpm-release - Sibling action for npm publishing and GitHub releases
MIT