Compare commits

..

1 Commits

Author SHA1 Message Date
Zoltan Kochan
c3e11127ab fix: append (not prepend) action node dir to PATH for npm bootstrap
#239 prepended `dirname(process.execPath)` to PATH so npm's
`#!/usr/bin/env node` shebang resolves on GHE self-hosted runners
where node isn't on PATH. But on runners with a prior `setup-node`
step, this shadowed the user's installed toolchain with the
runner-bundled node (e.g. externals/node24/bin), pairing the user's
npm with a mismatched node — or picking up a broken `npm` shipped
next to the runner-bundled node.

Append instead so a user-installed toolchain on PATH keeps
precedence; the runner's node dir remains as a fallback for the
original #234 case where node isn't on PATH at all.

Fixes #240
2026-05-02 10:48:15 +02:00
8 changed files with 203 additions and 276 deletions

View File

@@ -166,49 +166,6 @@ jobs:
fi
shell: bash
test_bin_dest_output:
name: 'Test bin_dest output points to requested version (${{ matrix.version }}, ${{ matrix.os }})'
# Regression test for #247: invoking pnpm via the `bin_dest` output returned the
# bootstrap version because self-update writes the target to `${bin_dest}/bin/`,
# not directly into `${bin_dest}/`.
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- macos-latest
- windows-latest
version:
- '9.15.5'
- '10.33.2'
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- id: pnpm
name: Run the action
uses: ./
with:
version: ${{ matrix.version }}
- name: 'Test: bin_dest/pnpm reports requested version'
# Pass paths via env, not template interpolation, so Windows
# backslashes in `bin_dest` aren't eaten by bash's escape handling.
env:
BIN_DEST: ${{ steps.pnpm.outputs.bin_dest }}
REQUIRED: ${{ matrix.version }}
run: |
actual="$("$BIN_DEST/pnpm" --version)"
echo "pnpm version via bin_dest: ${actual}"
if [ "${actual}" != "${REQUIRED}" ]; then
echo "Expected pnpm version ${REQUIRED}, but got ${actual}"
exit 1
fi
shell: bash
test_package_manager_field:
name: 'Test packageManager field is respected (${{ matrix.version }}, ${{ matrix.os }})'
# Reproduces #227: when `packageManager` is set in package.json and no `version:` input is given,

