Skip to content

Commit ccf6c18

Browse files
committed
fix: prevent false dependency drift alerts from npm ls exits
Treat dependency install checks as failing only when npm ls reports expected dependencies as missing or invalid, so unrelated non-zero exits no longer trigger stale dependency notifications. Made-with: Cursor
1 parent 3db6e73 commit ccf6c18

2 files changed

Lines changed: 50 additions & 21 deletions

File tree

packages/workshop-utils/src/package-install/package-install-check.server.test.ts

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,31 @@ describe('getRootPackageInstallStatus', () => {
256256
)
257257
})
258258

259+
test('ignores non-zero npm ls exit when expected deps are healthy', async () => {
260+
await using temp = await createTempDir()
261+
const tempDir = temp.dir
262+
263+
await writePackageJson(tempDir, {
264+
name: 'test-package',
265+
dependencies: { react: '^18.0.0', 'react-dom': '^18.0.0' },
266+
})
267+
mockNpmLsResult({
268+
exitCode: 1,
269+
dependencies: {
270+
react: {},
271+
'react-dom': {},
272+
},
273+
})
274+
275+
const status = await getRootPackageInstallStatus(
276+
path.join(tempDir, 'package.json'),
277+
)
278+
279+
expect(status.dependenciesNeedInstall).toBe(false)
280+
expect(status.reason).toBe('up-to-date')
281+
expect(status.missingDependencies).toEqual([])
282+
})
283+
259284
test('detects missing devDependencies', async () => {
260285
await using temp = await createTempDir()
261286
const tempDir = temp.dir
@@ -611,31 +636,37 @@ describe('getWorkspaceInstallStatus', () => {
611636
test('returns all up-to-date when all roots satisfied', async () => {
612637
await using temp = await createTempDir()
613638
const tempDir = temp.dir
639+
const subDir = path.join(tempDir, 'sub')
614640

615641
await writePackageJson(tempDir, {
616642
name: 'root-package',
617643
packageManager: 'yarn@4.0.0',
618644
dependencies: { react: '^18.0.0' },
619645
})
620-
vi.mocked(execa)
621-
.mockResolvedValueOnce({
622-
exitCode: 0,
623-
stdout: JSON.stringify({ dependencies: { react: {} } }),
624-
stderr: '',
625-
} as never)
626-
.mockResolvedValueOnce({
627-
exitCode: 0,
628-
stdout: JSON.stringify({ dependencies: { typescript: {} } }),
629-
stderr: '',
630-
} as never)
631-
632-
const subDir = path.join(tempDir, 'sub')
633646
await fs.mkdir(subDir, { recursive: true })
634647
await writePackageJson(subDir, {
635648
name: 'sub-package',
636649
packageManager: 'bun@1.0.0',
637650
dependencies: { typescript: '^5.0.0' },
638651
})
652+
vi.mocked(execa).mockImplementation(async (_command, _args, options) => {
653+
const cwd = (options as { cwd?: string }).cwd
654+
if (cwd === tempDir) {
655+
return {
656+
exitCode: 0,
657+
stdout: JSON.stringify({ dependencies: { react: {} } }),
658+
stderr: '',
659+
} as never
660+
}
661+
if (cwd === subDir) {
662+
return {
663+
exitCode: 0,
664+
stdout: JSON.stringify({ dependencies: { typescript: {} } }),
665+
stderr: '',
666+
} as never
667+
}
668+
return { exitCode: 1, stdout: '', stderr: '' } as never
669+
})
639670

640671
const status = await getWorkspaceInstallStatus(tempDir)
641672

packages/workshop-utils/src/package-install/package-install-check.server.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -172,16 +172,14 @@ async function checkDependenciesWithNpmLs(
172172
{ cwd: rootDir, reject: false },
173173
)
174174
const output = parseNpmLsOutput(result.stdout)
175-
const ok = result.exitCode === 0
176-
const failingDependencies = ok
177-
? []
178-
: getFailingDependencies(expectedDependencies, output)
175+
const failingDependencies = getFailingDependencies(
176+
expectedDependencies,
177+
output,
178+
)
179+
const ok = failingDependencies.length === 0
179180
return {
180181
ok,
181-
failingDependencies:
182-
ok || failingDependencies.length > 0
183-
? failingDependencies
184-
: expectedDependencies,
182+
failingDependencies,
185183
}
186184
} catch (error) {
187185
console.warn(

0 commit comments

Comments
 (0)