Skip to content

Commit d44258d

Browse files
committed
Fix Windows spawn ENOENT for package managers
Three fixes for Windows compatibility: 1. Use pnpmExecPath constant to find pnpm executable (similar to npmExecPath) 2. When spawning with just a command name on Windows (not a full path), append .cmd extension for package managers to ensure Windows can find them 3. Add Windows-specific paths in findRealPnpm for common pnpm locations This should resolve optimize test failures on Windows CI where 'spawn pnpm ENOENT' errors were occurring because pnpm couldn't be found in PATH.
1 parent 64a0417 commit d44258d

File tree

2 files changed

+30
-2
lines changed

2 files changed

+30
-2
lines changed

src/utils/agent.mts

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
1+
import path from 'node:path'
2+
13
import { logger } from '@socketsecurity/registry/lib/logger'
24
import { getOwn } from '@socketsecurity/registry/lib/objects'
35
import { spawn } from '@socketsecurity/registry/lib/spawn'
46
import { Spinner } from '@socketsecurity/registry/lib/spinner'
57

6-
import constants, { NPM, PNPM } from '../constants.mts'
8+
import constants, {
9+
NPM,
10+
PNPM,
11+
YARN_BERRY,
12+
YARN_CLASSIC,
13+
} from '../constants.mts'
714
import { cmdFlagsToString } from './cmd.mts'
815
import { shadowNpmInstall } from '../shadow/npm/install.mts'
916

@@ -61,7 +68,19 @@ export function runAgentInstall(
6168
logger.error(` agentExecPath: ${agentExecPath}`)
6269
}
6370

64-
return spawn(agentExecPath, installArgs, {
71+
// On Windows with shell: true, if we get just the command name (not a full path),
72+
// we need to append .cmd for package managers to work correctly.
73+
let command = agentExecPath
74+
if (
75+
constants.WIN32 &&
76+
!agentExecPath.includes(path.sep) &&
77+
(agent === PNPM || agent === YARN_CLASSIC || agent === YARN_BERRY)
78+
) {
79+
// If it's just a command name like 'pnpm' (no path separator), add .cmd for Windows.
80+
command = `${agentExecPath}.cmd`
81+
}
82+
83+
return spawn(command, installArgs, {
6584
cwd: pkgPath,
6685
shell: constants.WIN32,
6786
spinner,

src/utils/package-environment.mts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,15 @@ async function getAgentExecPath(agent: Agent): Promise<string> {
223223
// Fall back to whichBin.
224224
return (await whichBin(binName, { nothrow: true })) ?? binName
225225
}
226+
if (binName === PNPM) {
227+
// Try to use constants.pnpmExecPath first, but verify it exists.
228+
const pnpmPath = constants.pnpmExecPath
229+
if (existsSync(pnpmPath)) {
230+
return pnpmPath
231+
}
232+
// Fall back to whichBin.
233+
return (await whichBin(binName, { nothrow: true })) ?? binName
234+
}
226235
return (await whichBin(binName, { nothrow: true })) ?? binName
227236
}
228237

0 commit comments

Comments
 (0)