@@ -29,16 +29,20 @@ export async function runSelfInstaller(inputs: Inputs): Promise<number> {
2929 await writeFile ( path . join ( dest , 'package.json' ) , packageJson )
3030 await writeFile ( path . join ( dest , 'package-lock.json' ) , JSON . stringify ( lockfile ) )
3131
32- // Prepend the action's node directory to PATH so npm's
32+ // Append the action's node directory to PATH so npm's
3333 // `#!/usr/bin/env node` shebang resolves on runners (e.g. GHE
34- // self-hosted) where node isn't already on PATH. npm itself is
35- // resolved via PATH — on the GitHub Actions runner it is not
36- // co-located with `process.execPath`.
34+ // self-hosted) where node isn't already on PATH. Append (not
35+ // prepend) so a user-installed toolchain on PATH — e.g. from a
36+ // prior `setup-node` step — keeps precedence; otherwise the
37+ // runner-bundled node would shadow it and pair the user's npm
38+ // with a mismatched node version. npm itself is resolved via
39+ // PATH — on the GitHub Actions runner it is not co-located with
40+ // `process.execPath`.
3741 const nodeDir = path . dirname ( process . execPath )
3842 // On Windows, the PATH key casing varies; search case-insensitively.
3943 const pathKey = Object . keys ( process . env ) . find ( k => k . toUpperCase ( ) === 'PATH' ) ?? 'PATH'
4044 const currentPath = process . env [ pathKey ]
41- const npmEnv = { ...process . env , [ pathKey ] : currentPath ? nodeDir + path . delimiter + currentPath : nodeDir }
45+ const npmEnv = { ...process . env , [ pathKey ] : currentPath ? currentPath + path . delimiter + nodeDir : nodeDir }
4246 const npmExitCode = await runCommand ( 'npm' , [ 'ci' ] , { cwd : dest , env : npmEnv } )
4347 if ( npmExitCode !== 0 ) {
4448 return npmExitCode
0 commit comments