1
0
mirror of https://github.com/pnpm/action-setup.git synced 2026-06-26 16:43:47 +08:00

Compare commits

..

9 Commits

Author SHA1 Message Date
Oscar Busk
8a1f0929f7 Merge 35353b8037 into 3a0024f066 2025-12-05 16:51:05 +01:00
Oscar Busk
35353b8037 Add store_prune to run name 2025-10-28 01:07:44 +01:00
Oscar Busk
4f04570f82 Add store_prune to tests 2025-10-28 00:58:14 +01:00
Oscar Busk
40fbc12c16 Actually check for run_install before store_prune, to match documentation 2025-10-28 00:45:12 +01:00
Oscar Busk
14f23f2699 Add more documentation regarding caching, pruning and the run_install and store_prune options 2025-10-28 00:44:29 +01:00
Oscar Busk
6a5147c614 Update documentation about pnpm store prune 2025-10-28 00:41:07 +01:00
Oscar Busk
82352014bc Add option to disable automatic pruning of store 2025-10-28 00:35:57 +01:00
Oscar Busk
37f0218d62 Make the message when not pruning more helpful
The original message made it sound like it checked the store and decided there was nothing to prune, in reality pruning just did not run if run_install was not set.
2025-10-28 00:31:32 +01:00
Oscar Busk
3cec5320c9 Run pruning as part of main action, not in post
The post action will execute too late to actually improve any caching. By pruning directly after running pnpm install(s), we make sure the store is as clean as possible before continuing. This means any attempt to cache the pnpm store will be caching a pruned store
2025-10-28 00:26:18 +01:00
26 changed files with 237624 additions and 2021 deletions

View File

@@ -1,28 +0,0 @@
name: pr-check
on: [ pull_request ]
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
cancel-in-progress: true
jobs:
check-dist:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- name: Setup pnpm
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
with:
run_install: true
version: 9
- name: Update dist/index.js
run: pnpm run build
- name: Check for uncommitted changes in dist
run: git diff --exit-code dist/index.js

View File

@@ -22,7 +22,7 @@ jobs:
- windows-latest - windows-latest
steps: steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - uses: actions/checkout@v4
- name: Run the action - name: Run the action
uses: ./ uses: ./
@@ -32,23 +32,8 @@ jobs:
- name: 'Test: which' - name: 'Test: which'
run: which pnpm; which pnpx run: which pnpm; which pnpx
- name: 'Test: version' - name: 'Test: install'
run: | run: pnpm install
actual="$(pnpm --version)"
echo "pnpm version: ${actual}"
if [[ ! "${actual}" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-.+)?$ ]]; then
echo "ERROR: pnpm --version did not produce valid output"
exit 1
fi
shell: bash
- name: 'Test: install in a fresh project'
run: |
mkdir /tmp/test-project
cd /tmp/test-project
pnpm init
pnpm add is-odd
shell: bash
test_dest: test_dest:
name: Test with dest name: Test with dest
@@ -66,7 +51,7 @@ jobs:
- windows-latest - windows-latest
steps: steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - uses: actions/checkout@v4
- name: Run the action - name: Run the action
uses: ./ uses: ./
@@ -77,15 +62,8 @@ jobs:
- name: 'Test: which' - name: 'Test: which'
run: which pnpm && which pnpx run: which pnpm && which pnpx
- name: 'Test: version' - name: 'Test: install'
run: | run: pnpm install
actual="$(pnpm --version)"
echo "pnpm version: ${actual}"
if [[ ! "${actual}" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-.+)?$ ]]; then
echo "ERROR: pnpm --version did not produce valid output"
exit 1
fi
shell: bash
test_standalone: test_standalone:
name: Test with standalone name: Test with standalone
@@ -97,166 +75,53 @@ jobs:
matrix: matrix:
os: os:
- ubuntu-latest - ubuntu-latest
- macos-latest
- windows-latest - windows-latest
standalone:
- true
- false
steps: steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - uses: actions/checkout@v4
- name: Run the action - name: Run the action
uses: ./ uses: ./
with: with:
version: 9.15.0 version: 9.15.0
standalone: true standalone: ${{ matrix.standalone }}
- name: 'Test: which' - name: install Node.js
uses: actions/setup-node@v4
with:
# pnpm@7.0.0 is not compatible with Node.js 12
node-version: 12.22.12
- name: 'Test: which (pnpm)'
run: which pnpm run: which pnpm
- name: 'Test: version' - name: 'Test: which (pnpx)'
if: matrix.standalone == false
run: which pnpx
- name: 'Test: install when standalone is true'
if: matrix.standalone
run: pnpm install
- name: 'Test: install when standalone is false'
if: matrix.standalone == false
# Since the default shell on windows runner is pwsh, we specify bash explicitly
shell: bash
run: | run: |
actual="$(pnpm --version)" if pnpm install; then
echo "pnpm version: ${actual}" echo "pnpm install should fail"
if [[ ! "${actual}" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-.+)?$ ]]; then
echo "ERROR: pnpm --version did not produce valid output"
exit 1 exit 1
fi
shell: bash
- name: 'Test: install in a fresh project'
run: |
mkdir /tmp/test-standalone
cd /tmp/test-standalone
pnpm init
pnpm add is-odd
shell: bash
test_version_respects_request:
name: 'Test version input is actually installed (${{ matrix.version }}, ${{ matrix.os }})'
# Regression test for #225 / #230: the bootstrap pnpm on PATH was shadowing the self-updated binary,
# so a user requesting e.g. `version: 9.15.5` would silently get the bootstrap version.
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- macos-latest
- windows-latest
version:
- '9.15.5'
- '10.33.0'
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- name: Run the action
uses: ./
with:
version: ${{ matrix.version }}
- name: 'Test: exact version installed'
run: |
required='${{ matrix.version }}'
actual="$(pnpm --version)"
echo "pnpm version: ${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,
# the action should install the version specified there.
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- macos-latest
- windows-latest
version:
- '9.15.5'
- '10.33.0'
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- name: Set up package.json with packageManager field
run: echo '{"packageManager":"pnpm@${{ matrix.version }}"}' > package.json
shell: bash
- name: Run the action
uses: ./
- name: 'Test: exact version installed'
run: |
required='${{ matrix.version }}'
actual="$(pnpm --version)"
echo "pnpm version: ${actual}"
if [ "${actual}" != "${required}" ]; then
echo "Expected pnpm version ${required}, but got ${actual}"
exit 1
fi
shell: bash
test_dev_engines:
name: Test with devEngines.packageManager
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- macos-latest
- windows-latest
version:
- '9.15.5'
- '>=9.15.0'
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- name: Set up package.json with devEngines.packageManager
run: echo '{"devEngines":{"packageManager":{"name":"pnpm","version":"${{ matrix.version }}","onFail":"download"}}}' > package.json
shell: bash
- name: Run the action
uses: ./
- name: 'Test: which'
run: which pnpm; which pnpx
- name: 'Test: version'
run: |
set -e
required='${{ matrix.version }}'
actual="$(pnpm --version)"
echo "pnpm version: ${actual}"
if [ "${required}" = ">=9.15.0" ]; then
min="9.15.0"
if [ "$(printf '%s\n' "${min}" "${actual}" | sort -V | head -n1)" != "${min}" ]; then
echo "Expected pnpm version >= ${min}, but got ${actual}"
exit 1
fi
else else
if [ "${actual}" != "${required}" ]; then echo "pnpm install failed as expected"
echo "Expected pnpm version ${required}, but got ${actual}"
exit 1
fi
fi fi
shell: bash
test_run_install: test_run_install:
name: 'Test with run_install (${{ matrix.run_install.name }}, ${{ matrix.os }})' name: 'Test with run_install (${{ matrix.run_install.name }}, prune=${{matrix.store_prune}}, ${{ matrix.os }})'
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
@@ -272,6 +137,11 @@ jobs:
run_install: run_install:
- name: 'null' - name: 'null'
value: 'null' value: 'null'
- name: 'empty object'
value: '{}'
- name: 'recursive'
value: |
recursive: true
- name: 'global' - name: 'global'
value: | value: |
args: args:
@@ -279,25 +149,31 @@ jobs:
- --global-dir=./pnpm-global - --global-dir=./pnpm-global
- npm - npm
- yarn - yarn
- name: 'array'
value: |
- {}
- recursive: true
- args:
- --global
- --global-dir=./pnpm-global
- npm
- yarn
store_prune:
- 'true'
- 'false'
steps: steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - uses: actions/checkout@v4
- name: Run the action - name: Run the action
uses: ./ uses: ./
with: with:
version: 9.15.5 version: 9.15.5
run_install: ${{ matrix.run_install.value }} run_install: ${{ matrix.run_install.value }}
store_prune: ${{ matrix.store_prune }}
- name: 'Test: which' - name: 'Test: which'
run: which pnpm; which pnpx run: which pnpm; which pnpx
- name: 'Test: version' - name: 'Test: install'
run: | run: pnpm install
actual="$(pnpm --version)"
echo "pnpm version: ${actual}"
if [[ ! "${actual}" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-.+)?$ ]]; then
echo "ERROR: pnpm --version did not produce valid output"
exit 1
fi
shell: bash

3
.gitignore vendored
View File

@@ -2,6 +2,8 @@ node_modules
*.log *.log
/dist/* /dist/*
!/dist/index.js !/dist/index.js
!/dist/pnpm.cjs
!/dist/worker.js
tmp tmp
temp temp
*.tmp *.tmp
@@ -9,4 +11,3 @@ temp
tmp.* tmp.*
temp.* temp.*
.pnpm-store .pnpm-store
.claude

View File

@@ -14,7 +14,7 @@ Version of pnpm to install.
**Optional** when there is a [`packageManager` field in the `package.json`](https://nodejs.org/api/corepack.html). **Optional** when there is a [`packageManager` field in the `package.json`](https://nodejs.org/api/corepack.html).
otherwise, this field is **required** It supports npm versioning scheme, it could be an exact version (such as `10.9.8`), or a version range (such as `10`, `10.x.x`, `10.9.x`, `^10.9.8`, `*`, etc.), or `latest`. otherwise, this field is **required** It supports npm versioning scheme, it could be an exact version (such as `6.24.1`), or a version range (such as `6`, `6.x.x`, `6.24.x`, `^6.24.1`, `*`, etc.), or `latest`.
### `dest` ### `dest`
@@ -30,6 +30,8 @@ If `run_install` is `true`, pnpm will install dependencies recursively.
If `run_install` is a YAML string representation of either an object or an array, pnpm will execute every install commands. If `run_install` is a YAML string representation of either an object or an array, pnpm will execute every install commands.
If any `run_install` is not falsy, and `store_prune` is not set to `false`, `pnpm store prune` will be executed after all install commands have been executed. This is to ensure the pnpm store is pruned before caching.
#### `run_install.recursive` #### `run_install.recursive`
**Optional** (_type:_ `boolean`, _default:_ `false`) Whether to use `pnpm recursive install`. **Optional** (_type:_ `boolean`, _default:_ `false`) Whether to use `pnpm recursive install`.
@@ -42,13 +44,9 @@ If `run_install` is a YAML string representation of either an object or an array
**Optional** (_type:_ `string[]`) Additional arguments after `pnpm [recursive] install`, e.g. `[--ignore-scripts, --strict-peer-dependencies]`. **Optional** (_type:_ `string[]`) Additional arguments after `pnpm [recursive] install`, e.g. `[--ignore-scripts, --strict-peer-dependencies]`.
### `cache` #### `store_prune`
**Optional** (_type:_ `boolean`, _default:_ `false`) Whether to cache the pnpm store directory. **Optional** (_type:_ `boolean`, _default:_ `true`) Whether to run `pnpm store prune` after installation. If `run_install` is falsy, this option will be ignored. If you run `pnpm install` on your own, and intend to cache the pnpm store, it's recommended to run `pnpm store prune` yourself to make sure the store that will be cached is pruned.
### `cache_dependency_path`
**Optional** (_type:_ `string|string[]`, _default:_ `pnpm-lock.yaml`) File path to the pnpm lockfile, which contents hash will be used as a cache key.
### `package_json_file` ### `package_json_file`
@@ -86,7 +84,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: pnpm/action-setup@v6 - uses: pnpm/action-setup@v4
with: with:
version: 10 version: 10
``` ```
@@ -105,7 +103,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: pnpm/action-setup@v6 - uses: pnpm/action-setup@v4
``` ```
### Install pnpm and a few npm packages ### Install pnpm and a few npm packages
@@ -120,9 +118,9 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v4
- uses: pnpm/action-setup@v6 - uses: pnpm/action-setup@v4
with: with:
version: 10 version: 10
run_install: | run_install: |
@@ -144,19 +142,28 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v6 uses: actions/checkout@v4
- uses: pnpm/action-setup@v6 - uses: pnpm/action-setup@v4
name: Install pnpm name: Install pnpm
with: with:
version: 10 version: 10
cache: true run_install: false
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'
- name: Install dependencies - name: Install dependencies
run: pnpm install run: pnpm install
- name: Prune pnpm store
run: pnpm store prune
``` ```
**Note:** You don't need to run `pnpm store prune` at the end; post-action has already taken care of that. **Note:** If you you opt to run install on your own (`run_install: false`), it's recommended to run [`pnpm store prune`](https://pnpm.io/cli/store#prune) after installation to make sure the store that will be cached is pruned.
## Notes ## Notes

View File

@@ -15,16 +15,12 @@ inputs:
description: If specified, run `pnpm install` description: If specified, run `pnpm install`
required: false required: false
default: 'null' default: 'null'
cache: store_prune:
description: Whether to cache the pnpm store directory description: Enable store pruning after installation. Set to false to disable.
required: false required: false
default: 'false' default: 'true'
cache_dependency_path:
description: File path to the pnpm lockfile, which contents hash will be used as a cache key
required: false
default: 'pnpm-lock.yaml'
package_json_file: package_json_file:
description: File path to the package.json to read "packageManager" configuration. This path must be relative to the repository root (GITHUB_WORKSPACE). description: File path to the package.json to read "packageManager" configuration
required: false required: false
default: 'package.json' default: 'package.json'
standalone: standalone:
@@ -37,6 +33,5 @@ outputs:
bin_dest: bin_dest:
description: Location of `pnpm` and `pnpx` command description: Location of `pnpm` and `pnpx` command
runs: runs:
using: node24 using: node20
main: dist/index.js main: dist/index.js
post: dist/index.js

297
dist/index.js vendored

File diff suppressed because one or more lines are too long

220780
dist/pnpm.cjs vendored Normal file

File diff suppressed because one or more lines are too long

16625
dist/worker.js vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,24 +1,22 @@
{ {
"private": true, "private": true,
"scripts": { "scripts": {
"build:bundle": "esbuild src/index.ts --bundle --platform=node --target=node24 --format=cjs --minify --outfile=dist/index.js --loader:.json=json", "build:ncc": "ncc build --minify --no-source-map-register --no-cache dist/tsc/index.js --out dist/",
"build": "pnpm run build:bundle", "build": "tsc && pnpm run build:ncc",
"start": "pnpm run build && sh ./run.sh", "start": "pnpm run build && sh ./run.sh",
"update-bootstrap": "node scripts/update-bootstrap.mjs" "update-pnpm-dist": "pnpm install && cp ./node_modules/pnpm/dist/pnpm.cjs ./dist/pnpm.cjs && cp ./node_modules/pnpm/dist/worker.js ./dist/worker.js"
}, },
"dependencies": { "dependencies": {
"@actions/cache": "^4.1.0",
"@actions/core": "^1.10.1", "@actions/core": "^1.10.1",
"@actions/exec": "^1.1.1",
"@actions/glob": "^0.5.0",
"@types/expand-tilde": "^2.0.2", "@types/expand-tilde": "^2.0.2",
"@types/node": "^22.0.0", "@types/node": "^20.11.5",
"expand-tilde": "^2.0.2", "expand-tilde": "^2.0.2",
"yaml": "^2.3.4", "yaml": "^2.3.4",
"zod": "^3.22.4" "zod": "^3.22.4"
}, },
"devDependencies": { "devDependencies": {
"esbuild": "^0.27.4", "@vercel/ncc": "^0.38.1",
"pnpm": "^8.14.3",
"typescript": "^5.3.3" "typescript": "^5.3.3"
} }
} }

902
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +0,0 @@
packages:
- '.'
allowBuilds:
esbuild: true

View File

@@ -1,47 +0,0 @@
#!/usr/bin/env node
// Usage: node scripts/update-bootstrap.mjs [version]
// If version is omitted, fetches the latest next-11 tag from npm.
// Regenerates the bootstrap lockfiles used by action-setup to install pnpm via npm.
import { execSync } from 'child_process'
import { mkdtempSync, rmSync, readFileSync, writeFileSync } from 'fs'
import { join } from 'path'
import { tmpdir } from 'os'
const BOOTSTRAP_DIR = new URL('../src/install-pnpm/bootstrap/', import.meta.url).pathname
const version = process.argv[2] || resolveLatestVersion()
console.log(`Updating bootstrap lockfiles to pnpm@${version} ...`)
generateLock('pnpm-lock.json', { pnpm: version }, 'bootstrap-pnpm')
generateLock('exe-lock.json', { '@pnpm/exe': version }, 'bootstrap-exe')
console.log('Done!')
function resolveLatestVersion() {
const json = execSync('npm view @pnpm/exe dist-tags --json', { encoding: 'utf8' })
const tags = JSON.parse(json)
const version = tags['next-11'] || tags['latest']
if (!version) {
console.error('Could not determine latest pnpm version from npm dist-tags')
process.exit(1)
}
return version
}
function generateLock(filename, dependencies, name) {
const tmp = mkdtempSync(join(tmpdir(), 'pnpm-bootstrap-'))
try {
writeFileSync(join(tmp, 'package.json'), JSON.stringify({ private: true, dependencies }))
execSync('npm install --package-lock-only --ignore-scripts', { cwd: tmp, stdio: 'pipe' })
const lock = readFileSync(join(tmp, 'package-lock.json'), 'utf8')
const parsed = JSON.parse(lock)
parsed.name = name
writeFileSync(join(BOOTSTRAP_DIR, filename), JSON.stringify(parsed, null, 2) + '\n')
console.log(` ${filename} -> ${Object.values(dependencies)[0]}@${version}`)
} finally {
rmSync(tmp, { recursive: true, force: true })
}
}

View File

@@ -1,19 +0,0 @@
import { isFeatureAvailable } from '@actions/cache'
import { endGroup, startGroup, warning } from '@actions/core'
import { Inputs } from '../inputs'
import { runRestoreCache } from './run'
export async function restoreCache(inputs: Inputs) {
if (!inputs.cache) return
if (!isFeatureAvailable()) {
warning('Cache is not available, skipping cache restoration')
return
}
startGroup('Restoring cache...')
await runRestoreCache(inputs)
endGroup()
}
export default restoreCache

View File

@@ -1,39 +0,0 @@
import { restoreCache } from '@actions/cache'
import { debug, info, saveState, setOutput } from '@actions/core'
import { getExecOutput } from '@actions/exec'
import { hashFiles } from '@actions/glob'
import os from 'os'
import { Inputs } from '../inputs'
export async function runRestoreCache(inputs: Inputs) {
const cachePath = await getCacheDirectory()
saveState('cache_path', cachePath)
const fileHash = await hashFiles(inputs.cacheDependencyPath)
if (!fileHash) {
throw new Error('Some specified paths were not resolved, unable to cache dependencies.')
}
const primaryKey = `pnpm-cache-${process.env.RUNNER_OS}-${os.arch()}-${fileHash}`
debug(`Primary key is ${primaryKey}`)
saveState('cache_primary_key', primaryKey)
let cacheKey = await restoreCache([cachePath], primaryKey)
setOutput('cache-hit', Boolean(cacheKey))
if (!cacheKey) {
info(`Cache is not found`)
return
}
saveState('cache_restored_key', cacheKey)
info(`Cache restored from key: ${cacheKey}`)
}
async function getCacheDirectory() {
const { stdout } = await getExecOutput('pnpm store path --silent')
const cacheFolderPath = stdout.trim()
debug(`Cache folder is set to "${cacheFolderPath}"`)
return cacheFolderPath
}

View File

@@ -1,15 +0,0 @@
import { setFailed } from '@actions/core'
import { Inputs } from '../inputs'
import { runSaveCache } from './run'
export async function saveCache(inputs: Inputs) {
if (!inputs.cache) return
try {
await runSaveCache()
} catch (error) {
setFailed((error as Error).message)
}
}
export default saveCache

View File

@@ -1,18 +0,0 @@
import { saveCache } from '@actions/cache'
import { getState, info } from '@actions/core'
export async function runSaveCache() {
const state = getState('cache_restored_key')
const primaryKey = getState('cache_primary_key')
const cachePath = getState('cache_path')
if (primaryKey === state) {
info(`Cache hit occurred on the primary key ${primaryKey}, not saving cache.`)
return
}
const cacheId = await saveCache([cachePath], primaryKey)
if (cacheId == -1) return
info(`Cache saved with the key: ${primaryKey}`)
}

View File

@@ -1,7 +1,5 @@
import { setFailed, saveState, getState } from '@actions/core' import { setFailed } from '@actions/core'
import restoreCache from './cache-restore' import getInputs from './inputs'
import saveCache from './cache-save'
import getInputs, { Inputs } from './inputs'
import installPnpm from './install-pnpm' import installPnpm from './install-pnpm'
import setOutputs from './outputs' import setOutputs from './outputs'
import pnpmInstall from './pnpm-install' import pnpmInstall from './pnpm-install'
@@ -9,29 +7,11 @@ import pruneStore from './pnpm-store-prune'
async function main() { async function main() {
const inputs = getInputs() const inputs = getInputs()
if (getState('is_post') === 'true') {
await runPost(inputs)
} else {
await runMain(inputs)
}
}
async function runMain(inputs: Inputs) {
saveState('is_post', 'true')
await installPnpm(inputs) await installPnpm(inputs)
console.log('Installation Completed!') console.log('Installation Completed!')
setOutputs(inputs) setOutputs(inputs)
await restoreCache(inputs)
pnpmInstall(inputs) pnpmInstall(inputs)
}
async function runPost(inputs: Inputs) {
pruneStore(inputs) pruneStore(inputs)
await saveCache(inputs)
} }
main().catch(error => { main().catch(error => {

View File

@@ -5,9 +5,8 @@ import { RunInstall, parseRunInstall } from './run-install'
export interface Inputs { export interface Inputs {
readonly version?: string readonly version?: string
readonly dest: string readonly dest: string
readonly cache: boolean
readonly cacheDependencyPath: string
readonly runInstall: RunInstall[] readonly runInstall: RunInstall[]
readonly storePrune: boolean
readonly packageJsonFile: string readonly packageJsonFile: string
readonly standalone: boolean readonly standalone: boolean
} }
@@ -21,9 +20,8 @@ const parseInputPath = (name: string) => expandTilde(getInput(name, options))
export const getInputs = (): Inputs => ({ export const getInputs = (): Inputs => ({
version: getInput('version'), version: getInput('version'),
dest: parseInputPath('dest'), dest: parseInputPath('dest'),
cache: getBooleanInput('cache'),
cacheDependencyPath: parseInputPath('cache_dependency_path'),
runInstall: parseRunInstall('run_install'), runInstall: parseRunInstall('run_install'),
storePrune: getBooleanInput('store_prune'),
packageJsonFile: parseInputPath('package_json_file'), packageJsonFile: parseInputPath('package_json_file'),
standalone: getBooleanInput('standalone'), standalone: getBooleanInput('standalone'),
}) })

View File

@@ -1,5 +1,5 @@
import { getInput, error } from '@actions/core' import { getInput, error } from '@actions/core'
import { parse as parseYaml } from 'yaml' import * as yaml from 'yaml'
import { z, ZodError } from 'zod' import { z, ZodError } from 'zod'
const RunInstallSchema = z.object({ const RunInstallSchema = z.object({
@@ -20,7 +20,7 @@ export type RunInstall = z.infer<typeof RunInstallSchema>
export function parseRunInstall(inputName: string): RunInstall[] { export function parseRunInstall(inputName: string): RunInstall[] {
const input = getInput(inputName, { required: true }) const input = getInput(inputName, { required: true })
const parsedInput: unknown = parseYaml(input) const parsedInput: unknown = yaml.parse(input)
try { try {
const result: RunInstallInput = RunInstallInputSchema.parse(parsedInput) const result: RunInstallInput = RunInstallInputSchema.parse(parsedInput)

View File

@@ -1,282 +0,0 @@
{
"name": "bootstrap-exe",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"dependencies": {
"@pnpm/exe": "11.0.0-rc.2"
}
},
"node_modules/@pnpm/exe": {
"version": "11.0.0-rc.2",
"resolved": "https://registry.npmjs.org/@pnpm/exe/-/exe-11.0.0-rc.2.tgz",
"integrity": "sha512-EkL8nZApA0wUA7c5hDdbeuyNUkmkDRBn8evxx4O79SMlEX1D6XspEu9EkLmT+sqrHsAwKzHTHsNYwTSOuKavRg==",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
"@reflink/reflink": "0.1.19"
},
"bin": {
"pn": "pn",
"pnpm": "pnpm",
"pnpx": "pnpx",
"pnx": "pnx"
},
"funding": {
"url": "https://opencollective.com/pnpm"
},
"optionalDependencies": {
"@pnpm/linux-arm64": "11.0.0-rc.2",
"@pnpm/linux-x64": "11.0.0-rc.2",
"@pnpm/macos-arm64": "11.0.0-rc.2",
"@pnpm/macos-x64": "11.0.0-rc.2",
"@pnpm/win-arm64": "11.0.0-rc.2",
"@pnpm/win-x64": "11.0.0-rc.2"
}
},
"node_modules/@pnpm/linux-arm64": {
"version": "11.0.0-rc.2",
"resolved": "https://registry.npmjs.org/@pnpm/linux-arm64/-/linux-arm64-11.0.0-rc.2.tgz",
"integrity": "sha512-aw7wUq6ffXAfP7r9ZKa7GQmCoh/2EJcdb5ghkc8cgz0O2RZCmIaHqMV2O049iSAtblANkOu5uhwAZW7DKMJa3A==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"funding": {
"url": "https://opencollective.com/pnpm"
}
},
"node_modules/@pnpm/linux-x64": {
"version": "11.0.0-rc.2",
"resolved": "https://registry.npmjs.org/@pnpm/linux-x64/-/linux-x64-11.0.0-rc.2.tgz",
"integrity": "sha512-aCItGORv4lUjYldScyhd7uxgXQI3s1B1s99u5Eb42KRRC4Q8DAf7dboXbLGk7rQLjx8F9xIiaD7QX7YR8+MWEQ==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"funding": {
"url": "https://opencollective.com/pnpm"
}
},
"node_modules/@pnpm/macos-arm64": {
"version": "11.0.0-rc.2",
"resolved": "https://registry.npmjs.org/@pnpm/macos-arm64/-/macos-arm64-11.0.0-rc.2.tgz",
"integrity": "sha512-WsLK8St9Hpwp26qqdFVdLdDlJ3CLJVIkcFwP7G9b+HtkPZOx+Z9AGZ8iam1B7HSrf8XomZWlq0vntHDsc2uPTg==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"funding": {
"url": "https://opencollective.com/pnpm"
}
},
"node_modules/@pnpm/macos-x64": {
"version": "11.0.0-rc.2",
"resolved": "https://registry.npmjs.org/@pnpm/macos-x64/-/macos-x64-11.0.0-rc.2.tgz",
"integrity": "sha512-hiC0khjWqSu6l25rs52izVhPM+6IVbp89pLRyBMYTe5x2a9iydUsCloPl7E+SuNiZ5cNnG28qj3PDzc5upeH/Q==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"funding": {
"url": "https://opencollective.com/pnpm"
}
},
"node_modules/@pnpm/win-arm64": {
"version": "11.0.0-rc.2",
"resolved": "https://registry.npmjs.org/@pnpm/win-arm64/-/win-arm64-11.0.0-rc.2.tgz",
"integrity": "sha512-+bo8RmPQyPCKq+h1GE/QHJ7Ybt/4bWZLUSgXJQS6UOB7ar56g2g4ii1X5+8htkkdXxS5Uoj2TVqRjKp6hkkAdA==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"funding": {
"url": "https://opencollective.com/pnpm"
}
},
"node_modules/@pnpm/win-x64": {
"version": "11.0.0-rc.2",
"resolved": "https://registry.npmjs.org/@pnpm/win-x64/-/win-x64-11.0.0-rc.2.tgz",
"integrity": "sha512-srkbMALQgb4taTzKMlwqBZV+JHTh15jN4/FOVOGQ5XadjXdpJOievkvp/m87WankP8MX8th+mJhD9RX/rDOSOw==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"funding": {
"url": "https://opencollective.com/pnpm"
}
},
"node_modules/@reflink/reflink": {
"version": "0.1.19",
"resolved": "https://registry.npmjs.org/@reflink/reflink/-/reflink-0.1.19.tgz",
"integrity": "sha512-DmCG8GzysnCZ15bres3N5AHCmwBwYgp0As6xjhQ47rAUTUXxJiK+lLUxaGsX3hd/30qUpVElh05PbGuxRPgJwA==",
"license": "MIT",
"engines": {
"node": ">= 10"
},
"optionalDependencies": {
"@reflink/reflink-darwin-arm64": "0.1.19",
"@reflink/reflink-darwin-x64": "0.1.19",
"@reflink/reflink-linux-arm64-gnu": "0.1.19",
"@reflink/reflink-linux-arm64-musl": "0.1.19",
"@reflink/reflink-linux-x64-gnu": "0.1.19",
"@reflink/reflink-linux-x64-musl": "0.1.19",
"@reflink/reflink-win32-arm64-msvc": "0.1.19",
"@reflink/reflink-win32-x64-msvc": "0.1.19"
}
},
"node_modules/@reflink/reflink-darwin-arm64": {
"version": "0.1.19",
"resolved": "https://registry.npmjs.org/@reflink/reflink-darwin-arm64/-/reflink-darwin-arm64-0.1.19.tgz",
"integrity": "sha512-ruy44Lpepdk1FqDz38vExBY/PVUsjxZA+chd9wozjUH9JjuDT/HEaQYA6wYN9mf041l0yLVar6BCZuWABJvHSA==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@reflink/reflink-darwin-x64": {
"version": "0.1.19",
"resolved": "https://registry.npmjs.org/@reflink/reflink-darwin-x64/-/reflink-darwin-x64-0.1.19.tgz",
"integrity": "sha512-By85MSWrMZa+c26TcnAy8SDk0sTUkYlNnwknSchkhHpGXOtjNDUOxJE9oByBnGbeuIE1PiQsxDG3Ud+IVV9yuA==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@reflink/reflink-linux-arm64-gnu": {
"version": "0.1.19",
"resolved": "https://registry.npmjs.org/@reflink/reflink-linux-arm64-gnu/-/reflink-linux-arm64-gnu-0.1.19.tgz",
"integrity": "sha512-7P+er8+rP9iNeN+bfmccM4hTAaLP6PQJPKWSA4iSk2bNvo6KU6RyPgYeHxXmzNKzPVRcypZQTpFgstHam6maVg==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@reflink/reflink-linux-arm64-musl": {
"version": "0.1.19",
"resolved": "https://registry.npmjs.org/@reflink/reflink-linux-arm64-musl/-/reflink-linux-arm64-musl-0.1.19.tgz",
"integrity": "sha512-37iO/Dp6m5DDaC2sf3zPtx/hl9FV3Xze4xoYidrxxS9bgP3S8ALroxRK6xBG/1TtfXKTvolvp+IjrUU6ujIGmA==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@reflink/reflink-linux-x64-gnu": {
"version": "0.1.19",
"resolved": "https://registry.npmjs.org/@reflink/reflink-linux-x64-gnu/-/reflink-linux-x64-gnu-0.1.19.tgz",
"integrity": "sha512-jbI8jvuYCaA3MVUdu8vLoLAFqC+iNMpiSuLbxlAgg7x3K5bsS8nOpTRnkLF7vISJ+rVR8W+7ThXlXlUQ93ulkw==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@reflink/reflink-linux-x64-musl": {
"version": "0.1.19",
"resolved": "https://registry.npmjs.org/@reflink/reflink-linux-x64-musl/-/reflink-linux-x64-musl-0.1.19.tgz",
"integrity": "sha512-e9FBWDe+lv7QKAwtKOt6A2W/fyy/aEEfr0g6j/hWzvQcrzHCsz07BNQYlNOjTfeytrtLU7k449H1PI95jA4OjQ==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@reflink/reflink-win32-arm64-msvc": {
"version": "0.1.19",
"resolved": "https://registry.npmjs.org/@reflink/reflink-win32-arm64-msvc/-/reflink-win32-arm64-msvc-0.1.19.tgz",
"integrity": "sha512-09PxnVIQcd+UOn4WAW73WU6PXL7DwGS6wPlkMhMg2zlHHG65F3vHepOw06HFCq+N42qkaNAc8AKIabWvtk6cIQ==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@reflink/reflink-win32-x64-msvc": {
"version": "0.1.19",
"resolved": "https://registry.npmjs.org/@reflink/reflink-win32-x64-msvc/-/reflink-win32-x64-msvc-0.1.19.tgz",
"integrity": "sha512-E//yT4ni2SyhwP8JRjVGWr3cbnhWDiPLgnQ66qqaanjjnMiu3O/2tjCPQXlcGc/DEYofpDc9fvhv6tALQsMV9w==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 10"
}
}
}
}

View File

@@ -1,30 +0,0 @@
{
"name": "bootstrap-pnpm",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"dependencies": {
"pnpm": "11.0.0-rc.2"
}
},
"node_modules/pnpm": {
"version": "11.0.0-rc.2",
"resolved": "https://registry.npmjs.org/pnpm/-/pnpm-11.0.0-rc.2.tgz",
"integrity": "sha512-JkEMwm1mi63d4ToKzyx1ytALgqR3vMHi/mKd1B1reP4/stm7Ujr/951qkfBr6bkKYDJUPzC19zkxI5yCCqXwAQ==",
"license": "MIT",
"bin": {
"pn": "bin/pnpm.mjs",
"pnpm": "bin/pnpm.mjs",
"pnpx": "bin/pnpx.mjs",
"pnx": "bin/pnpx.mjs"
},
"engines": {
"node": ">=22.13"
},
"funding": {
"url": "https://opencollective.com/pnpm"
}
}
}
}

View File

@@ -1,103 +1,71 @@
import { addPath, exportVariable } from '@actions/core' import { addPath, exportVariable } from '@actions/core'
import { spawn } from 'child_process' import { spawn } from 'child_process'
import { rm, writeFile, mkdir, symlink } from 'fs/promises' import { rm, writeFile, mkdir, copyFile } from 'fs/promises'
import { readFileSync, existsSync } from 'fs' import { readFileSync } from 'fs'
import path from 'path' import path from 'path'
import { execPath } from 'process'
import util from 'util' import util from 'util'
import { Inputs } from '../inputs' import { Inputs } from '../inputs'
import { parse as parseYaml } from 'yaml' import YAML from 'yaml'
import pnpmLock from './bootstrap/pnpm-lock.json'
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 async function runSelfInstaller(inputs: Inputs): Promise<number> { export async function runSelfInstaller(inputs: Inputs): Promise<number> {
const { version, dest, packageJsonFile } = inputs const { version, dest, packageJsonFile, standalone } = inputs
// pnpm v11 requires Node >= 22.13; use standalone (exe) bootstrap which
// bundles its own Node.js when the system Node is too old
const systemNode = await getSystemNodeVersion()
const standalone = inputs.standalone || systemNode.major < 22 || (systemNode.major === 22 && systemNode.minor < 13)
// Install bootstrap pnpm via npm (integrity verified by committed lockfile)
await rm(dest, { recursive: true, force: true })
await mkdir(dest, { recursive: true })
const lockfile = standalone ? exeLock : pnpmLock
const packageJson = standalone ? BOOTSTRAP_EXE_PACKAGE_JSON : BOOTSTRAP_PNPM_PACKAGE_JSON
await writeFile(path.join(dest, 'package.json'), packageJson)
await writeFile(path.join(dest, 'package-lock.json'), JSON.stringify(lockfile))
const npmExitCode = await runCommand('npm', ['ci'], { cwd: dest })
if (npmExitCode !== 0) {
return npmExitCode
}
// On Windows with standalone mode, npm's .bin shims can't properly
// execute the extensionless @pnpm/exe native binaries. Add the
// @pnpm/exe directory directly to PATH so pnpm.exe is found natively.
const pnpmHome = standalone && process.platform === 'win32'
? path.join(dest, 'node_modules', '@pnpm', 'exe')
: path.join(dest, 'node_modules', '.bin')
// PNPM_HOME/bin is where `pnpm self-update` places the target version
// binary. It must have higher PATH precedence than pnpmHome (which
// contains the bootstrap binary) so the self-updated version is found
// first. The bootstrap pnpm is invoked via absolute path, not PATH,
// so this ordering does not affect the bootstrap step.
addPath(pnpmHome)
addPath(path.join(pnpmHome, 'bin'))
exportVariable('PNPM_HOME', pnpmHome)
// Ensure pnpm bin link exists — npm ci sometimes doesn't create it
if (process.platform !== 'win32') {
const pnpmBinLink = path.join(dest, 'node_modules', '.bin', 'pnpm')
if (!existsSync(pnpmBinLink)) {
await mkdir(path.join(dest, 'node_modules', '.bin'), { recursive: true })
const target = standalone
? path.join('..', '@pnpm', 'exe', 'pnpm')
: path.join('..', 'pnpm', 'bin', 'pnpm.mjs')
await symlink(target, pnpmBinLink)
}
}
const bootstrapPnpm = standalone
? path.join(dest, 'node_modules', '@pnpm', 'exe', process.platform === 'win32' ? 'pnpm.exe' : 'pnpm')
: path.join(dest, 'node_modules', 'pnpm', 'bin', 'pnpm.mjs')
// Determine the target version
const targetVersion = readTargetVersion({ version, packageJsonFile })
if (targetVersion) {
const cmd = standalone ? bootstrapPnpm : process.execPath
const args = standalone ? ['self-update', targetVersion] : [bootstrapPnpm, 'self-update', targetVersion]
const exitCode = await runCommand(cmd, args, { cwd: dest })
if (exitCode !== 0) {
return exitCode
}
}
return 0
}
function readTargetVersion(opts: {
readonly version?: string | undefined
readonly packageJsonFile: string
}): string | undefined {
const { version, packageJsonFile } = opts
const { GITHUB_WORKSPACE } = process.env const { GITHUB_WORKSPACE } = process.env
let packageManager: string | undefined // prepare self install
let devEngines: { packageManager?: { name?: string; version?: string } } | undefined await rm(dest, { recursive: true, force: true })
// create dest directory after removal
await mkdir(dest, { recursive: true })
const pkgJson = path.join(dest, 'package.json')
// we have ensured the dest directory exists, we can write the file directly
await writeFile(pkgJson, JSON.stringify({ private: true }))
// copy .npmrc if it exists to install from custom registry
if (GITHUB_WORKSPACE) {
try {
await copyFile(path.join(GITHUB_WORKSPACE, '.npmrc'), path.join(dest, '.npmrc'))
} catch (error) {
// Swallow error if .npmrc doesn't exist
if (!util.types.isNativeError(error) || !('code' in error) || error.code !== 'ENOENT') throw error
}
}
// prepare target pnpm
const target = await readTarget({ version, packageJsonFile, standalone })
const cp = spawn(execPath, [path.join(__dirname, 'pnpm.cjs'), 'install', target, '--no-lockfile'], {
cwd: dest,
stdio: ['pipe', 'inherit', 'inherit'],
})
const exitCode = await new Promise<number>((resolve, reject) => {
cp.on('error', reject)
cp.on('close', resolve)
})
if (exitCode === 0) {
const pnpmHome = path.join(dest, 'node_modules/.bin')
addPath(pnpmHome)
exportVariable('PNPM_HOME', pnpmHome)
}
return exitCode
}
async function readTarget(opts: {
readonly version?: string | undefined
readonly packageJsonFile: string
readonly standalone: boolean
}) {
const { version, packageJsonFile, standalone } = opts
const { GITHUB_WORKSPACE } = process.env
let packageManager
if (GITHUB_WORKSPACE) { if (GITHUB_WORKSPACE) {
try { try {
const content = readFileSync(path.join(GITHUB_WORKSPACE, packageJsonFile), 'utf8'); const content = readFileSync(path.join(GITHUB_WORKSPACE, packageJsonFile), 'utf8');
const manifest = packageJsonFile.endsWith(".yaml") ({ packageManager } = packageJsonFile.endsWith(".yaml")
? parseYaml(content, { merge: true }) ? YAML.parse(content, { merge: true })
: JSON.parse(content) : JSON.parse(content)
packageManager = manifest.packageManager )
devEngines = manifest.devEngines
} catch (error: unknown) { } catch (error: unknown) {
// Swallow error if package.json doesn't exist in root // Swallow error if package.json doesn't exist in root
if (!util.types.isNativeError(error) || !('code' in error) || error.code !== 'ENOENT') throw error if (!util.types.isNativeError(error) || !('code' in error) || error.code !== 'ENOENT') throw error
@@ -116,16 +84,7 @@ function readTargetVersion(opts: {
Remove one of these versions to avoid version mismatch errors like ERR_PNPM_BAD_PM_VERSION`) Remove one of these versions to avoid version mismatch errors like ERR_PNPM_BAD_PM_VERSION`)
} }
return version return `${ standalone ? '@pnpm/exe' : 'pnpm' }@${version}`
}
// pnpm will automatically download and switch to the right version
if (typeof packageManager === 'string' && packageManager.startsWith('pnpm@')) {
return undefined
}
if (devEngines?.packageManager?.name === 'pnpm' && devEngines.packageManager.version) {
return undefined
} }
if (!GITHUB_WORKSPACE) { if (!GITHUB_WORKSPACE) {
@@ -135,36 +94,22 @@ please run the actions/checkout before pnpm/action-setup.
Otherwise, please specify the pnpm version in the action configuration.`) Otherwise, please specify the pnpm version in the action configuration.`)
} }
throw new Error(`No pnpm version is specified. if (typeof packageManager !== 'string') {
throw new Error(`No pnpm version is specified.
Please specify it by one of the following ways: Please specify it by one of the following ways:
- in the GitHub Action config with the key "version" - in the GitHub Action config with the key "version"
- in the package.json with the key "packageManager" - in the package.json with the key "packageManager"`)
- in the package.json with the key "devEngines.packageManager"`) }
}
function getSystemNodeVersion(): Promise<{ major: number; minor: number }> { if (!packageManager.startsWith('pnpm@')) {
return new Promise((resolve) => { throw new Error('Invalid packageManager field in package.json')
const cp = spawn('node', ['--version'], { stdio: ['pipe', 'pipe', 'pipe'], shell: process.platform === 'win32' }) }
let output = ''
cp.stdout.on('data', (data: Buffer) => { output += data.toString() })
cp.on('close', () => {
const match = output.match(/^v(\d+)\.(\d+)/)
resolve(match ? { major: parseInt(match[1], 10), minor: parseInt(match[2], 10) } : { major: 0, minor: 0 })
})
cp.on('error', () => resolve({ major: 0, minor: 0 }))
})
}
function runCommand(cmd: string, args: string[], opts: { cwd: string }): Promise<number> { if (standalone) {
return new Promise<number>((resolve, reject) => { return packageManager.replace('pnpm@', '@pnpm/exe@')
const cp = spawn(cmd, args, { }
cwd: opts.cwd,
stdio: ['pipe', 'inherit', 'inherit'], return packageManager
shell: process.platform === 'win32',
})
cp.on('error', reject)
cp.on('close', resolve)
})
} }
export default runSelfInstaller export default runSelfInstaller

View File

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

View File

@@ -5,7 +5,12 @@ import { patchPnpmEnv } from '../utils'
export function pruneStore(inputs: Inputs) { export function pruneStore(inputs: Inputs) {
if (inputs.runInstall.length === 0) { if (inputs.runInstall.length === 0) {
console.log('Pruning is unnecessary.') console.log('No install commands were run, skipping pnpm store prune, remember to run it after pnpm install if caching the store.')
return
}
if (!inputs.storePrune) {
console.log('Store pruning is disabled, skipping pnpm store prune.')
return return
} }

View File

@@ -6,5 +6,5 @@ export const getBinDest = (inputs: Inputs): string => path.join(inputs.dest, 'no
export const patchPnpmEnv = (inputs: Inputs): NodeJS.ProcessEnv => ({ export const patchPnpmEnv = (inputs: Inputs): NodeJS.ProcessEnv => ({
...process.env, ...process.env,
PATH: path.join(getBinDest(inputs), 'bin') + path.delimiter + getBinDest(inputs) + path.delimiter + process.env.PATH, PATH: getBinDest(inputs) + path.delimiter + process.env.PATH,
}) })

View File

@@ -1,19 +1,26 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "ES2022", "target": "ES2022",
"module": "ESNext", "module": "Node16",
"moduleResolution": "bundler",
"resolveJsonModule": true, "resolveJsonModule": true,
"lib": [ "lib": [
"ES2023" "ES2023"
], ],
"noEmit": true, "outDir": "./dist/tsc",
"preserveConstEnums": true,
"incremental": false,
"declaration": true,
"sourceMap": true,
"importHelpers": false,
"strict": true, "strict": true,
"pretty": true, "pretty": true,
"noUnusedLocals": true, "noUnusedLocals": true,
"noUnusedParameters": true, "noUnusedParameters": true,
"noImplicitReturns": true, "noImplicitReturns": true,
"noFallthroughCasesInSwitch": true, "noFallthroughCasesInSwitch": true,
"esModuleInterop": true "esModuleInterop": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true
} }
} }