Skip to content

Upgrade pnpm from 10.22.0 to 10.32.1#3339

Open
Myranae wants to merge 5 commits intomainfrom
tb/bump-pnpm
Open

Upgrade pnpm from 10.22.0 to 10.32.1#3339
Myranae wants to merge 5 commits intomainfrom
tb/bump-pnpm

Conversation

@Myranae
Copy link
Contributor

@Myranae Myranae commented Mar 12, 2026

Summary

  • Bumps pnpm from 10.22.0 to 10.32.1 via corepack use pnpm@10

Test plan

  • CI passes with updated pnpm version
  • pnpm install works correctly in a clean checkout

Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@Myranae Myranae self-assigned this Mar 12, 2026
@github-actions
Copy link
Contributor

github-actions bot commented Mar 12, 2026

🗄️ Schema Change: No Changes ✅

@github-actions
Copy link
Contributor

github-actions bot commented Mar 12, 2026

🛠️ Item Splitting: No Changes ✅

@github-actions
Copy link
Contributor

github-actions bot commented Mar 12, 2026

Size Change: +119 B (+0.02%)

Total Size: 486 kB

Filename Size Change
packages/perseus/dist/es/index.js 187 kB +119 B (+0.06%)
ℹ️ View Unchanged
Filename Size
packages/kas/dist/es/index.js 20.8 kB
packages/keypad-context/dist/es/index.js 1 kB
packages/kmath/dist/es/index.js 5.96 kB
packages/math-input/dist/es/index.js 98.5 kB
packages/math-input/dist/es/strings.js 1.61 kB
packages/perseus-core/dist/es/index.item-splitting.js 11.8 kB
packages/perseus-core/dist/es/index.js 24.9 kB
packages/perseus-editor/dist/es/index.js 100 kB
packages/perseus-linter/dist/es/index.js 8.82 kB
packages/perseus-score/dist/es/index.js 9.26 kB
packages/perseus-utils/dist/es/index.js 403 B
packages/perseus/dist/es/strings.js 7.47 kB
packages/pure-markdown/dist/es/index.js 1.39 kB
packages/simple-markdown/dist/es/index.js 6.71 kB

compressed-size-action

@github-actions
Copy link
Contributor

github-actions bot commented Mar 12, 2026

npm Snapshot: Published

Good news!! We've packaged up the latest commit from this PR (578df27) and published it to npm. You
can install it using the tag PR3339.

Example:

pnpm add @khanacademy/perseus@PR3339

If you are working in Khan Academy's frontend, you can run the below command.

./dev/tools/bump_perseus_version.ts -t PR3339

If you are working in Khan Academy's webapp, you can run the below command.

./dev/tools/bump_perseus_version.js -t PR3339

Myranae and others added 3 commits March 12, 2026 18:16
pnpm 10.32.1 no longer hoists @swc/helpers to the top-level
node_modules since it's marked optional in the lockfile. This caused
Jest to fail resolving @swc/helpers/_/_interop_require_default, which
is required when externalHelpers is enabled in .swcrc.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
pnpm 10.32.1 blocks git-hosted packages from running build scripts
by default unless explicitly listed in onlyBuiltDependencies.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
It's used implicitly via externalHelpers in .swcrc, not imported directly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@Myranae Myranae marked this pull request as ready for review March 12, 2026 23:41
Copy link
Member

@benchristel benchristel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the context for this change? Is this something frontend infra wants us to do?

"@storybook/test": "^8.6.15",
"@swc-node/register": "^1.10.10",
"@swc/core": "1.11.13",
"@swc/helpers": "^0.5.17",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need @swc/helpers? Is this related to the pnpm update?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this was added due to some failing CI checks. Looks like the previous pnpm version was less explicit about things and this was being hoisted up before (or that's how Claude explained it). It fixed the related error (the checks couldn't find this).

Also, as I was bringing back Dependabot, Jeremy and I discussed just doing an update at the same time.

Copy link
Contributor Author

@Myranae Myranae Mar 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are the errors this fixed (link to the related check)

check related to cws/helpers

Copy link

@claude claude bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — straightforward pnpm version bump with mechanical supporting changes.

Extended reasoning...

Overview

This PR bumps pnpm from 10.22.0 to 10.32.1 and makes three small supporting changes: adding @swc/helpers as an explicit devDependency (with a corresponding knip ignore entry), and adding mathquill to pnpm.onlyBuiltDependencies. The lockfile and a changeset file are also updated.

Security risks