299
dist/index.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -20,10 +20,9 @@ async function main() {
async function runMain(inputs: Inputs) {
saveState('is_post', 'true')
const binDest = await installPnpm(inputs)
if (binDest === undefined) return
await installPnpm(inputs)
console.log('Installation Completed!')
setOutputs(inputs, binDest)
setOutputs(inputs)
await restoreCache(inputs)

View File

@@ -5,13 +5,13 @@
"packages": {
"": {
"dependencies": {
"@pnpm/exe": "11.0.4"
"@pnpm/exe": "11.0.0-rc.5"
}
},
"node_modules/@pnpm/exe": {
"version": "11.0.4",
"resolved": "https://registry.npmjs.org/@pnpm/exe/-/exe-11.0.4.tgz",
"integrity": "sha512-3OwYqbbj1KtuUqoMo5OEkY8nU/WutZ7L5ADFl0bbW9oyqU55U37aDqA3NJNSk28CyszNARfrjerAF2DW2TsV7w==",
"version": "11.0.0-rc.5",
"resolved": "https://registry.npmjs.org/@pnpm/exe/-/exe-11.0.0-rc.5.tgz",
"integrity": "sha512-HT1HxzeFc6RVIMhngQZ7bQgTNzF0IckeFpOvnwCJKfsjfsD/po3LvUVsidCvpALxCWOft1TuBZUkdHq03pEolA==",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
@@ -28,20 +28,20 @@
"url": "https://opencollective.com/pnpm"
},
"optionalDependencies": {
"@pnpm/linux-arm64": "11.0.4",
"@pnpm/linux-x64": "11.0.4",
"@pnpm/linuxstatic-arm64": "11.0.4",
"@pnpm/linuxstatic-x64": "11.0.4",
"@pnpm/macos-arm64": "11.0.4",
"@pnpm/macos-x64": "11.0.4",
"@pnpm/win-arm64": "11.0.4",
"@pnpm/win-x64": "11.0.4"
"@pnpm/linux-arm64": "11.0.0-rc.5",
"@pnpm/linux-x64": "11.0.0-rc.5",
"@pnpm/linuxstatic-arm64": "11.0.0-rc.5",
"@pnpm/linuxstatic-x64": "11.0.0-rc.5",
"@pnpm/macos-arm64": "11.0.0-rc.5",
"@pnpm/macos-x64": "11.0.0-rc.5",
"@pnpm/win-arm64": "11.0.0-rc.5",
"@pnpm/win-x64": "11.0.0-rc.5"
}
},
"node_modules/@pnpm/linux-arm64": {
"version": "11.0.4",
"resolved": "https://registry.npmjs.org/@pnpm/linux-arm64/-/linux-arm64-11.0.4.tgz",
"integrity": "sha512-Bz7V2sFypoGHX/t5w/w7jnCw5DCK3C8s5q8whHJJ3iS5kRznX3Q1F4LwSjjy+lsi777fHyNIvD7qtNmdt9IKoA==",
"version": "11.0.0-rc.5",
"resolved": "https://registry.npmjs.org/@pnpm/linux-arm64/-/linux-arm64-11.0.0-rc.5.tgz",
"integrity": "sha512-AreNJJI0r5oEsv5+i+FMVK8AeYs0MpWTGWc2GQwf7qi/w8uA8UxVlIDwhgwY+R6YgdrYVrEjgbU4WcqIqYfgog==",
"cpu": [
"arm64"
],
@@ -55,9 +55,9 @@
}
},
"node_modules/@pnpm/linux-x64": {
"version": "11.0.4",
"resolved": "https://registry.npmjs.org/@pnpm/linux-x64/-/linux-x64-11.0.4.tgz",
"integrity": "sha512-u0Yn1gytR1vKdPk6fYF500H8ZWQlj0cTuIQPp+5GYVPkMmA5bSw41RNIDPBfjDlE8ERmQWaQcrgmTcmTZ+n22A==",
"version": "11.0.0-rc.5",
"resolved": "https://registry.npmjs.org/@pnpm/linux-x64/-/linux-x64-11.0.0-rc.5.tgz",
"integrity": "sha512-NzZPWeIVxCEfQs84wR/O3IND2HSDOClPB2L8vvkWb8KQ4pczOG2x3aNkltXDwYVKxvw4URmwct5u57JGTEvtfg==",
"cpu": [
"x64"
],
@@ -71,15 +71,12 @@
}
},
"node_modules/@pnpm/linuxstatic-arm64": {
"version": "11.0.4",
"resolved": "https://registry.npmjs.org/@pnpm/linuxstatic-arm64/-/linuxstatic-arm64-11.0.4.tgz",
"integrity": "sha512-0aitEcfhWNXNZhfJGt/kJaRvfcdtJzXZpV+toJN94kfawSJnhuawfnUSXMi/3m0G97HkJc7BH8rOz3sojUKt0g==",
"version": "11.0.0-rc.5",
"resolved": "https://registry.npmjs.org/@pnpm/linuxstatic-arm64/-/linuxstatic-arm64-11.0.0-rc.5.tgz",
"integrity": "sha512-xK+U/fJDkvzs4ktswrCZ03cTSEAeFTfgUG88r2J+6JEDGuY/foNOMnnSNOiSplpaufY+Ie+uL+PEDlTyIy46Xg==",
"cpu": [
"arm64"
],
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
@@ -90,15 +87,12 @@
}
},
"node_modules/@pnpm/linuxstatic-x64": {
"version": "11.0.4",
"resolved": "https://registry.npmjs.org/@pnpm/linuxstatic-x64/-/linuxstatic-x64-11.0.4.tgz",
"integrity": "sha512-xDJdeJ7D2YvDBy2/IH9lEqMKiSuZiV8190XKWOgQgxUGGeuW4z3j6Ewpl0S5bXsWuNjAgC+uCKp7Qp3P7cXAvw==",
"version": "11.0.0-rc.5",
"resolved": "https://registry.npmjs.org/@pnpm/linuxstatic-x64/-/linuxstatic-x64-11.0.0-rc.5.tgz",
"integrity": "sha512-Z1kSilngaM2URfPhBjam/xhMDAn5jl8V0L5CjG/Gg5unmKkipyF93OYMpfnny7A9p1KWi6sNql/KufzUmRP4Eg==",
"cpu": [
"x64"
],
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
@@ -109,9 +103,9 @@
}
},
"node_modules/@pnpm/macos-arm64": {
"version": "11.0.4",
"resolved": "https://registry.npmjs.org/@pnpm/macos-arm64/-/macos-arm64-11.0.4.tgz",
"integrity": "sha512-dNR69jUARtGFuyyLE9VuyxhRUKC8MO/7/xIyAdeIMZAD5ej0Y/Ct0DYCa/FLbgFL1nXaXmp4+gRMfJBkkrKfQQ==",
"version": "11.0.0-rc.5",
"resolved": "https://registry.npmjs.org/@pnpm/macos-arm64/-/macos-arm64-11.0.0-rc.5.tgz",
"integrity": "sha512-98p3ilSzkyusC2bxk7Ya34CWt9MeJy/+kpXfwn9YgnOD7GDqCjYY9dlPB9yrkdtKUUMeOIvOuacAQTWnCg2GOQ==",
"cpu": [
"arm64"
],
@@ -125,9 +119,9 @@
}
},
"node_modules/@pnpm/macos-x64": {
"version": "11.0.4",
"resolved": "https://registry.npmjs.org/@pnpm/macos-x64/-/macos-x64-11.0.4.tgz",
"integrity": "sha512-RfyrxSBajeEU16dZsgFjbdagDV9F4HNCJfbBgm8IbGjL0+J95naM/VmCDLd6S3+1tISeI2MxtcyCxqjKJsD/BA==",
"version": "11.0.0-rc.5",
"resolved": "https://registry.npmjs.org/@pnpm/macos-x64/-/macos-x64-11.0.0-rc.5.tgz",
"integrity": "sha512-WZ9UqjTbZN+dMZcy4qaPDsEo4sxTIrw5H+fDvdxT1GUavsf8SBDpvzZMHrGDQ/k22H8oKvPtJ+RGd/Ie5dvbuA==",
"cpu": [
"x64"
],
@@ -141,9 +135,9 @@
}
},
"node_modules/@pnpm/win-arm64": {
"version": "11.0.4",
"resolved": "https://registry.npmjs.org/@pnpm/win-arm64/-/win-arm64-11.0.4.tgz",
"integrity": "sha512-fOQEv8b9KxZlUAxPPXSQQUUIrt2nY24Qwd4RzCPpatacBnsE4JIadlr/B4V5z2zFxmV7FdHr7nYUhv2RqTlY/w==",
"version": "11.0.0-rc.5",
"resolved": "https://registry.npmjs.org/@pnpm/win-arm64/-/win-arm64-11.0.0-rc.5.tgz",
"integrity": "sha512-hxgDmF4xpSVvUPvH+HdMllvHcV2zuYUn/uK182gzFvZ9DE0xEGVj09XaSn5VMbpa32i25oIqaT89QfMcOw/TJg==",
"cpu": [
"arm64"
],
@@ -157,9 +151,9 @@
}
},
"node_modules/@pnpm/win-x64": {
"version": "11.0.4",
"resolved": "https://registry.npmjs.org/@pnpm/win-x64/-/win-x64-11.0.4.tgz",
"integrity": "sha512-pErHAV8m3NZuPSeCmH3senTSHX0nwkH5lLzQSpiFuyt08hq8sqL3jDymT4ri9N7ixPN9RFZghZIiT3h+Croaew==",
"version": "11.0.0-rc.5",
"resolved": "https://registry.npmjs.org/@pnpm/win-x64/-/win-x64-11.0.0-rc.5.tgz",
"integrity": "sha512-B1H/6jhzW/6VLr8Bc3zOhMd2P3srANWytuBq0uppR5c7OJwUlqXqJtB6Q4nOEjWYZ2sA5m2xuFiaMeioZiiqgA==",
"cpu": [
"x64"
],
@@ -230,9 +224,6 @@
"cpu": [
"arm64"
],
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@@ -249,9 +240,6 @@
"cpu": [
"arm64"
],
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
@@ -268,9 +256,6 @@
"cpu": [
"x64"
],
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@@ -287,9 +272,6 @@
"cpu": [
"x64"
],
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [

View File

@@ -5,13 +5,13 @@
"packages": {
"": {
"dependencies": {
"pnpm": "11.0.4"
"pnpm": "11.0.0-rc.5"
}
},
"node_modules/pnpm": {
"version": "11.0.4",
"resolved": "https://registry.npmjs.org/pnpm/-/pnpm-11.0.4.tgz",
"integrity": "sha512-CjlxZQB6AU7VKRmmHl9GxIubyohATDA+yuzGP2Le9WOJjTxril1epYEes5jP4DqwXaGlzpY/Em1erUwC+TuDww==",
"version": "11.0.0-rc.5",
"resolved": "https://registry.npmjs.org/pnpm/-/pnpm-11.0.0-rc.5.tgz",
"integrity": "sha512-xGn7aqE6meV67JNc17hv9CJwH0YC7KwiMdPcIJEFhuv7a1CntFXQd47CKuVpEtjY6I6fngoDwIdaakF4OpShvQ==",
"license": "MIT",
"bin": {
"pn": "bin/pnpm.mjs",

View File

@@ -4,15 +4,13 @@ import runSelfInstaller from './run'
export { runSelfInstaller }
export async function install(inputs: Inputs): Promise<string | undefined> {
export async function install(inputs: Inputs) {
startGroup('Running self-installer...')
const { exitCode, binDest } = await runSelfInstaller(inputs)
const status = await runSelfInstaller(inputs)
endGroup()
if (exitCode) {
setFailed(`Something went wrong, self-installer exits with code ${exitCode}`)
return undefined
if (status) {
return setFailed(`Something went wrong, self-installer exits with code ${status}`)
}
return binDest
}
export default install

View File

@@ -12,12 +12,7 @@ import exeLock from './bootstrap/exe-lock.json'
const BOOTSTRAP_PNPM_PACKAGE_JSON = JSON.stringify({ private: true, dependencies: { pnpm: pnpmLock.packages['node_modules/pnpm'].version } })
const BOOTSTRAP_EXE_PACKAGE_JSON = JSON.stringify({ private: true, dependencies: { '@pnpm/exe': exeLock.packages['node_modules/@pnpm/exe'].version } })
export interface SelfInstallerResult {
exitCode: number
binDest: string
}
export async function runSelfInstaller(inputs: Inputs): Promise<SelfInstallerResult> {
export async function runSelfInstaller(inputs: Inputs): Promise<number> {
const { version, dest, packageJsonFile } = inputs
// pnpm v11 requires Node >= 22.13; use standalone (exe) bootstrap which
@@ -50,7 +45,7 @@ export async function runSelfInstaller(inputs: Inputs): Promise<SelfInstallerRes
const npmEnv = { ...process.env, [pathKey]: currentPath ? currentPath + path.delimiter + nodeDir : nodeDir }
const npmExitCode = await runCommand('npm', ['ci'], { cwd: dest, env: npmEnv })
if (npmExitCode !== 0) {
return { exitCode: npmExitCode, binDest: path.join(dest, 'node_modules', '.bin') }
return npmExitCode
}
// On Windows with standalone mode, npm's .bin shims can't properly
@@ -92,18 +87,11 @@ export async function runSelfInstaller(inputs: Inputs): Promise<SelfInstallerRes
const args = standalone ? ['self-update', targetVersion] : [bootstrapPnpm, 'self-update', targetVersion]
const exitCode = await runCommand(cmd, args, { cwd: dest })
if (exitCode !== 0) {
return { exitCode, binDest: pnpmHome }
return exitCode
}
// self-update writes the target pnpm/pnpx into PNPM_HOME/bin, leaving
// the bootstrap symlinks in pnpmHome pointing at the old version. Use
// PNPM_HOME/bin so consumers of the bin_dest output (e.g.
// `${steps.pnpm.outputs.bin_dest}/pnpm`) invoke the requested version.
return { exitCode: 0, binDest: path.join(pnpmHome, 'bin') }
}
// No explicit target version: rely on the bootstrap pnpm to switch to
// the version declared in packageManager/devEngines at runtime.
return { exitCode: 0, binDest: pnpmHome }
return 0
}
function readTargetVersion(opts: {

View File

@@ -1,7 +1,9 @@
import { setOutput } from '@actions/core'
import { Inputs } from '../inputs'
import { getBinDest } from '../utils'
export function setOutputs(inputs: Inputs, binDest: string) {
export function setOutputs(inputs: Inputs) {
const binDest = getBinDest(inputs)
// NOTE: addPath is already called in installPnpm — do not call it again
// here, as a second addPath would shadow the correct entry on Windows.
setOutput('dest', inputs.dest)