Skip to content

strictDepBuilds and allowBuilds checks are bypassed when package side-effects are cached in the store #11035

@zkochan

Description

@zkochan

Description

When a package with build scripts has been previously built and its side-effects are cached in the store, subsequent installs see isBuilt: true from the side-effects cache. This causes buildModules to skip the package entirely (via the !node.isBuilt filter at building/during-install/src/index.ts:77), which means:

  1. The allowBuild check is never reached
  2. The package is not added to ignoredBuilds
  3. strictDepBuilds does not fail
  4. No warning about skipped builds is shown

This affects both GVS (Global Virtual Store) mode and regular mode — any store that has cached side-effects from a prior build will exhibit this behavior.

Steps to reproduce

  1. Install a package with build scripts (e.g. esbuild) with allowBuilds: { esbuild: true } — this builds it and caches side-effects in the store
  2. Remove the allowBuilds entry (or set a placeholder)
  3. Run pnpm install — esbuild's build is silently reused from the store cache because isBuilt: true, bypassing the allowBuild check entirely

Expected behavior

Even if a package's side-effects are cached in the store, strictDepBuilds should still fail and the ignored builds warning should still appear when the package is not approved in allowBuilds.

Investigation notes

The fix is not straightforward because it spans multiple code paths:

  • building/during-install (buildModules): The !node.isBuilt filter removes cached packages before the allowBuild check. Adding a pre-loop check helps when the dep graph is fully populated, but the graph can be sparse on repeat installs.
  • installing/deps-restorer (headless install): The lockfileToDepGraph function excludes unchanged deps when includeUnchangedDeps is false. Removing the GVS guard on the allowBuilds comparison (line 349) helps trigger full graph population when allowBuilds changes, but this only works for the headless path.
  • installing/deps-installer (_installInContext): The entire build/ignoredBuilds block is inside if (result.newDepPaths?.length), so it's completely skipped on repeat installs with no changes.

A comprehensive fix likely needs to check allowBuild against all lockfile packages with build scripts after the install completes, independent of the dep graph's isBuilt state.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions