Skip to content

chore: assert bundled production deps resolve in the packed npm#9749

Open
reggi wants to merge 1 commit into
latestfrom
reggi/investigate-9740-sigstore
Open

chore: assert bundled production deps resolve in the packed npm#9749
reggi wants to merge 1 commit into
latestfrom
reggi/investigate-9740-sigstore

Conversation

@reggi

@reggi reggi commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

What

Adds a smoke test (smoke-tests/test/bundled-deps-resolve.js) that packs npm, installs it globally into an isolated testdir, then walks the installed bundle and require.resolve()s every non-optional production dependency from its owning package. If any hoisted dependency can't resolve, the test fails and names the culprit (<pkg> -> <dep>).

Why

In #9722/#9740, sigstore went missing from the packed npm bundle: a stale @npmcli/arborist@^9.1.2 pin in mock-registry couldn't be satisfied by the local v10 workspace, so arborist was pulled from the registry, dragging in a dev-only sigstore@4 that hoisted to the root node_modules and marked it dev. At pack time the dev-only copy was stripped and libnpmpublish's real sigstore@5 was nested (not root-bundled), so the published npm shipped with no node_modules/sigstore and npm publish --provenance failed with Cannot find module 'sigstore'.

Unit tests didn't catch it because they run against the source tree (where a nested copy still resolves) and mock sigstore anyway. Only the packed shape exposes the bug.

Approach

  • Runs against the packed/installed bundle, not the dev tree — the dev tree yields ~115 false positives from dev-only @types/*/peer deps.
  • Skips optionalDependencies (legitimately absent sometimes).
  • Reuses the existing setup.js / npmLocalTarball() infra; the --global install is fully isolated via testdir-scoped --prefix/--cache/config and redirected HOME (same pattern as npm-replace-global.js).

Verification

  • ✅ Passes against the current bundle (0 missing).
  • ✅ Fails when node_modules/sigstore is removed from the packed bundle (reports libnpmpublish -> sigstore, pacote -> sigstore).
  • ✅ eslint clean.

Generic: catches any dropped hoisted production dep, not just sigstore.

Adds a smoke test that packs npm, installs it globally into an isolated
testdir, then walks the installed bundle and require.resolve()s every
non-optional production dependency from its owning package.

This catches deps that get dropped from the hoisted bundle at pack time
(e.g. a dev-only version shadowing the real production copy), which unit
tests miss because they run against the source tree where a nested copy
still resolves. See #9722/#9740 where sigstore went missing from the
packed bundle and shipped a broken `npm publish --provenance`.

Runs against the packed/installed bundle (not the dev tree) to avoid
dev-only @types/peer noise, and skips optionalDependencies.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 716952b1-3f66-4a3e-a48b-ca9cff285466
@reggi reggi requested review from a team as code owners July 10, 2026 18:39
@reggi reggi changed the title test(smoke): assert bundled production deps resolve in the packed npm chore: assert bundled production deps resolve in the packed npm Jul 10, 2026
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.

4 participants