Skip to content

CI/CD

pubm is designed to behave well in both local terminals and CI runners. The normal pipeline already knows how to consume pending changesets during versioning, so you do not need a separate pubm changesets version step just to prepare CI.

pubm init can generate CI workflows during setup. The wizard offers to create .github/workflows/release.yml for tag-triggered publish and .github/workflows/changeset-check.yml for PR changeset enforcement, so you do not need to write them by hand.

Use two phases:

  1. run pubm --mode ci --phase prepare locally or in a controlled release job
  2. publish from CI with pubm --mode ci --phase publish
Terminal window
pubm --mode ci --phase prepare
Terminal window
pubm --mode ci --phase publish

pubm --mode ci --phase prepare is more than a token check. It runs the release pipeline up to the point right before the real publish:

  • collects registry tokens and plugin credentials
  • optionally syncs them to GitHub Secrets
  • runs prerequisite and required-condition checks
  • runs tests and build unless skipped
  • consumes pending changesets during versioning when present
  • creates the release commit and pushes tags and branch updates
  • dry-runs publish tasks instead of performing the real publish

Because of that, you do not need to run pubm patch --dry-run after CI preparation.

In CI, provide registry tokens with environment variables:

VariableRegistry
NODE_AUTH_TOKENnpm
JSR_TOKENjsr
CARGO_REGISTRY_TOKENcrates.io

Plugins can also declare their own required credentials. pubm collects and resolves these automatically. During --ci-prepare it prompts for missing values and syncs them to GitHub Secrets. During --phase publish it reads the resolved values from the environment only and errors if any required credential is absent.

For example, @pubm/plugin-brew requires:

VariablePurpose
PUBM_BREW_GITHUB_TOKENGitHub PAT used to push formula updates and open pull requests for Homebrew.

If you already stored tokens locally through a CI preparation run, push them into GitHub Secrets with:

Terminal window
pubm secrets sync
pubm secrets sync --registry npm,jsr
name: Release
on:
push:
tags:
- "v*"
- "@*"
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 24
- run: pnpm install --frozen-lockfile
- run: pubm --mode ci --phase publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }}
JSR_TOKEN: ${{ secrets.JSR_TOKEN }}
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}

Use pubm snapshot to publish preview versions from CI without creating a real release. This is useful for testing package changes before a full release.

- name: Publish snapshot
run: npx pubm snapshot
env:
NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }}

For monorepos, you can filter which packages to snapshot:

- name: Publish snapshot
run: npx pubm snapshot --filter @acme/core --filter @acme/react
env:
NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }}

Snapshot versions are published with a temporary version number derived from the base version, tag, timestamp, and commit hash. They do not affect normal release versioning.

Tag-based and history-aware operations need full Git information. Use fetch-depth: 0 for release jobs.

pubm will not be able to prompt in CI. If a token is absent, the run fails.

Use automation-compatible tokens for CI publish.

If you publish from dist/, ensure your workflow actually creates dist/ before pubm --mode ci --phase publish.

If your project uses releaseAssets in pubm.config.ts, pubm --mode ci --phase publish runs the asset pipeline and uploads the artifacts to the GitHub Release automatically.

GitHub Release creation and asset upload use the GitHub API. Provide GITHUB_TOKEN (or a fine-grained token with contents: write permission). The token is needed for all GitHub Release creation, not just asset uploads:

- run: pubm --mode ci --phase publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

GitHub Actions injects GITHUB_TOKEN as a built-in secret in every workflow run. You do not need to create it manually, just pass it through the environment.

The asset pipeline runs after the build step. Make sure your workflow produces the binary artifacts (e.g., compiled binaries in platforms/*/bin/) before pubm --mode ci --phase publish executes. If a configured glob pattern matches zero files at upload time, pubm treats it as an error.

name: Release
on:
push:
tags:
- "v*"
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: 24
- run: npm ci
- run: npm run build # Must produce platforms/*/bin/mytool
- run: pubm --mode ci --phase publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

As an alternative to pushing version bump commits directly, pubm can create a pull request instead. This is useful when your base branch is protected or you want a review step before publishing.

Enable it in config:

export default defineConfig({
createPr: true,
});

Or pass the flag at runtime:

Terminal window
pubm --create-pr

When createPr is enabled:

  • pubm creates a pubm/version-packages-* branch with the version bump commit
  • the branch is pushed and a PR is opened against the base branch
  • the PR is automatically labeled no-changeset to skip the changeset check
  • when the PR is merged, the existing release workflow triggers normally via the tag push

pubm also falls back to PR mode automatically when a direct push to a protected branch fails, so you do not need to configure createPr explicitly if you only want the fallback behavior.

Use the syi0808/pubm-actions GitHub Action to enforce that every PR includes a changeset. pubm init generates this workflow automatically when changesets are enabled.

name: Changeset Check
on:
pull_request:
types: [opened, synchronize, reopened, labeled, unlabeled]
permissions:
contents: read
pull-requests: write
jobs:
changeset-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: syi0808/pubm-actions@v1
with:
skip-label: no-changeset

The action detects new .pubm/changesets/*.md files in the PR diff, validates their format, and posts a comment with the result. Add the no-changeset label to skip the check for PRs that don’t need a changeset (docs, CI config, etc.).