Summary
Allow a job to restore the pnpm store cache without saving it, e.g. save: false (or cache: 'restore' alongside the existing boolean). There is currently no way to opt out of the post-step save while keeping the restore.
Why
The action assumes a workflow shape where saving is cheap because few jobs do it. That breaks down on a fan-out — a deploy matrix, or a reusable workflow called once per target — where many jobs share one lockfile and one runtime, and therefore one cache key.
In that shape only the first job to finish can usefully save. Every other job:
- rebuilds and compresses the whole store in its post step;
- loses the reservation and logs
Failed to save: Unable to reserve cache with key …, another job may be creating this cache;
- discards the upload.
On a fan-out of around a hundred jobs, with a store of several hundred MB, that is roughly 18s of job time per job spent producing something guaranteed to be thrown away, plus a warning per job drowning out real ones. The work is pure loss: the content is identical to what the winner already published.
What these workflows want is one designated job that warms the store and publishes it, with everything downstream restoring read-only.
Why the existing inputs do not cover it
cache: false also disables the restore, so the fan-out installs cold — much worse.
install: false does not affect caching.
- There is no equivalent of
actions/cache/restore's split, or of lookup-only.
Working around it means abandoning the action's caching entirely and hand-rolling actions/cache/restore plus a single actions/cache/save, which gives up the store-path detection and key construction this action exists to provide.
Sketch
# one upstream job warms and publishes the store
- uses: pnpm/setup@v2
with:
cache: true
# the fan-out restores it and never saves
- uses: pnpm/setup@v2
with:
cache: true
save: false
save: false would skip registering the post step (or make it a no-op), leaving restore, the lockfile-verification cache and cache-hit untouched.
Relationship to #43
#43 moves saves onto a run-scoped key. That does not help this case — GITHUB_RUN_ID and GITHUB_RUN_ATTEMPT are per run, so every job in a matrix or reusable workflow computes the same save key and races it exactly as now, while entries accumulate per run. Commented there with detail. The two are orthogonal: this request removes the redundant saves by construction, and would compose with whatever keying #43 settles on.
Summary
Allow a job to restore the pnpm store cache without saving it, e.g.
save: false(orcache: 'restore'alongside the existing boolean). There is currently no way to opt out of the post-step save while keeping the restore.Why
The action assumes a workflow shape where saving is cheap because few jobs do it. That breaks down on a fan-out — a deploy matrix, or a reusable workflow called once per target — where many jobs share one lockfile and one runtime, and therefore one cache key.
In that shape only the first job to finish can usefully save. Every other job:
Failed to save: Unable to reserve cache with key …, another job may be creating this cache;On a fan-out of around a hundred jobs, with a store of several hundred MB, that is roughly 18s of job time per job spent producing something guaranteed to be thrown away, plus a warning per job drowning out real ones. The work is pure loss: the content is identical to what the winner already published.
What these workflows want is one designated job that warms the store and publishes it, with everything downstream restoring read-only.
Why the existing inputs do not cover it
cache: falsealso disables the restore, so the fan-out installs cold — much worse.install: falsedoes not affect caching.actions/cache/restore's split, or oflookup-only.Working around it means abandoning the action's caching entirely and hand-rolling
actions/cache/restoreplus a singleactions/cache/save, which gives up the store-path detection and key construction this action exists to provide.Sketch
save: falsewould skip registering the post step (or make it a no-op), leaving restore, the lockfile-verification cache andcache-hituntouched.Relationship to #43
#43 moves saves onto a run-scoped key. That does not help this case —
GITHUB_RUN_IDandGITHUB_RUN_ATTEMPTare per run, so every job in a matrix or reusable workflow computes the same save key and races it exactly as now, while entries accumulate per run. Commented there with detail. The two are orthogonal: this request removes the redundant saves by construction, and would compose with whatever keying #43 settles on.