Skip to content

[finding] scaffold-next-steps-pm.test.ts pins pnpm detection over a probe that resolves OUTSIDE the repo, so a Corepack fetch decides the verdict — one queue red already #11616

Description

@os-zhuang

What went red

Merge-queue build 32708418190,
Test Core (5/6), on PR #11609 (a test-only diff in packages/cli that cannot reach
packages/create-objectstack):

FAIL src/scaffold-next-steps-pm.test.ts
> scaffolder "Next steps" names the package manager it actually detected (#10322)
> with pnpm on PATH: prints pnpm consistently, never bare npm
AssertionError: expected '\n cd my-app\n npm install\n …' to match /\bpnpm run dev\b/

Why it is not a real regression, and why that is the problem

The scaffolder decides what to print with a probe that swallows every failure mode into one answer
(packages/create-objectstack/src/index.ts:125):

functiondetectPackageManager(): string{try{execSync('pnpm --version',{stdio: 'ignore'});return'pnpm';}catch{return'npm';}}

npm install in the output therefore means the probe threw, not the code chose npm. The two are
not distinguishable from the assertion message.

The test's own vacuity guard — expect(() => which('pnpm')).not.toThrow() — does not cover the
probe, because the two run in different working directories:

cwdwhat resolves
the test's sanity command -v pnpmthe package dir, inside the repothe pinned packageManager, pnpm@10.31.0
the scaffold child's pnpm --versionmkdtemp under os.tmpdir(), outside the repoCorepack's own default

Measured locally on one machine, one binary, two cwds:

$ (cd <repo root> && pnpm --version) → 10.31.0
$ (cd /tmp && pnpm --version) → 10.33.0

The queue job runs pnpm through Corepack — COREPACK_HOME: /home/runner/work/_temp/corepack is in
that job's env, and a "Restore the Corepack store" cache step is part of it. os.tmpdir() on a GitHub
runner is /home/runner/work/_temp, which has no package.json above it, so the outer leg is the one
that has to resolve (and potentially fetch) a version the repo never pinned. Nothing in the assertion
distinguishes "the scaffolder regressed" from "that resolution failed once".

Related but distinct: #11369 is about Corepack downloads in workflow jobs. This is a Corepack
resolution inside a test's child process, and would survive that card being fixed.

Suggested shape (not a ruling — for triage)

The pin is worth keeping; what needs removing is the dependency on an unpinned resolution:

  1. Make the probe's outcome the fixture rather than the ambient environment — run the pnpm leg under
    a controlled PATH holding a stub pnpm that exits 0, the exact mirror of the npm-fallback leg's
    existing makePnpmlessBin(). Both branches then become hermetic, and the test stops asserting a
    property of the runner.
  2. Independently: consider whether detectPackageManager() collapsing spawn failure and pnpm
    absent
    into one answer is itself worth separating, since a user with pnpm installed but a slow or
    failing probe is told to run npm. That is a user-facing question, not a test one — split it out if
    triage agrees it is a card.

Filed unassigned, for grading. Not folded into #11609: different package, and that PR's card
(#11301) is a packages/cli exit-code pin.

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions