Commit Graph
19 Commits
Author SHA1 Message Date
Zoltan Kochan 987541b4df feat: check the verification log before caching it
Moving the upload to just after the install left one window open: pnpm runs a
package's lifecycle scripts during the install, so an allow-listed dependency
can still append a record claiming some other lockfile passed verification, and
the upload would publish it. Writing pnpm's own record after those scripts
would not help — the log is appended to, so the forged record survives whatever
pnpm writes next to it.

What does distinguish the two is shape: an install appends its own verdict and
leaves earlier records untouched. So the log is uploaded only when every record
that predated the install is still there, and no more records were added than
there were installs. Both failure modes cost a re-verification in the next job
and nothing else, which is also the price of pnpm compacting the log past a
thousand records — rare enough in CI, where a job restores at most one record.
2026-08-13 17:13:55 +02:00
Zoltan Kochan e6cb65ab2f fix: upload the verification log right after the install writes it
Saving in the post step left the whole job between the install and the upload.
Anything running in that window — the job's tests, its build, a dependency's
own install scripts — can rewrite the log on disk, and the job's own cache
write would then publish a record claiming some other lockfile passed
verification, for every later job to restore and trust. No cache credentials
needed: the attacker rides the write the job performs anyway.

The log is complete the moment the install finishes, so it is uploaded there.
The post step still covers a job that installs in a step of its own, where
that is the first point the log is known to be final; the save is idempotent
across the two, and the process-local flags exist because main and post do not
share state within a run.
2026-08-13 17:03:37 +02:00
Zoltan Kochan 544072d0b9 docs: tighten the verification cache comments
The module header explained the whole feature where naming the file's purpose
is enough, and the ordering comment described `pnpm store prune` deleting the
log without saying which versions do — pnpm/pnpm#13893 stops deleting it.
2026-08-13 16:47:45 +02:00
Zoltan Kochan c0a6b0ff36 perf: cache pnpm's lockfile verification results
pnpm v11 and newer verify every lockfile entry against the configured
supply-chain policies (`minimumReleaseAge`, `trustPolicy`, ...) and memoize
the verdict in `<cacheDir>/lockfile-verified.jsonl`. The action cached only
the store, so every job started with that verdict missing and re-checked the
whole lockfile against the registry — on typescript-eslint's repository,
16.6s of a 17.6s install on Linux and 40.1s of 42.4s on Windows.

The verdict depends on the lockfile content and the policies, never on the
runner, so it is cached under its own key alongside the store cache and
restored without prefix fallback: an entry recorded for a different lockfile
could never be reused. Saving happens before `pnpm store prune`, which drops
the log along with the store's other derived state.

Anything that goes wrong here only costs the next job the re-verification, so
failures are reported as warnings instead of failing the build. Older pnpm
versions never write the log, and the post step then finds nothing to save.
2026-08-13 13:59:37 +02:00
Andrew HainesandGitHub 7a5507b117 fix: restore inputs from state in post (#255) 2026-05-11 12:44:49 +02:00
Zoltan KochanandGitHub 91ab88e261 fix: bin_dest output points to self-updated pnpm, not bootstrap (#249)
* fix: bin_dest output points to self-updated pnpm, not bootstrap (#247)

`pnpm self-update <version>` writes the target binary to
`${PNPM_HOME}/bin/`, leaving the bootstrap symlink at `${PNPM_HOME}/pnpm`
untouched. The `bin_dest` output was set to `${PNPM_HOME}`, so consumers
invoking `${{ steps.pnpm.outputs.bin_dest }}/pnpm` got the bootstrap
version (currently 11.0.4) instead of the version they requested.

PATH lookup hid the bug: `${PNPM_HOME}/bin` was prepended ahead of
`${PNPM_HOME}`, so `pnpm` resolved from PATH was the right one. Existing
version-respect tests only checked `pnpm --version`, not `bin_dest`.

Resolve `binDest` inside `runSelfInstaller` (target lives in
`${PNPM_HOME}/bin` after self-update, otherwise stays at `${PNPM_HOME}`)
and plumb it through to `setOutputs`. Add a regression test that invokes
`${bin_dest}/pnpm --version` directly across Linux/macOS/Windows.

* test(ci): pass bin_dest via env to survive Windows backslashes

Direct GitHub-expression interpolation of `${{ steps.pnpm.outputs.bin_dest }}`
into the bash script let bash eat the backslashes in the Windows path
(`C:Usersrunneradminsetup-pnpmnode_modules.binbin/pnpm`), failing with
"No such file or directory". Forward the value via env so the path
reaches bash unmangled.

* build: rebuild dist with clean lockfile-matched deps
2026-05-07 12:58:58 +02:00
e94b270858 feat: store caching (#188)
* add pnpm store caching

* style: format

* no semicolons
* no star imports
* import order

* style: no star imports

---------

Co-authored-by: khai96_ <hvksmr1996@gmail.com>
2025-12-07 22:16:49 +01:00
khai96_ 11ba3424e0 fmt 2022-02-23 10:07:15 +07:00
khai96_ c8fc1974e1 Run pnpm store prune post action 2020-05-09 21:15:50 +07:00
khai96_ 291e58ad85 Enable post action 2020-05-09 21:02:32 +07:00
khai96_ 1790ca7f76 Add pnpm install 2020-05-09 20:24:52 +07:00
khai96_ 9a1617cf46 Rename install to install-pnpm 2020-05-09 20:03:45 +07:00
khai96_ 087311f996 refactor: Remove then 2020-05-08 21:55:03 +07:00
khai96_ 59a67d7671 Support tilde 2020-05-08 14:24:25 +07:00
khai96_ cf0395bd79 Use glob 2020-05-08 14:12:16 +07:00
khai96_ e1bd3c6b13 Use execPath 2020-05-08 13:47:46 +07:00
khai96_ b223fef427 Debug 2020-05-08 13:44:22 +07:00
khai96_ 696222a6f3 Complete source code 2020-05-08 13:12:01 +07:00
khai96_ 7d62586afe Complete basic 2020-05-08 13:06:16 +07:00