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.
Recommended release model
Section titled “Recommended release model”Use two phases:
- run
pubm --mode ci --phase preparelocally or in a controlled release job - publish from CI with
pubm --mode ci --phase publish
pubm --mode ci --phase preparepubm --mode ci --phase publishWhat CI preparation does
Section titled “What CI preparation does”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.
Required environment variables
Section titled “Required environment variables”In CI, provide registry tokens with environment variables:
| Variable | Registry |
|---|---|
NODE_AUTH_TOKEN | npm |
JSR_TOKEN | jsr |
CARGO_REGISTRY_TOKEN | crates.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:
| Variable | Purpose |
|---|---|
PUBM_BREW_GITHUB_TOKEN | GitHub PAT used to push formula updates and open pull requests for Homebrew. |
Syncing GitHub secrets
Section titled “Syncing GitHub secrets”If you already stored tokens locally through a CI preparation run, push them into GitHub Secrets with:
pubm secrets syncpubm secrets sync --registry npm,jsrExample GitHub Actions structure
Section titled “Example GitHub Actions structure”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 }}Snapshot releases in CI
Section titled “Snapshot releases in CI”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.
Common CI pitfalls
Section titled “Common CI pitfalls”Shallow checkout
Section titled “Shallow checkout”Tag-based and history-aware operations need full Git information. Use fetch-depth: 0 for release jobs.
Missing registry tokens
Section titled “Missing registry tokens”pubm will not be able to prompt in CI. If a token is absent, the run fails.
npm 2FA token mismatch
Section titled “npm 2FA token mismatch”Use automation-compatible tokens for CI publish.
Build output is not present in contents
Section titled “Build output is not present in contents”If you publish from dist/, ensure your workflow actually creates dist/ before pubm --mode ci --phase publish.
GitHub Release assets
Section titled “GitHub Release assets”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_TOKEN requirement
Section titled “GITHUB_TOKEN requirement”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.
Build outputs must exist before upload
Section titled “Build outputs must exist before upload”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.
Example with release assets
Section titled “Example with release assets”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 }}PR-based version bump workflow
Section titled “PR-based version bump workflow”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:
pubm --create-prWhen 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-changesetto 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.
Changeset check (PR validation)
Section titled “Changeset check (PR validation)”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-changesetThe 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.).
Next steps
Section titled “Next steps”- Read the Troubleshooting guide for failure diagnosis.
- Read the CLI Reference for every execution flag used in CI.
- Read the Release Assets guide to configure
releaseAssetsin your project.