The worker pool and the default workspaceConcurrency took the CPU count from os.availableParallelism(), which counts the CPUs in the process's affinity mask. In a container with a cgroup CPU quota smaller than that mask, such as a Kubernetes pod with a 4-CPU limit on a 233-CPU node, pnpm 11 created 232 workers per install, and four concurrent installs exhausted a 16 GiB memory limit while the workers were still loading. Node's libuv does try to apply the quota, but its cgroup v1 parser looks for ":cpu," and keeps "cpuacct:" in the path it builds, so it never finds the quota file there, and both it and Rust's standard library give up when the cgroup path from /proc/self/cgroup is not mounted under /sys/fs/cgroup, as happens with a host cgroup namespace and a bind-mounted controller. A new package, `@pnpm/os.available-parallelism`, reads the quota itself: the smallest limit/period walking from the process's cgroup up to the hierarchy root, for cgroup v2 (cpu.max) and v1 (cpu.cfs_quota_us and cpu.cfs_period_us), rounded down and floored at 1 like Rust's std::thread::available_parallelism, which pnpm 12 already uses. The cgroup directory is located through /proc/self/mountinfo, which says which cgroup each mount shows, so a container that sees only its own cgroup bind-mounted at /sys/fs/cgroup is read correctly; the standard mount points are the fallback. The worker pool and the config reader's workspace-concurrency default both use it, so the two stay in step. pnpm 12 is unaffected: every Rust pool is sized with std::thread::available_parallelism, which honours the quota. Closes pnpm/pnpm#17382
3.2 KiB
id, title
| id | title |
|---|---|
| recursive | pnpm -r, --recursive |
Aliases: m, multi, recursive, <command> -r
Runs a command in every project of a workspace, when used with the following commands:
installlistoutdatedpublishpackrebuildremoveunlinkupdatewhy
Runs a command in every project of a workspace, excluding the root project, when used with the following commands:
execruntestadd
If you want the root project be included even when running scripts, set the includeWorkspaceRoot setting to true.
Usage example:
pnpm -r publish
By default, recursive run, exec, and test execute projects in
topological order: dependencies run before their dependents. Use --no-sort
to disable graph ordering, or --parallel to start tasks without waiting for
dependencies.
Options
--link-workspace-packages
- Default: false
- Type: true, false, deep
Link locally available packages in workspaces of a monorepo into node_modules
instead of re-downloading them from the registry. This emulates functionality
similar to yarn workspaces.
When this is set to deep, local packages can also be linked to subdependencies.
Be advised that it is encouraged instead to use pnpm-workspace.yaml for this setting, to
enforce the same behaviour in all environments. This option exists solely so you
may override that if necessary.
--workspace-concurrency
- Default: the smaller of 4 and the number of available CPU cores
- Type: Number
Set the maximum number of tasks to run simultaneously. For unlimited concurrency
use Infinity.
In a container with a CPU quota, such as a Kubernetes CPU limit, the quota is the number of available CPU cores when it is smaller than the number of CPUs the container may run on. A fractional quota is rounded down, to at least 1.
You can set the workspace-concurrency as <= 0 and it will use the number of available CPU cores as: max(1, (number of available CPU cores) - abs(workspace-concurrency))
--[no-]bail
- Default: true
- Type: Boolean
If true, stops when a task throws an error.
This config does not affect the exit code.
Even if --no-bail is used, all tasks will finish but if any of the tasks fail,
the command will exit with a non-zero code.
Example (run tests in every package, continue if tests fail in one of them):
pnpm -r --no-bail test
--[no-]sort
- Default: true
- Type: Boolean
When true, commands follow the workspace dependency graph. Recursive run
also applies relationships from the tasks setting. Pass --no-sort to
remove graph ordering. This also makes tasks, --reverse, and --resume-from
inapplicable.
Example:
pnpm -r --no-sort test
--reverse
- Default: false
- Type: boolean
When true, dependency edges are reversed. For recursive run, this reverses
the resolved task graph, including relationships declared with dependsOn.
pnpm -r --reverse run clean