Skip to main content
Version: Next

A pnpm workspace

Releasing a pnpm workspace takes the same shape as an npm monorepo. You will notice three differences that come from the package manager rather than from dispat. The lock file lives at the workspace root, internal ranges use the workspace: protocol, and pnpm publish checks your git tree state.

{
"scripts": {
"pnpm-build": "pnpm install --frozen-lockfile && pnpm run build",
"pnpm-publish": "pnpm publish --access public --no-git-checks",
"pnpm-lock": "pnpm install --lockfile-only"
},
"spaces": {
"libs": {
"path": "packages",
"autoVersion": {
"enabled": true,
"range": "workspace:*",
"syncLock": [
"pnpm-lock"
]
},
"flow": {
"build": "pnpm-build",
"publish": "pnpm-publish"
}
}
},
"commit": {
"enabled": true,
"include": [
"pnpm-lock.yaml"
]
}
}
  • The install runs from the package folder and installs the workspace anyway. pnpm looks upward for pnpm-workspace.yaml. Your build stage does not need -C ../... Pass --frozen-lockfile to make the stage fail locally on a mismatched lock file, instead of quietly resolving something new mid-release.
  • workspace:* ranges stay as they are. autoVersion writes each package's own version field. pnpm publish substitutes that version for the workspace: specifier when it packs, so your declared ranges never need rewriting. Set range: "workspace:*" to write this literal back verbatim and keep the protocol intact.
  • pnpm-lock.yaml is outside every package folder. Use syncLock to regenerate it after the version stage, and add it to commit.include to put it in the release commit. Without this line, your release commit carries rewritten manifests and a stale lock file. The one-at-a-time syncLockConcurrency default matters here because every package in the workspace regenerates the same file.
  • --no-git-checks. pnpm publish refuses to publish from a dirty working tree or an unapproved branch. A dispat run creates exactly that situation, because the version stage rewrites manifests and dispat creates the release commit after the publishes. Pass this flag to bypass the check and rely on the annotated tag as the record of what shipped.

Yarn workspaces work the same way. Put yarn.lock in commit.include and use yarn npm publish in the publish slot.

Keep publisher trust consistent across release lines​

pnpm's trustPolicy: no-downgrade rejects a package version when an earlier-published version had stronger publisher evidence. This is conditional: token publishing does not fail by itself, but switching one release to npm trusted publishing and later returning to a token can make installs of later versions fail under that policy. A provenance attestation does not satisfy pnpm's trusted-publisher check.

This matters when one npm package has several maintained release lines. Before migrating any line, confirm that every publishing workflow can use the package's trusted-publisher configuration. Keep the authentication method consistent across the lines, and exercise the consumer policy in an isolated verification project with scripts disabled:

pnpm add --ignore-scripts --trust-policy no-downgrade your-package@the-published-version

Restoring consistent publisher evidence is the release-side fix; weakening the consumer trust policy would hide the downgrade. dispat can run each line's native publish command, but npm owns the publisher configuration and authorization constraint.