CalcSnippets
DevOps 2 min read

A pnpm Lockfile and CI Cache Workflow That Fails Clearly

Combine a pinned package manager, frozen installs, and a deliberate cache boundary so dependency drift fails at the right line in CI.

Make the lockfile a contract

The useful CI install command for a lockfile-managed pnpm project is usually:

pnpm install --frozen-lockfile

This should fail when package.json and pnpm-lock.yaml disagree. That failure is valuable. A pipeline that silently rewrites the lockfile can report green while installing a dependency graph that no developer reviewed.

Pin pnpm in package.json with packageManager, then activate that version in CI. Also print the Node and pnpm versions before installation. If the install fails, you want to know whether the failure is a dependency graph problem, a package-manager mismatch, or a cache problem.

Put cache boundaries in the right order

For GitHub Actions, set up Node with pnpm caching, enable Corepack, activate the version, and only then install:

- uses: actions/setup-node@v4
  with:
    node-version: 22
    cache: pnpm
- run: corepack enable
- run: corepack prepare [email protected] --activate
- run: pnpm install --frozen-lockfile
- run: pnpm test

The cache can speed up downloads, but it must never be the source of truth for the dependency graph. A cache hit does not prove that the lockfile is valid. Keep the install command strict even when the cache is warm.

Use pnpm fetch intentionally

In a Docker build, copy the manifests before source files so dependency layers remain reusable:

COPY package.json pnpm-lock.yaml ./
RUN corepack enable && corepack prepare [email protected] --activate
RUN pnpm fetch --frozen-lockfile
COPY . .
RUN pnpm install --offline --frozen-lockfile

fetch prepares the store; it does not create the final project installation by itself. The later offline install is the step that links dependencies into the workspace. If that step fails, inspect the lockfile and the package manager version before disabling offline mode.

For a monorepo, make sure the lockfile and workspace manifest are copied together, and run the same filter or recursive command locally that CI runs. Avoid caching node_modules unless you have a strong reason; the store is a cleaner cache boundary across jobs and platforms.

The pnpm CI Command Builder produces a starting workflow for GitHub Actions, Docker, or local reproduction. Review action versions and project scripts before committing its output.

Keep reading

Related guides