Skip to content

chore: Update yarn to 4.13, add package age gate, fix pnpm linker path detection#198

Open
dividedmind wants to merge 3 commits intomainfrom
chore/update-yarn
Open

chore: Update yarn to 4.13, add package age gate, fix pnpm linker path detection#198
dividedmind wants to merge 3 commits intomainfrom
chore/update-yarn

Conversation

@dividedmind
Copy link
Collaborator

Updates yarn from 3.6.3 to 4.13.0 and adds a 2-day minimum package age gate (npmMinimalAgeGate) as a supply-chain security measure.

Doing this unearthed some issues which were fixed:

  • Fixed hook detection for the yarn 4 pnpm linker: yarn 4 renamed the .store subdirectory from the package name to the generic package/, breaking path-based hook detection in the mocha, jest, and vitest hooks. Added matchesPackageFile() utility to handle all layouts (classic node_modules, yarn 3 pnpm, yarn 4 pnpm).
  • Switched the main project from nodeLinker: pnpm to nodeLinker: node-modules (avoids the yarn 4 pnpm linker compatibility gap with Next.js 14), and added a minimal independent test/pnpm-compat/ sub-project to keep explicit test coverage of the pnpm linker path format.

dividedmind and others added 2 commits March 25, 2026 14:59
Yarn 4 pnpm linker changed the .store subdirectory naming from the
package name (e.g. .store/mocha-npm-10.8.2-hash/mocha/) to a generic
'package/' directory (.store/mocha-npm-10.8.2-hash/package/). This
broke all endsWith() path checks in the mocha, jest, and vitest hooks,
which relied on resolved paths ending with /mocha/lib/runner.js etc.

Add matchesPackageFile() utility to transform.ts that handles both the
classic node_modules layout and the yarn 4 pnpm linker store layout,
and update all three hooks to use it.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@dividedmind dividedmind self-assigned this Mar 25, 2026
…-project

Yarn 4 changed the pnpm linker's .store subdirectory name to 'package/'
(was the package name in yarn 3), breaking path-based hook detection.

Switch the main project to nodeLinker: node-modules to avoid the issue,
and add test/pnpm-compat/ as a minimal independent yarn sub-project with
nodeLinker: pnpm to specifically test the pnpm linker path format support.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@dividedmind dividedmind marked this pull request as ready for review March 25, 2026 18:05
Copilot AI review requested due to automatic review settings March 25, 2026 18:05
@pkg-pr-new
Copy link

pkg-pr-new bot commented Mar 25, 2026

Open in StackBlitz

npm i https://pkg.pr.new/appmap-node@198

commit: 1f17220

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the repo’s Yarn tooling to v4.13.0, adds a supply-chain “package age gate”, and fixes test-framework hook detection under Yarn 4’s pnpm linker layout by introducing a shared path-matching helper and exercising it via a new pnpm-compat integration test.

Changes:

  • Bump Yarn to 4.13.0, switch root nodeLinker to node-modules, and enable npmMinimalAgeGate.
  • Add matchesPackageFile() and update Vitest/Jest/Mocha hooks to support Yarn 4 pnpm linker .store/.../package/... paths.
  • Add a standalone test/pnpm-compat/ project + integration test and CI cache entries to validate pnpm-linker compatibility.

Reviewed changes

