Subchapter 9.19
references/features-versioning.mdMarkdown5 KBView on GitHub
pnpm versions and releases a workspace without a separate release tool. Two halves:
pnpm change records change intents — markdown files in .changeset/ (changesets format) naming affected packages, bump types, and a changelog summary. Commit them with the change.pnpm version -r consumes pending intents: bumps versions, propagates to dependents, writes changelogs, and records what it consumed in a committed ledger.An existing .changeset/ keeps working; you can still use the Changesets CLI instead.
pnpm change # interactive prompt
pnpm change --bump patch --summary "Fix crash" @ex/core # non-interactive (scripts)
pnpm change status # pending intents + release planWrites e.g. .changeset/calm-cats-resolve.md:
---
"@example/core": minor
---
Added a `--watch` flag to the build command.--bump accepts none|patch|minor|major (none = explicit “no release”). When two projects share a name, reference one by ./-prefixed directory ("./packages/cli": minor).
pnpm version -r # consume intents, bump, changelog, ledger
pnpm version -r --dry-run # preview
pnpm version -r --filter … # narrow (selection expands to settle deps/fixed groups)No git commit/tag is created (many packages, many versions) — commit yourself, then pnpm publish -r. Working tree must be clean unless --dry-run/--no-git-checks. Every package bumped through a workspace: range to a bumped dependency is bumped too. First release of a package publishes the manifest version verbatim (v11.16.0+); private packages skip that registry check and always use committed CHANGELOG.md (repository storage). Bumps run preversion/version/postversion scripts (skipped by --dry-run/ignoreScripts); gitTagVersion: false and tagVersionPrefix can be set in pnpm-workspace.yaml. pnpm version -r outside a workspace fails with ERR_PNPM_WORKSPACE_ONLY.
versioning:
fixed:
- ['@example/cli', '@example/napi'] # always release at one shared version
ignore:
- '@example/internal' # excluded from versioning + propagation
maxBump: minor # cap the bump this checkout may apply
lanes:
'@example/cli': alpha # parallel release track
epics:
- lead: '@example/app'
packages: ['./packages/**', '!./packages/private-*']
changelog:
storage: repository # commit CHANGELOG.md (default: registry)registry (default) composes each section at publish time into the tarball, no committed CHANGELOG.md; repository commits one per package.A lane is a parallel release track. A package on lane alpha releases X.Y.Z-alpha.N prereleases from the same runs that ship stable versions of everything on main.
pnpm lane alpha --filter @example/cli # move onto alpha (--filter required)
pnpm lane main --filter @example/cli # graduate to stable on next version -r
pnpm lane # show membershipN counts from 0 and restarts when the stable target changes. A package already on another lane can’t move directly (ERR_PNPM_VERSIONING_ALREADY_ON_LANE): go through main first. An empty --filter match fails with ERR_PNPM_VERSIONING_NO_PACKAGES. Lane names: alphanumerics/hyphens, not purely numeric; main is reserved.
An epic ties member packages to a lead, constraining each member’s major to a band: while the lead is on major M, members live in M*100…M*100+99 (lead on 11.x ⇒ members in 1100–1199). A bump past the ceiling is rejected until the lead advances; when the lead hits a new major, members re-base to the band floor in the same plan.
pnpm change check # (v12.4.0) validate pending intents (plans the release; fails on e.g. an intent naming a package outside the workspace) + committed versions against epic bands and fixed groups — run on every PRpnpm version -r records consumed intents in .changeset/ledger.yaml (committed, append-only). Consumption is tracked per project — an intent file is deleted only once every project it names has released, making cherry-picks/merge-backs between release branches safe.
For registries declared serverType: pnpr, registry storage sends each section as the version’s release notes instead of packing it into the tarball. Intents naming one package go to its notes; intents naming several go once into the release notes (named v<version> after the epic lead or the one fixed group). pnpm publish -r --batch sends the whole release in one request; pnpm version -r --release-notes <file> adds a hand-written summary above the composed notes; pnpm publish --publication-name names the release.