diff --git a/.changeset/deps-status-no-manifest.md b/.changeset/deps-status-no-manifest.md new file mode 100644 index 0000000000..8a4e524167 --- /dev/null +++ b/.changeset/deps-status-no-manifest.md @@ -0,0 +1,6 @@ +--- +"@pnpm/exec.commands": patch +"pnpm": patch +--- + +Avoid running dependency-status auto-install when the dependency status is unavailable without a project manifest. diff --git a/exec/commands/src/runDepsStatusCheck.ts b/exec/commands/src/runDepsStatusCheck.ts index 85f1f97c64..37de0897cd 100644 --- a/exec/commands/src/runDepsStatusCheck.ts +++ b/exec/commands/src/runDepsStatusCheck.ts @@ -18,7 +18,8 @@ export async function runDepsStatusCheck (opts: RunDepsStatusCheckOptions): Prom opts.ignoredWorkspaceStateSettings = ignoredWorkspaceStateSettings const { upToDate, issue, workspaceState } = await checkDepsStatus(opts) - if (upToDate) return + if (upToDate === true) return + if (upToDate === undefined && opts.allProjects == null && opts.rootProjectManifest == null) return const command = ['install', ...createInstallArgs(workspaceState?.settings)] const install = runPnpmCli.bind(null, command, { cwd: opts.dir, reporter: opts.reporter }) diff --git a/exec/commands/test/runDepsStatusCheck.test.ts b/exec/commands/test/runDepsStatusCheck.test.ts new file mode 100644 index 0000000000..df0b4070c0 --- /dev/null +++ b/exec/commands/test/runDepsStatusCheck.test.ts @@ -0,0 +1,75 @@ +import { beforeEach, expect, jest, test } from '@jest/globals' +import type { checkDepsStatus as checkDepsStatusFn } from '@pnpm/deps.status' +import type { runPnpmCli as runPnpmCliFn } from '@pnpm/exec.pnpm-cli-runner' + +const checkDepsStatus = jest.fn() +const runPnpmCli = jest.fn() + +jest.unstable_mockModule('@pnpm/deps.status', () => ({ + checkDepsStatus, +})) + +jest.unstable_mockModule('@pnpm/exec.pnpm-cli-runner', () => ({ + runPnpmCli, +})) + +jest.unstable_mockModule('@pnpm/logger', () => ({ + globalWarn: jest.fn(), +})) + +jest.unstable_mockModule('@inquirer/prompts', () => ({ + confirm: jest.fn(), +})) + +const { runDepsStatusCheck } = await import('../src/runDepsStatusCheck.js') + +beforeEach(() => { + checkDepsStatus.mockReset() + runPnpmCli.mockReset() +}) + +test('does not install when dependency status is unavailable without a project manifest', async () => { + checkDepsStatus.mockResolvedValue({ + upToDate: undefined, + issue: 'No package manifest found. Skipping check.', + workspaceState: undefined, + }) + + await runDepsStatusCheck({ + dir: process.cwd(), + excludeLinksFromLockfile: false, + linkWorkspacePackages: false, + preferWorkspacePackages: false, + pnpmfile: [], + rootProjectManifestDir: process.cwd(), + verifyDepsBeforeRun: 'install', + }) + + expect(runPnpmCli).not.toHaveBeenCalled() +}) + +test('installs when dependency status is unavailable for an unexpected reason', async () => { + checkDepsStatus.mockResolvedValue({ + upToDate: undefined, + issue: 'Cannot verify dependency status', + workspaceState: undefined, + }) + + await runDepsStatusCheck({ + dir: process.cwd(), + excludeLinksFromLockfile: false, + linkWorkspacePackages: false, + pnpmfile: [], + preferWorkspacePackages: false, + rootProjectManifest: { + name: 'root', + }, + rootProjectManifestDir: process.cwd(), + verifyDepsBeforeRun: 'install', + }) + + expect(runPnpmCli).toHaveBeenCalledWith(['install'], { + cwd: process.cwd(), + reporter: undefined, + }) +})