Skip to content

Parse PNPM lock files and support PNPM workspaces - #1502

Merged
codykaup merged 16 commits into
mainfrom
cody/cap-4975-recognize-pnpm-lockyaml-as-a-package-metadata-file
Sep 28, 2026
Merged

codykaup merged 16 commits into
mainfrom
cody/cap-4975-recognize-pnpm-lockyaml-as-a-package-metadata-file

Conversation

@codykaup

@codykaup codykaup commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

Problem

TurboSnap missed dependency changes in PNPM projects in two layers:

  1. We added pnpm-lock.yaml as a SUPPORTED_LOCK_FILES but didn't add it to the isPackageLockFile check, so a lockfile-only change never entered the TurboSnap code path.
  2. Even if we had that, we weren't handling PNPM workspaces so snyk was parsing the package.json and pnpm-lock.yaml pair as if it wasn't a monorepo. Therefore, a dependency with the specifier catalog: would produce <dependency>@catalog: instead of the real version number.

Solution

  • Moved all supported lockfiles into utilities.ts for a single source of truth.
  • getDependencies branches on lockfile type. For pnpm it derives the manifest's importer (its directory relative to the lockfile) from the paths it is given, then drives parsePnpmWorkspaceProject directly so catalog: and workspace: specifiers resolve against the right importer table. Baselines are checked out to their repository-relative paths under a temp directory so the manifest keeps its position relative to the lockfile.
  • snyk-nodejs-lockfile-parser is pinned to exactly 2.7.0 to match snyk-nodejs-plugin's own pin, so only one copy is installed.
  • Manifests the lockfile has no importer for (standalone pre-v9 lockfiles, or a package.json outside the workspace globs) fall back to parsePnpmProject. That keeps raw specifiers instead of throwing, which is what the yarn and npm parsers already do for manifests the lockfile can't place.
  • pnpm-workspace.yaml is deliberately not tracked. A catalog change there always co-changes pnpm-lock.yaml, and tracking it would force full rebuilds for unrelated workspace config edits.
📦 Published PR as canary version: 18.10.1--canary.1502.36458228651.0

✨ Test out this PR locally via:

npm install chromatic@18.10.1--canary.1502.36458228651.0
# or 
yarn add chromatic@18.10.1--canary.1502.36458228651.0

@codykaup codykaup added release Auto: Create a `latest` release when merged minor Auto: Increment the minor version when merged labels Sep 22, 2026
@github-actions

github-actions Bot commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

📦 Package Size: 7180 KB
✅ Compared to main: 0 KB 5a80919 (7180 KB)

Comment thread node-src/lib/turbosnap/v1/getDependencies.ts
@codecov

codecov Bot commented Sep 22, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 86.91%. Comparing base (5a80919) to head (2a9e14c).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1502      +/-   ##
==========================================
+ Coverage   86.88%   86.91%   +0.03%     
==========================================
  Files         274      274              
  Lines        5499     5512      +13     
  Branches     1488     1497       +9     
==========================================
+ Hits         4778     4791      +13     
  Misses        635      635              
  Partials       86       86              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@codykaup
codykaup force-pushed the cody/cap-4975-recognize-pnpm-lockyaml-as-a-package-metadata-file branch from ea897b3 to 40d04e5 Compare September 22, 2026 19:05
@codykaup codykaup changed the title Recognize pnpm-lock.yaml as a package metadata file and resolve pnpm workspace importers Parse PNPM lock files and support PNPM workspaces Sep 22, 2026
@codykaup
codykaup force-pushed the cody/cap-4975-recognize-pnpm-lockyaml-as-a-package-metadata-file branch 2 times, most recently from 66a2ff4 to 4ed58d2 Compare September 22, 2026 19:25
@codykaup
codykaup marked this pull request as ready for review September 22, 2026 20:12
@codykaup
codykaup requested a review from a team September 22, 2026 20:12

@justin-thurman justin-thurman left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Overall, looks good. I think the package version issue is blocking, but should be an easy fix. Also worth calling out that I think this won't work for workspaces in a subdirectory, since, unless I'm misreading, findChangedDependencies checks each package's own directory for a lockfile, and then the repo root, but not subdirs. And maybe the same gap exists for yarn already? Seems like this would have come up before though, so maybe I'm missing something. In any case, not a regression, so debatable whether it should be added in this PR or not.

