mirror of
https://github.com/penpot/penpot.git
synced 2026-09-19 02:16:14 +00:00
Drop the ignored-since-pnpm-11 onlyBuiltDependencies entry from render-wasm/pnpm-workspace.yaml, keeping allowBuilds as the single source of build approvals. Clarify the updating-pnpm gotcha so it no longer claims pnpm writes ignoredBuiltDependencies. AI-assisted-by: muse-spark-1.3-contributor
4.8 KiB
4.8 KiB
Updating pnpm Across All Workspaces
Canonical procedure. Run it from the repo root with the log redirected to a file (never pipe tool output through filters).
Layout facts
- The repo has 11 pnpm workspaces, each with its own
pnpm-workspace.yamlandpnpm-lock.yaml: the repo root plusbackend,common,docs,exporter,frontend,library,mcp,media-processor,plugins, andrender-wasm. - Every package inside a module workspace (for example all
plugins/apps/*andplugins/libs/*packages) is a plain member of that module's workspace. Members must not carry their ownpnpm-workspace.yamlorpnpm-lock.yaml; their dependencies resolve through the parent workspace's lockfile. - One shared pnpm store for the whole repo:
<repo>/.pnpm-store. Every workspace yaml sets it explicitly:storeDir: .pnpm-storeat the root,storeDir: ../.pnpm-storein each module. pnpm resolves the value against the workspace root, so all workspaces land on the same store. Do not remove these lines: nested workspaces do not inherit settings, and without them each workspace may resolve a different store. - The store survives
node_modulescleans. It is content-addressed and integrity-verified, so it cannot go stale; staleness lives in node_modules. Onlyscripts/clean-node-modules --storeremoves it. - Every
package.json(about 35 of them) must carry apackageManagerfield with the identicalpnpm@<version>+sha512.<hash>value. Do not let them drift. - CI pins no pnpm version; workflows rely on corepack reading
packageManager. Fixing the fields fixes CI.
Procedure
- Resolve the target tag first and note the version. Example:
npm view pnpm dist-tags --jsonfornext-12(latest 12.x). The tag moves over time; always re-check. - List every directory with a
package.json, excludingnode_modules(fd -H -t f package.json -E node_modules). This list is the work set; do not maintain a hand-written list. - Run
corepack use pnpm@<tag>in workspace roots first, then members.corepack usestampspackageManagerin the nearest package.json and runs an install. Member runs repeat the workspace install; after the root run they are quick no-ops. - If a run fails, fix the cause (see gotchas) and re-run that directory.
Gotchas
corepack useonly updates an existingpackageManagerfield. If a package.json lacks the field, corepack walks up to the nearest ancestor that has one and stamps that file instead; the member stays unstamped. After the sweep, assert every package.json carries the field. For a missing one, insert the identicalpnpm@<version>+sha512.<hash>string, then re-runcorepack use pnpm@<tag>in that directory.- A workspace may fail with
ERR_PNPM_IGNORED_BUILDS, and pnpm then writes a placeholder scaffold into itspnpm-workspace.yaml:allowBuilds: esbuild: set this to true or false. Current pnpm writes only theallowBuildsplaceholder; any legacy key still present (ignoredBuiltDependencies,onlyBuiltDependencies,neverBuiltDependencies) is ignored since pnpm 11. Repo convention isallowBuilds: esbuild: true. Replace the placeholder and drop the legacy entry, then re-run. plugins/apps/composable-test-suiteonce had its ownpnpm-workspace.yamland acted as a nested workspace root. That state is gone on purpose: pnpm picks the nearestpnpm-workspace.yamlwalking up, so a nested one silently forks install and lockfile behavior. Do not reintroduce it.- Expect metadata-only lockfile diffs when only the pnpm version moves:
the pnpm self-reference entries, plus a new
packageManagerDependenciessection in lockfiles last written by older pnpm. Large diffs mean re-resolution; inspect them before accepting.
Verification
- Every
packageManagerfield is byte-identical (same version and hash). pnpm --versionin each workspace prints the target version.pnpm install --frozen-lockfilesucceeds in each of the 11 workspaces.git diffon lockfiles matches the expectations above.
Cleaning stale node_modules
scripts/clean-node-modulesremoves every workspacenode_modules: the repo root, all module workspaces, and all member packages. Use it when installs misbehave after dependency changes: clean, reinstall, done.- Flags:
-n/--dry-runlists without deleting;--storealso removes the shared pnpm store at<repo>/.pnpm-store(the next install re-downloads what it held).external/(vendored dependency trees with their own lifecycles) and.opencode/are always ignored. - The script never touches the pnpm store by default, so the reinstall after cleaning reuses cached packages (zero downloads).
- After cleaning, run
pnpm installin each workspace root to restore the development environment;frontendpostinstall also reinstalls and buildsplugins-runtime.