mirror of
https://github.com/penpot/penpot.git
synced 2026-09-10 05:58:47 +00:00
🔧 Pin all pnpm workspaces to one shared pnpm store
Set storeDir in every pnpm-workspace.yaml: `.pnpm-store` at the repo root and `../.pnpm-store` in the ten module workspaces, so all of them resolve to <repo>/.pnpm-store. pnpm resolves the value against the workspace root, and nested workspaces do not inherit settings, which had left the root workspace and the modules on two different stores. Add scripts/clean-node-modules: removes every workspace node_modules in one pass (ignores external/ and .opencode/), keeps the shared store unless --store removes it too. Verified: every workspace resolves the same store path; reinstalls after a full clean reuse the cache with zero downloads; frozen-lockfile installs pass in all 11 workspaces with no lockfile changes; the frontend storybook suite stays green. AI-assisted-by: omen-alpha
This commit is contained in:
parent
f68c266380
commit
5c474939ac
@ -74,6 +74,10 @@ module. You can read it from `mem:<MODULE>/core`
|
|||||||
- `scripts/error-reports.mjs` — Query error reports via RPC API with token
|
- `scripts/error-reports.mjs` — Query error reports via RPC API with token
|
||||||
authentication. Supports list/get operations with filtering and pagination.
|
authentication. Supports list/get operations with filtering and pagination.
|
||||||
See `mem:scripts/error-reports`.
|
See `mem:scripts/error-reports`.
|
||||||
|
- `scripts/clean-node-modules` — Remove stale `node_modules` from all pnpm
|
||||||
|
workspaces (root, modules, member packages). Keeps the shared pnpm store
|
||||||
|
at `<repo>/.pnpm-store` unless `--store`; ignores `external/` and
|
||||||
|
`.opencode/`. Usage and reinstall steps: `mem:workflow/updating-pnpm`.
|
||||||
|
|
||||||
# Dependency graph
|
# Dependency graph
|
||||||
|
|
||||||
|
|||||||
@ -14,6 +14,15 @@ file (never pipe tool output through filters).
|
|||||||
workspace. Members must not carry their own `pnpm-workspace.yaml` or
|
workspace. Members must not carry their own `pnpm-workspace.yaml` or
|
||||||
`pnpm-lock.yaml`; their dependencies resolve through the parent
|
`pnpm-lock.yaml`; their dependencies resolve through the parent
|
||||||
workspace's lockfile.
|
workspace's lockfile.
|
||||||
|
- One shared pnpm store for the whole repo: `<repo>/.pnpm-store`. Every
|
||||||
|
workspace yaml sets it explicitly: `storeDir: .pnpm-store` at the root,
|
||||||
|
`storeDir: ../.pnpm-store` in 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_modules` cleans. It is content-addressed and
|
||||||
|
integrity-verified, so it cannot go stale; staleness lives in
|
||||||
|
node_modules. Only `scripts/clean-node-modules --store` removes it.
|
||||||
- Every `package.json` (about 35 of them) must carry a `packageManager` field
|
- Every `package.json` (about 35 of them) must carry a `packageManager` field
|
||||||
with the identical `pnpm@<version>+sha512.<hash>` value. Do not let them drift.
|
with the identical `pnpm@<version>+sha512.<hash>` value. Do not let them drift.
|
||||||
- CI pins no pnpm version; workflows rely on corepack reading
|
- CI pins no pnpm version; workflows rely on corepack reading
|
||||||
@ -63,3 +72,18 @@ file (never pipe tool output through filters).
|
|||||||
- `pnpm --version` in each workspace prints the target version.
|
- `pnpm --version` in each workspace prints the target version.
|
||||||
- `pnpm install --frozen-lockfile` succeeds in each of the 11 workspaces.
|
- `pnpm install --frozen-lockfile` succeeds in each of the 11 workspaces.
|
||||||
- `git diff` on lockfiles matches the expectations above.
|
- `git diff` on lockfiles matches the expectations above.
|
||||||
|
|
||||||
|
## Cleaning stale node_modules
|
||||||
|
|
||||||
|
- `scripts/clean-node-modules` removes every workspace `node_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-run` lists without deleting; `--store` also 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 install` in each workspace root to restore the
|
||||||
|
development environment; `frontend` postinstall also reinstalls and
|
||||||
|
builds `plugins-runtime`.
|
||||||
|
|||||||
@ -1,2 +1,4 @@
|
|||||||
|
storeDir: ../.pnpm-store
|
||||||
|
|
||||||
minimumReleaseAgeExclude:
|
minimumReleaseAgeExclude:
|
||||||
- brace-expansion@5.0.8 || 5.0.9
|
- brace-expansion@5.0.8 || 5.0.9
|
||||||
|
|||||||
@ -1 +1,3 @@
|
|||||||
|
storeDir: ../.pnpm-store
|
||||||
|
|
||||||
minimumReleaseAge: 0
|
minimumReleaseAge: 0
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
storeDir: ../.pnpm-store
|
||||||
|
|
||||||
minimumReleaseAgeExclude:
|
minimumReleaseAgeExclude:
|
||||||
- undici@7.28.0 || 7.29.0
|
- undici@7.28.0 || 7.29.0
|
||||||
- js-yaml@3.15.0 || 4.3.0
|
- js-yaml@3.15.0 || 4.3.0
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
storeDir: ../.pnpm-store
|
||||||
|
|
||||||
allowBuilds:
|
allowBuilds:
|
||||||
core-js-pure: false
|
core-js-pure: false
|
||||||
minimumReleaseAgeExclude:
|
minimumReleaseAgeExclude:
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
storeDir: ../.pnpm-store
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
- "packages/draft-js"
|
- "packages/draft-js"
|
||||||
- "packages/mousetrap"
|
- "packages/mousetrap"
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
storeDir: ../.pnpm-store
|
||||||
|
|
||||||
minimumReleaseAgeExclude:
|
minimumReleaseAgeExclude:
|
||||||
- brace-expansion@5.0.8 || 5.0.9
|
- brace-expansion@5.0.8 || 5.0.9
|
||||||
patchedDependencies:
|
patchedDependencies:
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
storeDir: ../.pnpm-store
|
||||||
|
|
||||||
allowBuilds:
|
allowBuilds:
|
||||||
esbuild: true
|
esbuild: true
|
||||||
sharp: false
|
sharp: false
|
||||||
|
|||||||
@ -1,2 +1,4 @@
|
|||||||
|
storeDir: ../.pnpm-store
|
||||||
|
|
||||||
allowBuilds:
|
allowBuilds:
|
||||||
esbuild: true
|
esbuild: true
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
storeDir: ../.pnpm-store
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
- 'apps/**'
|
- 'apps/**'
|
||||||
- 'libs/**'
|
- 'libs/**'
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
storeDir: .pnpm-store
|
||||||
|
|
||||||
allowBuilds:
|
allowBuilds:
|
||||||
esbuild: true
|
esbuild: true
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
storeDir: ../.pnpm-store
|
||||||
|
|
||||||
allowBuilds:
|
allowBuilds:
|
||||||
esbuild: true
|
esbuild: true
|
||||||
onlyBuiltDependencies:
|
onlyBuiltDependencies:
|
||||||
|
|||||||
91
scripts/clean-node-modules
Executable file
91
scripts/clean-node-modules
Executable file
@ -0,0 +1,91 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Remove node_modules directories across the monorepo's pnpm workspaces:
|
||||||
|
# the repo root, all module workspaces, and all workspace member packages.
|
||||||
|
#
|
||||||
|
# Use it when node_modules are stale or corrupted and a clean reinstall is
|
||||||
|
# cheaper than debugging. Reinstall afterwards with `pnpm install` in each
|
||||||
|
# workspace root (root, backend, common, docs, exporter, frontend, library,
|
||||||
|
# mcp, media-processor, plugins, render-wasm).
|
||||||
|
#
|
||||||
|
# external/ (vendored dependency trees) and .opencode/ are always ignored.
|
||||||
|
# The pnpm content-addressable store lives at <repo>/.pnpm-store, outside
|
||||||
|
# node_modules, and survives a default clean. `--store` removes it too;
|
||||||
|
# the next install re-downloads what it held.
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<'EOF'
|
||||||
|
Usage: scripts/clean-node-modules [options]
|
||||||
|
|
||||||
|
Remove every node_modules directory in the pnpm workspaces: the repo root,
|
||||||
|
all module workspaces, and all workspace member packages.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-n, --dry-run Print what would be removed without deleting anything.
|
||||||
|
--store Also delete the shared pnpm store at <repo>/.pnpm-store.
|
||||||
|
The next install re-downloads everything it held.
|
||||||
|
-h, --help Show this help.
|
||||||
|
|
||||||
|
external/ (vendored dependency trees) and .opencode/ are always ignored.
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
DRY_RUN=0
|
||||||
|
WITH_STORE=0
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
-n | --dry-run) DRY_RUN=1 ;;
|
||||||
|
--store) WITH_STORE=1 ;;
|
||||||
|
-h | --help) usage; exit 0 ;;
|
||||||
|
*) {
|
||||||
|
echo "error: unknown option: $1" >&2
|
||||||
|
usage >&2
|
||||||
|
exit 64
|
||||||
|
} ;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
cd "$ROOT"
|
||||||
|
|
||||||
|
if [[ $WITH_STORE -eq 1 && -d .pnpm-store ]]; then
|
||||||
|
size="$(du -sh .pnpm-store | cut -f1)"
|
||||||
|
if [[ $DRY_RUN -eq 1 ]]; then
|
||||||
|
echo "would remove: ./.pnpm-store (pnpm store, $size)"
|
||||||
|
else
|
||||||
|
echo "removing pnpm store: $ROOT/.pnpm-store ($size); the next install re-downloads it"
|
||||||
|
rm -rf .pnpm-store
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# -prune stops the descent, so only the top-most node_modules of each tree
|
||||||
|
# matches; nested dependency copies inside it die with their parent.
|
||||||
|
mapfile -t dirs < <(
|
||||||
|
find . \( -name .git -o -name external -o -name .opencode \) -type d -prune \
|
||||||
|
-o \( -name node_modules -type d -prune -print \)
|
||||||
|
)
|
||||||
|
|
||||||
|
if [[ ${#dirs[@]} -eq 0 ]]; then
|
||||||
|
echo "no node_modules directories found"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
cleaned=0
|
||||||
|
for dir in "${dirs[@]}"; do
|
||||||
|
if [[ $DRY_RUN -eq 1 ]]; then
|
||||||
|
echo "would remove: $dir"
|
||||||
|
else
|
||||||
|
rm -rf "$dir"
|
||||||
|
echo "removed: $dir"
|
||||||
|
fi
|
||||||
|
cleaned=$((cleaned + 1))
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ $DRY_RUN -eq 1 ]]; then
|
||||||
|
echo "$cleaned node_modules directories found"
|
||||||
|
else
|
||||||
|
echo "$cleaned node_modules directories cleaned"
|
||||||
|
fi
|
||||||
Loading…
x
Reference in New Issue
Block a user