chore: upgrade pnpm 9 → 11 with supply-chain protection#235
Conversation
- Upgrade pnpm 9.0.0 → 11.1.1 (packageManager, engines, corepack) - Add minimumReleaseAge: 4320 (3-day cooldown) to pnpm-workspace.yaml - Move overrides from package.json → pnpm-workspace.yaml (pnpm 11 requirement) - Add @internal/eslint-config and eslint-plugin-storybook as root devDeps - Add allowBuilds for esbuild, @parcel/watcher, msw - Remove version pins from CI workflows (reads from packageManager field) - Update AGENTS.md with pnpm 11 refs and supply-chain docs
|
- Bump node-version from 20 → 22 in ci.yml and storybook.yml (pnpm 11 requires Node >= 22.13) - Bump engines.node from >=20 → >=22 in package.json - Remove minimumReleaseAgeExclude — workspace packages bypass the gate inherently - Update AGENTS.md Node requirement references
|
Hey @jhampton, Can I get your feedback on this PR? Mainly around the idea of it. I just want to make sure that with the rise of supply chain attacks, that we are protected on our repos. So I just want to share this with you and let me know so that I can hear your feedback (any feedback) |
Resolve pnpm-lock.yaml conflict by regenerating against main (YPE-642 verse action popover) with pnpm 11.10.0. Supply-chain hardening follow-ups: - pnpm 11.1.1 -> 11.10.0 (latest stable 11.x; corepack-written hash) - vite override ">=5.4.21" -> exact "7.3.3" (closes the last loose version range; a >= let a bad newer release resolve silently) - allowBuilds: '@swc/core': false (tsup uses esbuild by default; no tsup.config requests swc, so its native postinstall is unneeded) - CONTRIBUTING.md prerequisites: Node >=22, pnpm >=11 (match engines) Verified: pnpm lint (7/7), typecheck (6/6), test (751 pass: core 298, hooks 275, ui 178), build. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
CLAUDITHAN SAYS Re: the Greptile note that 1. Stale premise. After the lockfile regen on the current head, Greptile reviewed an earlier commit where swc had transiently dropped out; the regen restored it, so "resolves without it" no longer describes this code. 2. Wrong mechanism regardless. tsup always transforms/bundles with esbuild. Net: nothing to fix. The green build is expected, not just reassuring — esbuild was always the transformer. (Also FYI: |
pnpm 11 reads only auth/registry settings from .npmrc; the publicHoistPattern / autoInstallPeers / strictPeerDependencies lines were silently ignored. Verified publicHoistPattern default is [] under pnpm 11, so eslint/prettier/@types/* were no longer hoisted to root. Migrate them to pnpm-workspace.yaml to preserve the repo's intended hoisting. Confirmed via `pnpm install --force`: full @types/* set is hoisted to root node_modules again (was just @types/node before). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
pnpm 11.x declares engines.node >=22.13 in its own package.json (verified against the npm registry). Aligns engines with the docs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
bmanquen
left a comment
There was a problem hiding this comment.
Just a couple of questions for clarity, both non blocking.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Tests are failing due to: https://appwrite.io/blog/post/nodejs-v25-whats-new#the-localstorage-controversy |
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…pers Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…est/jsdom test envs The SDK itself is hardened for Node 26 (web-storage guards, in-memory installationId fallback), but test files and the vitest/jsdom toolchain still assume a working bare localStorage global. Revisit 26 when the ecosystem catches up. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
RELATES TO https://lifechurch.atlassian.net/browse/YPE-2688
The recent news of seeing more and more supply-chain attacks via npm has caused me to want to make sure we're as secure as can be. That's what this PR does.
Summary
minimumReleaseAge: 4320(3-day cooldown) to mitigate supply-chain attacks on new package versionspackage.json→pnpm-workspace.yaml(pnpm 11 breaking change — overrides in package.json no longer enforce for auto-installed peers)vitewas the last loose range (>=5.4.21→7.3.3), which could otherwise resolve a compromised newer release silentlypnpm/action-setup@v4now reads frompackageManagerfield (single source of truth)Changes
package.jsonpackageManager: "pnpm@11.10.0",engines.pnpm: ">=11.0.0", removedpnpm.overrides, added@internal/eslint-config+eslint-plugin-storybookas root devDepspnpm-workspace.yamlminimumReleaseAge, exact-pinnedoverrides(incl.vite: "7.3.3"),allowBuilds(@swc/core: false— tsup uses esbuild, swc native build unneeded)CONTRIBUTING.md>=22, pnpm>=11to matchengines.github/workflows/ci.ymlversion: 9.0.0pins.github/workflows/release.ymlversion: 9.0.0pin.github/workflows/storybook.ymlversion: 9.0.0pinAGENTS.mdpnpm 11 breaking changes handled
pnpm-workspace.yaml(notpackage.json) to enforce for auto-installed peersallowBuildsapproval (esbuild, @parcel/watcher, msw)@internal/eslint-configandeslint-plugin-storybookmust be root devDependenciesminimumReleaseAgeblocks packages published < 3 days ago; override with--forceif needed urgentlyVerification
pnpm lint— all 7 packages passpnpm typecheck— all 6 packages passpnpm test— 751 tests pass (core: 298, hooks: 275, ui: 178)Greptile Summary
This PR upgrades the monorepo from pnpm 9 to pnpm 11.10.0 and adds supply-chain protections, handling all pnpm 11 breaking changes along the way.
package.json→pnpm-workspace.yaml(required for peer enforcement),.npmrcstripped to auth/registry only,allowBuildsmap replaces the legacyonlyBuiltDependencies/neverBuiltDependenciessettings, and@internal/eslint-config+eslint-plugin-storybookadded as explicit root devDependencies to compensate for the removed workspace hoisting.minimumReleaseAge: 4320(3-day cooldown, in minutes) blocks packages published less than 72 hours ago from being resolved;viteoverride tightened from a loose>=5.4.21range to the exact7.3.3; all CI workflows now derive the pnpm version from thepackageManagerfield rather than hardcoded pins.engines.noderaised to>=22.13.0, Node in all CI jobs bumped to 24, consistent with the documented pnpm 11 minimum and what AGENTS.md/CONTRIBUTING.md now state.Confidence Score: 5/5
Safe to merge — all pnpm 11 breaking changes are handled correctly, the supply-chain settings are well-configured, and the previous concerns about engines.node floor and minimumReleaseAgeExclude have both been resolved in the final state of the diff.
This is a carefully executed tooling upgrade. The overrides migration, allowBuilds map, .npmrc cleanup, and packageManager hash are all structurally correct per the pnpm 11 docs. The engines.node floor matches AGENTS.md/CONTRIBUTING.md/review-guidelines.md (>=22.13.0). The minimumReleaseAge value of 4320 is in minutes (confirmed), giving the documented 3-day cooldown. All CI workflows consistently derive the pnpm version from the packageManager field. The 751-test suite passing gives further confidence that the esbuild-only tsup path (with @swc/core build suppressed) works correctly.
No files require special attention.
Important Files Changed
Flowchart
%%{init: {'theme': 'neutral'}}%% flowchart TD A[pnpm install] --> B{Lockfile frozen?} B -- Yes / CI --> C[Install from lockfile\nno resolution step] B -- No / local add --> D{minimumReleaseAge\n4320 min = 3 days} D -- Package age < 3 days --> E[❌ Blocked\nuse --force to override] D -- Package age ≥ 3 days --> F{In allowBuilds?} F -- Not listed --> G[Install, no build script run] F -- Listed: true --> H[Install + run build script\ne.g. esbuild, msw, @parcel/watcher] F -- Listed: false --> I[Install only\nbuild script suppressed\ne.g. @swc/core] C --> J[✅ Packages installed] G --> J H --> J I --> J%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%% flowchart TD A[pnpm install] --> B{Lockfile frozen?} B -- Yes / CI --> C[Install from lockfile\nno resolution step] B -- No / local add --> D{minimumReleaseAge\n4320 min = 3 days} D -- Package age < 3 days --> E[❌ Blocked\nuse --force to override] D -- Package age ≥ 3 days --> F{In allowBuilds?} F -- Not listed --> G[Install, no build script run] F -- Listed: true --> H[Install + run build script\ne.g. esbuild, msw, @parcel/watcher] F -- Listed: false --> I[Install only\nbuild script suppressed\ne.g. @swc/core] C --> J[✅ Packages installed] G --> J H --> J I --> JComments Outside Diff (1)
pnpm-lock.yaml, line 194-195 (link)@swc/coreno longer resolved as atsuppeerAcross every package (
root,packages/core,packages/hooks,packages/ui),tsup@8.5.0previously resolved with@swc/core@1.13.5as a satisfied peer; after this upgrade it resolves without it. This means tsup will now use esbuild as its transformer instead of SWC. If any package'stsup.config.tsexplicitly sets esbuildOptions or SWC-specific options, behaviour changes silently. The test suite passing is reassuring, but it's worth confirming notsup.configreferencesexperimentalDtsor similar options that behaved differently under SWC.Prompt To Fix With AI
Reviews (17): Last reviewed commit: "docs: state Node 22.13 minimum with Node..." | Re-trigger Greptile