연속 통합
pnpm은 다양한 ci 시스템들과 함께 사용하기 쉽습니다.
pnpm 설치하기#
자체 액션이 있는 GitHub Actions 외의 환경에서는 독립 실행형 스크립트로 pnpm을 설치하세요:
curl -fsSL https://get.pnpm.io/install.sh | sh -
CI에서 이 방식이 편리한 이유는 두 가지입니다:
- Node.js가 필요하지 않습니다. pnpm은 독립 실행형 실행 파일이며, 이후
pnpm runtime set node lts -g로 런타임을 설치할 수 있으므로 작업을 시작할 때 Node.js 이미지가 필요하지 않습니다. - 자체적으로 버전을 선택합니다.
package.json에packageManager또는devEngines.packageManager필드가 있으면 pnpm은 처음 사용할 때 해당 버전으로 전환하므로, 파이프라인에서 두 곳에 버전을 고정할 필요가 없습니다.
이 스크립트는 PNPM_HOME에 설치하고 셸 프로필에 내용을 추가하지만, CI 작업은 셸 프로필을 다시 불러오지 않습니다. 플랫폼이 제공하는 방식을 사용하여 PNPM_HOME을 선언하고 $PNPM_HOME/bin을 PATH에 직접 추가하세요 — 아래 예시에서 각 플랫폼별 방법을 보여줍니다.
참고
이 페이지의 이전 버전에서는 Corepack을 사용했습니다. Corepack은 pnpm 대신 JavaScript shim을 설치하므로, 모든 pnpm 호출이 pnpm 자체가 시작되기 전에 shim을 실행하기 위해 Node.js를 시작합니다 — 이는 호출할 때마다 발생하는 비용이며, CI 작업은 pnpm을 여러 번 호출합니다.
pnpm 자체를 설치하면 이 비용을 완전히 피할 수 있습니다.
참고
제공된 모든 설정 파일에서는 스토어를 캐시합니다. 하지만 이는 필수가 아니며, 스토어를 캐시한다고 해서 설치가 더 빨라진다는 보장은 없습니다. 따라서 작업에서 pnpm 스토어를 캐시하지 않아도 괜찮습니다.
메타데이터 캐시도 캐시하세요
버전 v11.22.0부터 pnpm cache path가 pnpm이 메타데이터 캐시에 사용하는 디렉터리를 출력하므로, 작업에서 pnpm 자체의 경로 해석을 그대로 따라 하지 않고도 이를 캐시할 수 있습니다. 해당 디렉터리에는 lockfile 검증 로그도 저장되어 있어, 작업에서 변경되지 않은 lockfile을 구성된 공급망 보안 정책에 대해 다시 검사하는 과정을 건너뛸 수 있습니다 — 이는 스토어가 준비된 이후 CI 설치에서 가장 큰 비용을 차지합니다.
Important
pnpm의 스토어와 캐시 디렉터리는 신뢰할 수 있는 작업만 쓸 수 있는 위치에만 캐시하세요. 신뢰할 수 있는 작업이 나중에 복원하는 스토어나 메타데이터 캐시에 신뢰할 수 없는 CI 작업이 쓰지 못하도록 하세요. 이 디렉터리들은 신뢰할 수 있는 캐시입니다. 자세한 내용은 storeDir 및 cacheDir 설정을 참조하세요.
CI에서의 lockfile 동작
pnpm은 CI에서 실행 중임을 감지하면 자동으로 frozen-lockfile 모드로 전환합니다. v11부터 pnpm은 CI에서 호환되지 않는 lockfile이 있으면 실패합니다 — lockfile이 더 새로운 pnpm 메이저 버전으로 작성된 경우, 조용히 다시 작성하지 않고 설치 오류가 발생합니다. lockfile을 생성할 때 사용한 버전과 일치하도록 CI의 pnpm 버전을 업그레이드하세요.
AppVeyor#
AppVeyor에서는 appveyor.yml에 다음을 추가하여 pnpm으로 종속성을 설치할 수 있습니다:
environment:
PNPM_HOME: C:\pnpm
install:
- ps: $env:PATH = "$env:PNPM_HOME;$env:PNPM_HOME\bin;$env:PATH"
- ps: 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 Pipelines에서는 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 | 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에 추가합니다. pnpm을 설치하는 단계 내에서는 전체 경로로 호출하세요.
Bitbucket Pipelines#
pnpm을 통해 dependencies를 설치하고 캐시할 수 있습니다.
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 | 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
한 단계의 모든 줄은 하나의 셸에서 실행되므로 export는 이후 줄에도 적용되며, store-dir은 캐시가 저장하는 디렉터리를 가리키도록 설정됩니다.
이 예시는 기본 이미지에서 시작하여 pnpm이 Node.js를 설치하도록 합니다. 최소 이미지에는 pnpm 11 실행 파일이 링크하는 라이브러리인 libatomic1과 libstdc++6이 필요하며, node:24와 같은 이미지에는 이미 포함되어 있습니다. Linux 런타임 요구 사항을 참조하세요. pnpm 12는 정적으로 링크되어 있어 둘 다 필요하지 않습니다. 기존 node 이미지를 변경하지 않으려면 그대로 유지하고 apt-get 및 pnpm runtime set 줄을 제거하세요.
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 | 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@c9883cc79df532ad1a7b81bf9ab944ceb090d65c # v2.0.0
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 | sh -
- pnpm config set store-dir .pnpm-store
script:
- pnpm install # install dependencies
cache:
key:
files:
- pnpm-lock.yaml
paths:
- .pnpm-store
Jenkins#
pnpm을 통해 dependencies를 설치하고 캐시할 수 있습니다.
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 | sh -'
sh 'pnpm install'
}
}
}
}
각 sh 단계는 자체 셸에서 실행되므로, PATH는 단계 내에서 export하는 대신 파이프라인의 environment 블록에서 설정합니다.
Semaphore#
Semaphore에서는 .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 | 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 | sh -
- pnpm config set store-dir ~/.pnpm-store
install:
- pnpm install