Side note:

We added pnpm-lock.yaml as a SUPPORTED_LOCK_FILES but didn't add it to the isPackageLockFile check, so a lockfile-only change never entered the TurboSnap code path.

Any way to enforce that SUPPORTED_LOCK_FILES and isPackageLockFile can't drift? If not something structural, then a unit test that parameterizes SUPPORTED_LOCK_FILES and just ensure each one is supported by isPackageLockFile?

Comment thread node-src/lib/turbosnap/v1/getDependencies.ts
Comment thread node-src/lib/turbosnap/v1/getDependencies.ts Outdated
Comment thread node-src/lib/turbosnap/v1/getDependencies.ts Outdated
@codykaup
codykaup force-pushed the cody/cap-4975-recognize-pnpm-lockyaml-as-a-package-metadata-file branch from 4ed58d2 to 9e6973a Compare September 25, 2026 15:47
@codykaup
codykaup marked this pull request as draft September 25, 2026 15:47
Comment thread node-src/git/git.ts
checkoutFile now writes to tmpdir/<fileName> instead of tmpdir/<basename>,
so files checked out together keep the layout they have in the repository.
getDependencies now computes the importer from the manifest and lockfile
paths it already receives, so callers no longer pass it. findChangedDependencies
stops flattening HEAD files into a temp directory and checks baseline files out
to their repository-relative paths. The flatten-and-copy workaround for
snyk-nodejs-plugin's inspect moves next to the inspect call.
@codykaup
codykaup force-pushed the cody/cap-4975-recognize-pnpm-lockyaml-as-a-package-metadata-file branch from 9e6973a to e6af1f6 Compare September 25, 2026 15:51
The single-project parser still resolves against the root importer when
the lockfile has one, so only deps the root lacks keep raw specifiers.
The workspace-link test name now says what it asserts: catalog entries
resolve, and workspace links come out the same on HEAD and baseline.
Assert the pnpm importers by name rather than by argument position,
remove the temp directory the unparseable-lockfile test creates, and
pass repository-relative paths in the historic-files test to match the
getDependencies contract.
The checked-out file now lives at its repository-relative path under
tmpdir, so a directory name with a space or shell metacharacter would
break the redirect.
findChangedDependencies no longer uses the path checkoutFile returns, so
the mock's fake result and the comment describing it were misleading.
Record the importer each workspace-parser call receives and compare the
full multiset, so each importer is proven to be used for both HEAD and
the baseline. Note that the changed-dependency result comes from the
mocked graph, so the importer assertion is what exercises the pnpm path.
Callers know where the file lands because it keeps its repository-relative
path under tmpdir. Returning the path suggested a second contract.
@codykaup
codykaup marked this pull request as ready for review September 25, 2026 17:39
@codykaup

Copy link
Copy Markdown
Contributor Author

@justin-thurman quite a few changes because I pulled out the importer argument from getDependencies so the caller doesn't need to worry about it at all. That spiraled into a much larger change than I thought. Curious what you think.

@codykaup

Copy link
Copy Markdown
Contributor Author

Also worth calling out that I think this won't work for workspaces in a subdirectory

Correct but that still applies to all package managers. Something we can address in a separate PR if we run into it in the wild later!

@justin-thurman justin-thurman left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks great!

@codykaup
codykaup added this pull request to stack #1506 September 25, 2026 19:52
@codykaup codykaup added skip-release Auto: Preserve the current version when merged and removed release Auto: Create a `latest` release when merged labels Sep 28, 2026
@codykaup
codykaup added this pull request to the merge queue Sep 28, 2026
Merged via the queue into main with commit a15b8b4 Sep 28, 2026
28 of 29 checks passed
@codykaup
codykaup deleted the cody/cap-4975-recognize-pnpm-lockyaml-as-a-package-metadata-file branch September 28, 2026 15:44
@chromatic-ci-bot

Copy link
Copy Markdown
Collaborator

🚀 PR was released in v18.10.0 🚀

@chromatic-ci-bot chromatic-ci-bot added the released Verdict: This issue/pull request has been released label Sep 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

minor Auto: Increment the minor version when merged released Verdict: This issue/pull request has been released skip-release Auto: Preserve the current version when merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants