* feat!: replace bundled pnpm binary with npm + lockfile bootstrap Remove the 9MB bundled pnpm.cjs/worker.js and instead use npm ci with committed package-lock.json files (~5KB) to install a bootstrap pnpm, which then installs the target version with integrity verification via the project's pnpm-lock.yaml. Also switch from ncc to esbuild and modernize to ESM. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: bundle as CJS to support @actions/* packages The @actions/* packages use CJS require() for Node.js builtins, which fails with "Dynamic require of 'os' is not supported" when bundled as ESM. Switch esbuild output to CJS format. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: remove "type": "module" from package.json Node.js treats dist/index.js as ESM due to "type": "module", but the bundle uses CJS require() calls. Remove the field so Node.js defaults to CJS for .js files. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: remove packageManager field and fix Windows npm spawn - Remove packageManager from package.json to avoid version conflict when the action tests against itself (uses: ./) - Use shell: true on Windows so spawn can find npm.cmd Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: always use pnpm (not @pnpm/exe) for bootstrap and update lockfile The bootstrap only needs regular pnpm to install the target package. @pnpm/exe requires install scripts which we skip with --ignore-scripts. Also regenerate pnpm-lock.yaml to match current package.json. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: use --no-lockfile for target install --lockfile-dir pointing to GITHUB_WORKSPACE causes the bootstrap pnpm to use the project's pnpm-lock.yaml (which tracks project deps, not pnpm itself), corrupting the install. Revert to --no-lockfile for now. Lockfile-based integrity verification can be added when pnpm v11 has proper support for verifying the pnpm package itself. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: run bootstrap pnpm via node instead of bin shim Use `node .../pnpm/bin/pnpm.cjs` to run the bootstrap pnpm, matching the approach used by the old bundled pnpm.cjs. This avoids issues with the .bin symlink on different platforms. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: use pnpm self-update instead of installing target separately - Bootstrap pnpm via npm ci (verified by lockfile) - Use `pnpm self-update <version>` for explicit version - Let pnpm handle packageManager field automatically - Remove standalone/exe-specific install logic (pnpm handles this) - Update tests to not run pnpm install against the action repo itself Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: support standalone mode with @pnpm/exe bootstrap - When standalone=true, bootstrap with @pnpm/exe via npm ci - When standalone=false, bootstrap with pnpm via npm ci - Both use pnpm self-update to reach the target version - Remove --ignore-scripts from npm ci so @pnpm/exe install scripts run - Add standalone test back to CI Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * debug: add logging to diagnose pnpm not found on PATH Log .bin directory contents after npm ci to understand why pnpm binary is not found in subsequent CI steps. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: ensure pnpm bin link exists after npm ci npm ci sometimes doesn't create the .bin/pnpm symlink for @pnpm/exe (observed on Linux CI). Manually create the symlink if it's missing after npm ci completes. This fixes the case where standalone=true with no explicit version (relying on packageManager field) — pnpm self-update wouldn't run, leaving .bin empty and pnpm not found on PATH. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: add PNPM_HOME/bin to PATH for pnpm v11 pnpm v11 moved global binaries from PNPM_HOME to PNPM_HOME/bin. Add the new bin subdirectory to PATH so that pnpm's global bin directory check passes. This is backwards compatible — the extra PATH entry is harmless for older pnpm versions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: add packages field to pnpm-workspace.yaml pnpm v9 requires the packages field in pnpm-workspace.yaml. Without it, `pnpm --version` fails with "packages field missing or empty". Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix pnpm-workspace.yaml --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
⚠️ Upgrade from v2!
The v2 version of this action has stopped working with newer Node.js versions. Please, upgrade to the latest version to fix any issues.
Setup pnpm
Install pnpm package manager.
Inputs
version
Version of pnpm to install.
Optional when there is a packageManager field in the package.json.
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
Optional Where to store pnpm files.
run_install
Optional (default: null) If specified, run pnpm install.
If run_install is either null or false, pnpm will not install any npm package.
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.
run_install.recursive
Optional (type: boolean, default: false) Whether to use pnpm recursive install.
run_install.cwd
Optional (type: string) Working directory when run pnpm [recursive] install.
run_install.args
Optional (type: string[]) Additional arguments after pnpm [recursive] install, e.g. [--ignore-scripts, --strict-peer-dependencies].
cache
Optional (type: boolean, default: false) Whether to cache the pnpm store directory.
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
Optional (type: string, default: package.json) File path to the package.json/package.yaml to read "packageManager" configuration.
standalone
Optional (type: boolean, default: false) When set to true, @pnpm/exe, which is a Node.js bundled package, will be installed, enabling using pnpm without Node.js.
This is useful when you want to use a incompatible pair of Node.js and pnpm.
Outputs
dest
Expanded path of inputs#dest.
bin_dest
Location of pnpm and pnpx command.
Usage example
Install only pnpm without packageManager
This works when the repo either doesn't have a package.json or has a package.json but it doesn't specify packageManager.
on:
- push
- pull_request
jobs:
install:
runs-on: ubuntu-latest
steps:
- uses: pnpm/action-setup@v4
with:
version: 10
Install only pnpm with packageManager
Omit version input to use the version in the packageManager field in the package.json.
on:
- push
- pull_request
jobs:
install:
runs-on: ubuntu-latest
steps:
- uses: pnpm/action-setup@v4
Install pnpm and a few npm packages
on:
- push
- pull_request
jobs:
install:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 10
run_install: |
- recursive: true
args: [--strict-peer-dependencies]
- args: [--global, gulp, prettier, typescript]
Use cache to reduce installation time
on:
- push
- pull_request
jobs:
cache-and-install:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
name: Install pnpm
with:
version: 10
cache: true
- name: Install dependencies
run: pnpm install
Note: You don't need to run pnpm store prune at the end; post-action has already taken care of that.
Notes
This action does not setup Node.js for you, use actions/setup-node yourself.