持续集成
pnpm 可以很容易地用于各种持续集成系统。
安装 pnpm#
在 GitHub Actions 之外(它有自己的 action),请使用独立脚本安装 pnpm:
curl -fsSL https://get.pnpm.io/install.sh | env PNPM_VERSION=latest-11 sh -
在 CI 中,有两点让这变得方便:
- **它不需要 Node.js。**pnpm 是自包含的可执行文件,之后还可以用
pnpm runtime set node lts -g为你安装运行时,因此一个任务 一开始就无需使用 Node.js 镜像。 - **它自行选择版本。**如果你的
package.json中带有packageManager或devEngines.packageManager字段,pnpm 会在首次使用时切换到该版本,因此流水线无需在两处固定版本。
该脚本会安装到 PNPM_HOME,并追加到 shell 配置文件中,而 CI 的任务从不会重新加载该文件。 Declare PNPM_HOME and put $PNPM_HOME/bin on PATH
yourself, using whatever mechanism the platform provides. The examples below
show it for each one.
注意
此页面的早期版本使用了 Corepack。 Corepack installs a JavaScript shim
in place of pnpm, so every pnpm call starts Node.js to run the shim before pnpm
itself starts. That cost is paid on each invocation, and CI jobs make many of them.
安装 pnpm 本身完全避免了这个问题。
注意
在所有提供的配置文件中,存储都被缓存。但是,这不是必需的,并且不能保证缓存的存储会使安装速度更快。因此,不必在作业中缓存 pnpm 存储。
同时缓存元数据缓存
自 v11.22.0 起,pnpm cache path 会打印 pnpm 用于元数据缓存的目录,因此 job 可以缓存它,而无需复制 pnpm 自身的路径解析逻辑。 That directory also holds the lockfile verification log, which
lets a job skip re-checking an unchanged lockfile against the configured
supply-chain policies, the dominant cost of an
install in CI once the store is warm.
important
仅将 pnpm 的 store 和 cache 目录缓存到受信任作业具有写入权限的位置。切勿让不受信任的 CI 任务向存储或元数据缓存写入数据,以免受信任的任务随后将其恢复。这些目录是受信任的缓存;有关详细信息,请参阅 storeDir 和 cacheDir 设置。
CI 中的锁文件行为
当 pnpm 检测到它在 CI 中运行时,它会自动切换到 frozen-lockfile 模式。 Since v11, pnpm also fails on incompatible lockfiles in CI. If the lockfile was written by a newer pnpm major version, the install will error out instead of silently rewriting it. 将你的 CI pnpm 版本升级到与生成 lockfile 时使用的版本一致。
AppVeyor#
在 AppVeyor 上,在你的 appveyor.yml 中添加这些来使用 pnpm 安装你的依赖项:
environment:
PNPM_HOME: C:\pnpm
install:
- ps: $env:PATH = "$env:PNPM_HOME;$env:PNPM_HOME\bin;$env:PATH"
- ps: $env:PNPM_VERSION = "latest-11"; Invoke-WebRequest https://get.pnpm.io/install.ps1 -UseBasicParsing | Invoke-Expression
- ps: pnpm install
pnpm 自带运行时,因此不再需要 Install-Product node。如果你的构建脚本直接调用 node,请添加
pnpm runtime set node lts -g。
Azure Pipelines#
在 Azure pipeline 中,你可以将以下内容添加到 Azure-Pipelines.yml 中,使用 pnpm 安装和缓存依赖项`:
variables:
pnpm_config_cache: $(Pipeline.Workspace)/.pnpm-store
PNPM_HOME: $(Pipeline.Workspace)/.pnpm
steps:
- task: Cache@2
inputs:
key: 'pnpm | "$(Agent.OS)" | pnpm-lock.yaml'
path: $(pnpm_config_cache)
displayName: Cache pnpm
- script: |
curl -fsSL https://get.pnpm.io/install.sh | env PNPM_VERSION=latest-11 sh -
echo "##vso[task.prependpath]$(PNPM_HOME)/bin"
"$(PNPM_HOME)/bin/pnpm" config set store-dir $(pnpm_config_cache)
displayName: "Setup pnpm"
- script: |
pnpm install
pnpm run build
displayName: "pnpm install and build"
task.prependpath 会为后续步骤把 pnpm 加入 PATH;在安装它的那个步骤内部,请用完整路径调用。
Bitbucket 流水线#
你可以使用 pnpm 来安装和缓存你的依赖项:
definitions:
caches:
pnpm: $BITBUCKET_CLONE_DIR/.pnpm-store
pipelines:
pull-requests:
"**":
- step:
name: Build and test
image: debian:stable-slim
script:
- apt-get update && apt-get install -y --no-install-recommends ca-certificates curl libatomic1 libstdc++6
- export PNPM_HOME="$HOME/.local/share/pnpm"
- export PATH="$PNPM_HOME/bin:$PATH"
- curl -fsSL https://get.pnpm.io/install.sh | env PNPM_VERSION=latest-11 sh -
- pnpm config set store-dir "$BITBUCKET_CLONE_DIR/.pnpm-store"
- pnpm runtime set node lts -g
- pnpm install
- pnpm run build # Replace with your build/test…etc. commands
caches:
- pnpm
一个步骤中的所有行都在同一个 shell 中运行,因此 export 会传递给其后的行,且 store-dir 指向缓存所保存的目录。
这个示例从一个空白镜像开始,并且让 pnpm 安装 Node.js。 A minimal
image needs the libraries the pnpm 11 executable links against (libatomic1
and libstdc++6), which images like node:24 already carry; see Linux runtime
requirements.
CircleCI#
在 CircleCI 中,你可以将以下内容添加到 .circleci/config.yml 中,使用 pnpm 安装和缓存依赖项`:
version: 2.1
jobs:
build: # this can be any name you choose
docker:
- image: node:24
resource_class: large
parallelism: 10
environment:
PNPM_HOME: /root/.local/share/pnpm
steps:
- checkout
- restore_cache:
name: Restore pnpm Package Cache
keys:
- pnpm-packages-{{ checksum "pnpm-lock.yaml" }}
- run:
name: Install pnpm package manager
command: |
curl -fsSL https://get.pnpm.io/install.sh | env PNPM_VERSION=latest-11 sh -
echo 'export PATH="$PNPM_HOME/bin:$PATH"' >> "$BASH_ENV"
"$PNPM_HOME/bin/pnpm" config set store-dir .pnpm-store
- run:
name: Install Dependencies
command: |
pnpm install
- save_cache:
name: Save pnpm Package Cache
key: pnpm-packages-{{ checksum "pnpm-lock.yaml" }}
paths:
- .pnpm-store
CircleCI 会在每个步骤之前加载 $BASH_ENV,pnpm 正是借此传递给后续步骤。
GitHub Actions#
在 GitHub Actions 上,你可以像这样使用 pnpm 安装和缓存你的依赖项(属于 ·.github/workflows/NAME.yml·):
name: pnpm Example Workflow
on:
push:
jobs:
build:
runs-on: ubuntu-24.04
strategy:
matrix:
node-version: [24]
steps:
- uses: actions/checkout@v6
- name: Install pnpm and Node.js
uses: pnpm/setup@fa36a5ef7dcdefc3a7cb25655c122e00cf6e636e # v3.1.2
with:
runtime: node@${{ matrix.node-version }}
cache: true
pnpm/setup 会先安装 pnpm,再用它来安装所需的运行时,因此无需单独的 actions/setup-node 步骤。它还会替你运行 pnpm install,而 cache: true 会在多次运行之间缓存 pnpm 存储。如果你希望自己执行安装,请设置 install: false。
pnpm 版本取自 package.json 的 packageManager 或 devEngines.packageManager 字段,因此当你更改版本时,工作流无需更新。如果你的 package.json 两者都未声明,请添加 version 输入。
GitLab CI#
在 Gitlab 上,你可以像这样使用 pnpm 来安装和缓存你的依赖项(在 .gitlab-ci.yml 中):
stages:
- build
build:
stage: build
image: node:24.14.1
variables:
PNPM_HOME: "$CI_PROJECT_DIR/.pnpm"
before_script:
- export PATH="$PNPM_HOME/bin:$PATH"
- curl -fsSL https://get.pnpm.io/install.sh | env PNPM_VERSION=latest-11 sh -
- pnpm config set store-dir .pnpm-store
script:
- pnpm install # install dependencies
cache:
key:
files:
- pnpm-lock.yaml
paths:
- .pnpm-store
Jenkins#
你可以使用 pnpm 来安装和缓存你的依赖项:
pipeline {
agent {
docker {
image 'node:lts-bookworm-slim'
args '-p 3000:3000'
}
}
environment {
PNPM_HOME = "${WORKSPACE}/.pnpm"
PATH = "${PNPM_HOME}/bin:${PATH}"
}
stages {
stage('Build') {
steps {
sh 'curl -fsSL https://get.pnpm.io/install.sh | env PNPM_VERSION=latest-11 sh -'
sh 'pnpm install'
}
}
}
}
每个 sh 步骤都在各自的 shell 中运行,因此 PATH 是在流水线的
environment 块中设置的,而不是在步骤内部导出。
Semaphore#
在 [Semapore] 上,请将此内容添加到 .semaphore/semaphore.yml 文件中以使用 pnpm 来安装和缓存你的依赖:
version: v1.0
name: Semaphore CI pnpm example
agent:
machine:
type: e1-standard-2
os_image: ubuntu2404
blocks:
- name: Install dependencies
task:
env_vars:
- name: PNPM_HOME
value: /home/semaphore/.local/share/pnpm
jobs:
- name: pnpm install
commands:
- export PATH="$PNPM_HOME/bin:$PATH"
- curl -fsSL https://get.pnpm.io/install.sh | env PNPM_VERSION=latest-11 sh -
- checkout
- cache restore node-$(checksum pnpm-lock.yaml)
- pnpm install
- cache store node-$(checksum pnpm-lock.yaml) $(pnpm store path)
Travis#
在 Travis CI 上,请将此添加到你的 .travis.yml 文件中以使用 pnpm 来安装你的依赖项:
cache:
npm: false
directories:
- "~/.pnpm-store"
env:
global:
- PNPM_HOME="$HOME/.local/share/pnpm"
- PATH="$PNPM_HOME/bin:$PATH"
before_install:
- curl -fsSL https://get.pnpm.io/install.sh | env PNPM_VERSION=latest-11 sh -
- pnpm config set store-dir ~/.pnpm-store
install:
- pnpm install