Copilot reviewed 22 out of 26 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
.yarnrc.yml Updates Yarn settings (compression, node linker, minimal age gate, yarnPath).
package.json Updates packageManager to Yarn 4.13.0.
.github/workflows/ci.yml Adds caching for test/pnpm-compat Yarn cache/global folders.
src/util/matchesPackageFile.ts New helper to match hook target files across node_modules layouts.
src/transform.ts Re-exports matchesPackageFile (and keeps hook dispatch unchanged).
src/hooks/vitest.ts Switches Vitest hook target detection to matchesPackageFile().
src/hooks/jest.ts Switches Jest hook target detection to matchesPackageFile().
src/hooks/mocha.ts Switches Mocha hook target detection to matchesPackageFile().
test/pnpm-compat.test.ts New integration test running Vitest under Yarn pnpm linker.
test/pnpm-compat/appmap.yml New AppMap config for pnpm-compat fixture project.
test/pnpm-compat/package.json New fixture package manifest (Vitest dependency).
test/pnpm-compat/vitest.config.mjs Minimal Vitest config for pnpm-compat fixture.
test/pnpm-compat/sum.test.js Minimal Vitest test used by pnpm-compat fixture.
test/pnpm-compat/.yarnrc.yml Yarn config for pnpm-compat fixture (pnpm linker + local cache folders).
test/pnpm-compat/.gitignore Ignores .yarn/ within pnpm-compat fixture.
test/pnpm-compat/yarn.lock Lockfile for pnpm-compat fixture project.
test/vitest1/appmap.yml Excludes node_modules from the vitest package path.
test/vitest2/appmap.yml Excludes node_modules from the vitest package path.
test/vitest3/appmap.yml Excludes node_modules from the vitest package path.
test/vitest4/appmap.yml Excludes node_modules from the vitest package path.
test/next.test.ts Uses require.resolve to locate Next’s bin in the fixture project.
test/next16.test.ts Uses require.resolve to locate Next’s bin in the fixture project.
test/__snapshots__/next16.test.ts.snap Updates snapshot to match new Next.js output/header values.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +11 to +18
integrationTest("pnpm linker: vitest hooks instrument code in .store paths", () => {
const dir = resolve(__dirname, "pnpm-compat");
if (!existsSync(resolve(dir, "node_modules")))
spawnSync("yarn", ["install"], {
cwd: dir,
stdio: "inherit",
shell: process.platform === "win32",
});
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

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

The test only runs yarn install when node_modules/ doesn't exist. That can lead to stale dependencies locally (e.g., if test/pnpm-compat/yarn.lock changes but node_modules/ is already present), making the test non-deterministic. Consider always running yarn install --immutable (or another lockfile-enforcing check) in this test setup; CI performance can still be preserved via the workflow cache for test/pnpm-compat/.yarn/*.

Copilot uses AI. Check for mistakes.
// @scope/pkg → @scope-pkg-npm-ver-hash or @scope-pkg-virtual-hash
// pkg → pkg-npm-ver-hash or pkg-virtual-hash
const sanitized = packageName.replace("/", "-");
if (urlOrPath.includes(`/.store/${sanitized}-`)) return true;
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

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

matchesPackageFile() can return false positives for Yarn 4 pnpm store paths because it checks includes('/.store/${sanitized}-'). For example, packageName vite would also match a store entry like vite-node-... since it contains /.store/vite-. This could cause hooks to instrument/patch the wrong package file if the filePath suffix matches. Consider matching the store entry more strictly (e.g., require /.store/${sanitized}-(npm|virtual)- or otherwise enforce a delimiter after the package name).

Suggested change
if (urlOrPath.includes(`/.store/${sanitized}-`)) return true;
if (
urlOrPath.includes(`/.store/${sanitized}-npm-`) ||
urlOrPath.includes(`/.store/${sanitized}-virtual-`)
) {
return true;
}

Copilot uses AI. Check for mistakes.
Comment on lines +2 to +3
packages:
- path: .
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

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

This appmap.yml explicitly sets packages: [{ path: '.' }] but doesn't exclude node_modules/.yarn. In this repo the default package config excludes those directories (see src/config.ts default packages), and most test apps rely on that to avoid instrumenting dependencies. Consider either removing packages: entirely (to fall back to defaults) or adding an exclude list so the pnpm-compat test doesn't instrument the entire dependency tree (which can significantly slow tests and bloat generated AppMaps).

Suggested change
packages:
- path: .

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,7 @@
{
"name": "pnpm-compat-appmap-node-test",
"private": true,
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

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

This test project package.json omits packageManager. Other test subprojects pin Yarn via packageManager (e.g. test/mocha/package.json:3), which helps Corepack/CI reliably run the intended Yarn version when executing commands from that subdirectory. Consider adding "packageManager": "yarn@4.13.0" here to ensure yarn install/yarn vitest in test/pnpm-compat/ consistently uses Yarn 4.

Suggested change
"private": true,
"private": true,
"packageManager": "yarn@4.13.0",

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants