Skip to content

Commit 401406a

Browse files
acozzetteclaude
andauthored
feat: add support for pnpm 11 (#2802)
pnpm 11 introduced several breaking changes to the lockfile format that this commit addresses: 1. patchedDependencies path moved to pnpm-workspace.yaml: pnpm 11 no longer includes the patch file path in pnpm-lock.yaml (only the hash). Add _normalize_patched_dependencies() to look up the path from pnpm-workspace.yaml and restore the dict form expected by the rest of the code. 2. Multi-document lockfile format: in some situations, such as when configDependencies are present, pnpm 11 prepends an "env lockfile" YAML document to pnpm-lock.yaml. Update the yq invocation to always return the last document regardless of whether the file has one or two YAML documents. 3. Changed peer dependency path encoding in snapshot keys: pnpm 11 encodes workspace-relative peer dep paths with a leading '+' (e.g. `@scoped/b@+projects+b` instead of `@scoped/b@projects+b`), which changes the generated virtual store target names. Also adds v110 test fixtures (lockfile, workspace config, snapshots) and reorganizes the e2e/pnpm_lockfiles setup so each version (v90, v101, v110) is self-contained. v90 needs its own package.json and pnpm-workspace.yaml, because pnpm 9 requires some things to be in package.json that are expected in pnpm-workspace.yaml in later versions. Fixes #2798. --- ### Changes are visible to end-users: yes - Searched for relevant documentation and updated as needed: yes - Breaking change (forces users to change their own code or config): no - Suggested release notes appear below: no ### Test plan - New test cases added --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent a55809f commit 401406a

38 files changed

Lines changed: 4091 additions & 270 deletions

docs/pnpm.md

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -271,10 +271,7 @@ npm packages have "lifecycle scripts" such as `postinstall` which are documented
271271

272272
We refer to these as "lifecycle hooks".
273273

274-
The lifecycle hooks of a package are determined by the `package.json` [`pnpm.onlyBuiltDependencies` attribute](https://pnpm.io/package_json#pnpmonlybuiltdependencies).
275-
276-
If `pnpm.onlyBuiltDependencies` is unspecified `npm_translate_lock` will fallback to the legacy pnpm lockfile `requiresBuild` attribute.
277-
This attribute is only available in pnpm _before_ v9, see [pnpm #7707](https://github.com/pnpm/pnpm/issues/7707) for reasons why this attribute was removed.
274+
The lifecycle hooks of a package are determined by [allowBuilds](https://pnpm.io/next/settings#allowbuilds). (The `package.json` [`pnpm.onlyBuiltDependencies` attribute](https://pnpm.io/package_json#pnpmonlybuiltdependencies) also works for this and is needed for pnpm versions prior to 10.26).
278275

279276
When a package has lifecycle hooks the `lifecycle_*` attributes are applied to filter which hooks are run and how they are run.
280277

e2e/pnpm_lockfiles/.bazelignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ cases/nested-peer-v9/node_modules
99
cases/workspace-peer-v9/node_modules
1010
cases/workspace-peer-v9/libs/chokidar/node_modules
1111
cases/isaacs-cliui-v90/node_modules
12+
cases/multi-document-v11/node_modules
1213
cases/override-with-alias-url-v9/node_modules
1314
projects/a/node_modules
1415
projects/a-types/node_modules
@@ -21,4 +22,5 @@ projects/peers-combo-1/node_modules
2122
projects/peers-combo-2/node_modules
2223
v90/node_modules/
2324
v101/node_modules/
25+
v110/node_modules/
2426
vendored/is-number/node_modules

e2e/pnpm_lockfiles/MODULE.bazel

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ local_path_override(
88
PNPM_LOCK_VERSIONS = [
99
"v90",
1010
"v101",
11+
"v110",
1112
]
1213

1314
# Lockfiles with unique test cases
@@ -19,6 +20,7 @@ PNPM_LOCK_TEST_CASES = [
1920
"nested-peer-v9",
2021
"rerooted-nested-projects-v10/root",
2122
"workspace-peer-v9",
23+
"multi-document-v11",
2224
]
2325

2426
bazel_dep(name = "bazel_lib", version = "3.0.0")

e2e/pnpm_lockfiles/base/pnpm-workspace.yaml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,30 @@ packages:
22
- '.'
33
- '../projects/*'
44
- '../vendored/*'
5+
6+
# The presence of configDependencies causes pnpm-lock.yaml to be a
7+
# multi-document YAML file with pnpm 11.
8+
configDependencies:
9+
semver: 7.7.4+sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==
10+
11+
# patchedDependencies, allowBuilds (or onlyBuiltDependencies), and overrides
12+
# are duplicated in package.json, and should be kept in sync for as long as we
13+
# maintain support for pnpm 9. Once we drop support for pnpm 9, we should
14+
# delete that information from package.json.
15+
patchedDependencies:
16+
meaning-of-life@1.0.0: patches/meaning-of-life@1.0.0-pnpm.patch
17+
18+
allowBuilds:
19+
'@aspect-test/c': true
20+
21+
# pnpm 11 defaults this to true, which blocks URL-based dependencies from being
22+
# used as subdependencies; the test intentionally uses a URL override for diff,
23+
# so this needs to be disabled
24+
blockExoticSubdeps: false
25+
26+
overrides:
27+
is-number: 'file:../vendored/is-number'
28+
diff: 'https://github.com/kpdecker/jsdiff/archive/refs/tags/v5.2.0.tar.gz'
29+
fsevents: '^2.3'
30+
typescript: '5.5.2'
31+
'@types/glob': '^8.1.0'
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
load("@bazel_skylib//rules:build_test.bzl", "build_test")
2+
load("@multi-document-v11//:defs.bzl", multi_document_v11_link_all = "npm_link_all_packages")
3+
4+
exports_files(["pnpm-lock.yaml"])
5+
6+
multi_document_v11_link_all()
7+
8+
# Verify that rules_js can parse a pnpm 11 multi-document lockfile (where
9+
# configDependencies cause an env lockfile to be prepended as a second YAML
10+
# document) and correctly resolves the main lockfile from the last document.
11+
# :node_modules/ms only appears in the second document, so its presence proves
12+
# we are reading the correct document.
13+
build_test(
14+
name = "multi_document_v11",
15+
targets = [
16+
":node_modules",
17+
":node_modules/ms",
18+
],
19+
)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"name": "config-deps-v11",
3+
"version": "0.0.0",
4+
"dependencies": {
5+
"ms": "^2.1.3"
6+
}
7+
}

e2e/pnpm_lockfiles/cases/multi-document-v11/pnpm-lock.yaml

Lines changed: 43 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
packages:
2+
- '.'
3+
4+
configDependencies:
5+
semver: 7.7.4+sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==
6+
7+
allowBuilds: {}

e2e/pnpm_lockfiles/lockfile-test.bzl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,10 @@ def lockfile_test(npm_link_all_packages, name = None):
145145
":node_modules/scoped/bad",
146146
":.aspect_rules_js/node_modules/@scoped+a@0.0.0",
147147
":.aspect_rules_js/node_modules/@scoped+b@0.0.0",
148-
":.aspect_rules_js/node_modules/@scoped+c@file+..+projects+c_@scoped+b@projects+b",
148+
# Workaround for peer suffixes changing in pnpm 11. We may want to
149+
# revisit this depending on the outcome of:
150+
# https://github.com/pnpm/pnpm/issues/11272
151+
":.aspect_rules_js/node_modules/@scoped+c@file+..+projects+c_@scoped+b@%sprojects+b" % ("+" if lock_version == "v110" else ""),
149152
":.aspect_rules_js/node_modules/@scoped+d@0.0.0",
150153

151154
# file: 4.17.21.tgz tarbal

e2e/pnpm_lockfiles/setup.sh

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@
22

33
# 9.0 - pnpm v9.0.0 bumped the lockfile version to 9.0; this includes breaking changes regarding lifecycle hooks and patches
44
# 10.0 - pnpm v10 kept the lockfile version at 9.0, but has minor differences such as length of hashes, yaml key order etc.
5+
# 11.0 - pnpm v11 kept the lockfile version at 9.0 and made several minor changes
56

67
# pnpm v9.0.0 bumped the lockfile version to 9.0
7-
pushd base && npx -y pnpm@~9 install --lockfile-only && mv pnpm-lock.yaml ../v90 && popd
8+
pushd v90 && npx -y pnpm@~9 install --lockfile-only && popd
89

910
# pnpm v10
10-
pushd base && npx -y pnpm@~10 install --lockfile-only && mv pnpm-lock.yaml ../v101 && popd
11+
pushd v101 && npx -y pnpm@~10 install --lockfile-only && popd
12+
13+
# pnpm v11 rc
14+
pushd v110 && npx -y pnpm@next-11 install --lockfile-only && popd

0 commit comments

Comments
 (0)