No security concerns. The packageManager field includes a SHA-512 hash to pin the exact pnpm binary. The onlyBuiltDependencies change allows mathquill (sourced from Khan's own GitHub repo, pinned to a specific commit in the lockfile) to run build scripts. The @swc/helpers addition is a well-known SWC companion package at a caret-pinned version.

Level of scrutiny

Low scrutiny is appropriate. This is a tooling/infrastructure version bump with no changes to application logic, no changes to production code paths, and no changes to security-sensitive areas. The code changes are mechanical and follow established patterns in the repository.

Other factors

  • CI is green (schema check, item splitting, size check, and npm snapshot all passed).
  • The two bugs found are both cosmetic nits: a missing trailing newline in the changeset file, and mathquill lacking a version pin in onlyBuiltDependencies (which may actually be intentional since mathquill is resolved from a GitHub tarball rather than a registry version).
  • No outstanding reviewer comments to address.
  • The +119B bundle size increase is negligible and likely from the @swc/helpers dependency being resolved slightly differently.

"esbuild@0.24.0",
"@swc/core@1.11.13"
"@swc/core@1.11.13",
"mathquill"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Nit: mathquill in pnpm.onlyBuiltDependencies is the only entry without a version pin — the other entries all use name@version format (e.g. cypress@13.6.5). Without a version pin, any version of mathquill is allowed to run build scripts. Consider using mathquill@1.0.3 for consistency, though note this may not match correctly since mathquill is resolved from a GitHub tarball rather than a registry version.

Extended reasoning...

Pattern inconsistency in onlyBuiltDependencies

The pnpm.onlyBuiltDependencies array in package.json controls which packages are permitted to run build scripts (install hooks). All three existing entries use the name@version format to restrict this permission to a specific version:

  • cypress@13.6.5
  • esbuild@0.24.0
  • @swc/core@1.11.13

The newly added mathquill entry breaks this pattern by omitting a version pin. Per pnpm documentation, an unversioned entry means any version of that package would be allowed to run build scripts, which is less restrictive than the pinned approach used for every other entry.

Step-by-step proof

  1. Look at package.json line 147-150: the onlyBuiltDependencies array has four entries.
  2. The first three entries all use name@version format.
  3. The fourth entry, mathquill, has no version qualifier.
  4. In the lockfile, mathquill resolves to version 1.0.3 from github:Khan/mathquill#v1.0.3 (commit c9e4329b0bc5d9b4c21d765b5768e4e7693515b3).
  5. If someone were to change the mathquill specifier to a different version or fork, the unpinned entry would still allow that new version to run build scripts without any explicit approval.

Practical impact and caveats

The real-world risk here is minimal for several reasons: (1) mathquill is sourced from Khan's own GitHub repository, (2) it's pinned to a specific git tag and commit hash in the lockfile, and (3) any version change requires an explicit lockfile update that would go through code review.

Additionally, there's a practical question about whether mathquill@1.0.3 would even work correctly as a matcher for a GitHub-sourced package. Internally, pnpm identifies this package by its tarball URL (https://codeload.github.com/Khan/mathquill/tar.gz/c9e4329b...) rather than a semver version from a registry. The plain name mathquill (without version) may actually be the most reliable way to match this GitHub-sourced package.

Recommendation

If mathquill@1.0.3 does work as a matcher, it would be worth adding for consistency. If not, a comment explaining why this entry differs from the others would help future maintainers understand the intentional inconsistency.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know that we need mathquill listed here. This array lists packages we want to allow pnpm to run install scripts for. Did something break after upgrading pnpm that this fixed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup! I should have taken pictures of the failures, but I can revert this to check what those errors were. Is there a record? And what the Claude review said about the tarball thing is what my Claude was saying regarding the version pin.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, perfect! That makes sense.

@jeremywiebe
Copy link
Collaborator

What's the context for this change? Is this something frontend infra wants us to do?

There was a pnpm upgrade in the Dependant removal PR. Tamara and I talked about why it was bumped and I mentioned it would be good to bump it again to latest to take advantage of bug fixes and any security improvements they've made (reviewing the releases since 10.22 there also seems to be some nice quality of life improvements).

@Myranae
Copy link
Contributor Author

Myranae commented Mar 13, 2026

Looks like there was also a downgrade of react-router, which affected the WB packaged peer dep resolutions. It could be possible to see runtime errors if any of WB code relied on the v6 APIs (resolved to v5 now)

More Review from Claude Interesting — the lockfile tells the full story. Here are the three concrete surprise areas:

1. react-router resolution shifted: 6.30.05.3.4

This is the most notable thing in the lockfile. All the Wonder Blocks packages had their react-router peer dependency resolution change from react-router@6.30.0 to react-router@5.3.4. This happened because pnpm 10.32 resolves peer dependencies differently (stricter matching).

This probably works fine since Perseus actually uses react-router v5, and the old lockfile was arguably wrong to resolve to v6. But if any Wonder Blocks code internally relies on v6 APIs (like the useNavigate hook or the <Routes> component), you'd see runtime errors — not build errors.

2. @swc/helpers hoisting change

Your commit message already nails this: pnpm 10.32 stopped hoisting @swc/helpers because it's marked optional. You fixed it by adding it as an explicit devDependency. The surprise risk here is in downstream consumers — if anyone else who consumes Perseus's lockfile (like a webapp that installs Perseus) also relied on the implicit hoisting, they'd hit the same Jest resolution failure you did until they make a similar fix.

3. mathquill build scripts

The onlyBuiltDependencies list is a security boundary — it controls which packages can run arbitrary code during pnpm install. Adding mathquill without a version pin (unlike the others which have cypress@13.6.5, esbuild@0.24.0, @swc/core@1.11.13) means any future version of mathquill would also get install-script permission. Lower risk since it's a KA-controlled fork, but worth noting.

★ Insight ─────────────────────────────────────
The react-router resolution shift is a good example of why lockfile diffs matter even when the package.json change looks trivial. pnpm's peer dependency resolution algorithm changed between versions, which means the same package.json can produce different dependency trees. This is why pnpm-lock.yaml exists — it pins the exact resolution. When you see peer dep resolutions shift in a lockfile diff, the question to ask is: "was the old resolution or the new one correct?" In this case, the new one (v5) is likely more correct since that's what Perseus actually depends on.
─────────────────────────────────────────────────

Bottom line: The react-router resolution is the one I'd watch most closely. Run Storybook and click through a few navigation-heavy flows (anything using Wonder Blocks routing components) to make sure nothing broke.

@jeremywiebe
Copy link
Collaborator

Looks like there was also a downgrade of react-router, which affected the WB packaged peer dep resolutions. It could be possible to see runtime errors if any of WB code relied on the v6 APIs (resolved to v5 now)

More Review from Claude

Looking at the wonder-blocks packages, it seems like they all have a peer-dependency on react-router v5. So I think this update is correct (aligns with what Claude says too).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants