Skip to content

ci: reuse pnpm's lockfile supply-chain check across jobs - #4318

Open
danielmlr wants to merge 2 commits into
mainfrom
daniel/ci-pnpm-verdict-cache
Open

danielmlr wants to merge 2 commits into
mainfrom
daniel/ci-pnpm-verdict-cache

Conversation

@danielmlr

@danielmlr danielmlr commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

What does this PR do?

Makes pnpm install about 15 seconds faster in most CI jobs by keeping pnpm's record of a passed lockfile check. On every install, pnpm 11 checks the 1,997 lockfile entries against minimumReleaseAge, the trust policy and the tarball URLs, which takes about 35 seconds and runs partly alongside the rest of the install. It skips that check when lockfile-verified.jsonl in its cache directory records a pass for the same lockfile content, but setup-node only caches the store, so CI jobs never had that file.

A new step keeps the file in actions/cache, keyed on the pnpm version and the hashes of pnpm-lock.yaml and pnpm-workspace.yaml, where the policy lives. It also sets pnpm's cache directory to its default (~/.cache/pnpm) so the cached path and pnpm's path can't drift apart. A changed lockfile or policy finds no cached record, so it gets the full check, and its new pass is saved for the jobs that start later. pnpm checks this on its own too: it only reuses a pass made for the same lockfile content under the same or a stricter policy. The step runs in the nine install jobs in ci.yml and in Format, Query Counts, Env Types, Visual Regression and Preview Releases. Release, Auto Extract and Lunaria, which run with write access, and the Dependabot-only release-action bundle job keep the full check on every run.

Type of change

  • Bug fix
  • Feature (requires an accepted feature plan or RFC)
  • Refactor (no behavior change)
  • Translation
  • Documentation
  • Performance improvement
  • Tests
  • Chore (dependencies, CI, tooling)

Your connection to this change

  • I use EmDash and ran into the problem this PR addresses
  • I maintain a tool, dependency, or service that EmDash uses, and this change concerns that integration
  • A Maintainer approved this specific change before I opened the PR

Checklist

  • I have read CONTRIBUTING.md
  • pnpm typecheck passes
  • pnpm lint passes
  • pnpm test passes (or targeted tests for my change)
  • pnpm format has been run
  • I have added/updated tests for my changes (if applicable) (n/a: workflow change; the CI run below exercises it)
  • User-visible strings in the admin UI are wrapped for translation (if applicable). Do not include messages.po changes except in translation PRs — a workflow extracts catalogs on merge to main. (n/a: no admin UI change)
  • I have added and reviewed the user-facing changeset (if this PR changes a published package) (n/a: CI workflow only)
  • New features link to their merged design PR: https://github.com/emdash-cms/emdash/pull/... (n/a: not a feature)
  • I have included screenshots below if this PR changes the UI (n/a: no UI change)

AI assistance disclosure

  • This PR includes AI-generated code or text — model/tool: Claude Opus 5.5

Screenshots / test output

Test output:

  • Before: in the last five successful main runs up to 8da0792 (2026-10-20), pnpm install took a median 38 s over all jobs, and pnpm's log put the lockfile check at a median 35 s (22 to 40 s).
  • After, on a fork with the same runner type (run): in the first run, jobs that started after the first job had saved the file already printed "Lockfile passes supply-chain policies (verified 9m ago)". In the second run all 19 jobs that install restored it, and pnpm install took a median 21 s (18 to 25 s), against 37 s (28 to 42 s) in a second run of main there (run).
  • Typecheck, lint and every test job passed in both runs.
  • zizmor 1.26.1 with .github/zizmor.yml: no findings in the default persona, and the same counts as main in the pedantic and auditor personas.

pnpm re-verifies every lockfile entry against minimumReleaseAge, the
trust policy and tarball URLs on each install, which takes 22-40 s per
job. It skips that check when lockfile-verified.jsonl in its cache
directory records a passing result for the same lockfile content and
policy, but setup-node only caches the store, so CI never kept that
file.

Cache the file per pnpm version and lockfile hash in the ci.yml install
jobs and in format, query-counts, env-types, visual and
preview-releases. The cache directory is pinned to pnpm's default so the
cached path and pnpm's path always agree. release.yml, whose publish job
has id-token: write, keeps the full check on every run.
@changeset-bot

changeset-bot Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 8bc9f82

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

🚀 Deploying Preview to Cloudflare 🚀

Preview URL: https://daniel-ci-pnpm-verdict-cache.try.emdashcms.com, https://daniel-ci-pnpm-verdict-cache-emdash-playground.emdash-cms.workers.dev (commit 8bc9f82)

This URL reflects your latest Preview deployment

Preview Deployments by commit

Status Deployment URL Commit Updated (UTC) See this deployment's details
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://69e49aa0.try.emdashcms.com, https://69e49aa0-emdash-playground.emdash-cms.workers.dev 8bc9f82 2026-10-21T02:26:46.122Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://596c40cc.try.emdashcms.com, https://596c40cc-emdash-playground.emdash-cms.workers.dev 90e24b4 2026-10-21T02:08:46.001Z Visit the dashboard ↗

@emdashbot emdashbot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The approach is sound: it caches only pnpm's lockfile-verified.jsonl record rather than disabling supply-chain checks, and it leaves the privileged workflows (Release, Auto Extract, Lunaria, release-action) unchanged. Both reviewers approved and found no correctness or security problems. A stale or bad cache entry can only cost a full check, since pnpm keys its lookup on the lockfile content hash and only reuses a pass made under the same or a stricter policy. The cache is also scoped away from untrusted runs. Both reviews were static, and neither confirmed pnpm's pnpm_config_cache_dir handling or the reported timings by running anything. One non-blocking suggestion remains: the cache key should also cover pnpm-workspace.yaml, which holds the policy. A verdict of comment rather than approve is used only so that suggestion is not lost. Only one reviewer raised it, and the other did not mention it.


Reviewed by anthropic/claude-opus-5-5 and openai/gpt-6.1-sol.

Comment thread .github/workflows/ci.yml Outdated
@pkg-pr-new

pkg-pr-new Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

@emdash-cms/admin

npm i https://pkg.pr.new/emdash-cms/emdash/@emdash-cms/admin@4318

@emdash-cms/auth

npm i https://pkg.pr.new/emdash-cms/emdash/@emdash-cms/auth@4318

@emdash-cms/auth-atproto

npm i https://pkg.pr.new/emdash-cms/emdash/@emdash-cms/auth-atproto@4318

@emdash-cms/blocks

npm i https://pkg.pr.new/emdash-cms/emdash/@emdash-cms/blocks@4318

@emdash-cms/cloudflare

npm i https://pkg.pr.new/emdash-cms/emdash/@emdash-cms/cloudflare@4318

@emdash-cms/contentful-to-portable-text

npm i https://pkg.pr.new/emdash-cms/emdash/@emdash-cms/contentful-to-portable-text@4318

emdash

npm i https://pkg.pr.new/emdash-cms/emdash@4318

create-emdash

npm i https://pkg.pr.new/emdash-cms/emdash/create-emdash@4318

@emdash-cms/gutenberg-to-portable-text

npm i https://pkg.pr.new/emdash-cms/emdash/@emdash-cms/gutenberg-to-portable-text@4318

@emdash-cms/plugin-cli

npm i https://pkg.pr.new/emdash-cms/emdash/@emdash-cms/plugin-cli@4318

@emdash-cms/plugin-test

npm i https://pkg.pr.new/emdash-cms/emdash/@emdash-cms/plugin-test@4318

@emdash-cms/plugin-types

npm i https://pkg.pr.new/emdash-cms/emdash/@emdash-cms/plugin-types@4318

@emdash-cms/registry-client

npm i https://pkg.pr.new/emdash-cms/emdash/@emdash-cms/registry-client@4318

@emdash-cms/registry-lexicons

npm i https://pkg.pr.new/emdash-cms/emdash/@emdash-cms/registry-lexicons@4318

@emdash-cms/registry-loader

npm i https://pkg.pr.new/emdash-cms/emdash/@emdash-cms/registry-loader@4318

@emdash-cms/registry-moderation

npm i https://pkg.pr.new/emdash-cms/emdash/@emdash-cms/registry-moderation@4318

@emdash-cms/registry-verification

npm i https://pkg.pr.new/emdash-cms/emdash/@emdash-cms/registry-verification@4318

upgrade-emdash

npm i https://pkg.pr.new/emdash-cms/emdash/upgrade-emdash@4318

@emdash-cms/sandbox-workerd

npm i https://pkg.pr.new/emdash-cms/emdash/@emdash-cms/sandbox-workerd@4318

@emdash-cms/x402

npm i https://pkg.pr.new/emdash-cms/emdash/@emdash-cms/x402@4318

@emdash-cms/plugin-ai-moderation

npm i https://pkg.pr.new/emdash-cms/emdash/@emdash-cms/plugin-ai-moderation@4318

@emdash-cms/plugin-ai-search

npm i https://pkg.pr.new/emdash-cms/emdash/@emdash-cms/plugin-ai-search@4318

@emdash-cms/plugin-atproto

npm i https://pkg.pr.new/emdash-cms/emdash/@emdash-cms/plugin-atproto@4318

@emdash-cms/plugin-audit-log

npm i https://pkg.pr.new/emdash-cms/emdash/@emdash-cms/plugin-audit-log@4318

@emdash-cms/plugin-color

npm i https://pkg.pr.new/emdash-cms/emdash/@emdash-cms/plugin-color@4318

@emdash-cms/plugin-embeds

npm i https://pkg.pr.new/emdash-cms/emdash/@emdash-cms/plugin-embeds@4318

@emdash-cms/plugin-field-kit

npm i https://pkg.pr.new/emdash-cms/emdash/@emdash-cms/plugin-field-kit@4318

@emdash-cms/plugin-forms

npm i https://pkg.pr.new/emdash-cms/emdash/@emdash-cms/plugin-forms@4318

@emdash-cms/plugin-webhook-notifier

npm i https://pkg.pr.new/emdash-cms/emdash/@emdash-cms/plugin-webhook-notifier@4318

commit: 8bc9f82

pnpm only reuses a stored pass made under the same policy, and the
policy lives in pnpm-workspace.yaml. With only the lockfile in the key, a
policy change that leaves the lockfile alone still hits the old cache
entry: pnpm rejects the pass and runs the full check, but actions/cache
does not save on an exact key hit, so every later job repeats the full
check until the lockfile changes.
@emdashbot emdashbot Bot added review/needs-review No maintainer or bot review yet and removed review/needs-review No maintainer or bot review yet labels Oct 21, 2026

@emdashbot emdashbot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The follow-up is the right, narrowly scoped change: including the policy file in the cache key preserves reuse after policy edits without changing pnpm's checks.

Verified all 14 cache keys across the six affected workflows now hash both pnpm-lock.yaml and pnpm-workspace.yaml. This addresses the earlier suggestion and matches the author's reply. No findings remain, and I found no new defects in the follow-up diff.

Review was static; workflows and reported timings were not independently executed or verified.


Follow-up review by openai/gpt-6.1-sol, scoped to the changes since the last review.

@danielmlr danielmlr added the ci:run Approve and re-run CI on the PR's latest commit label Oct 21, 2026
@github-actions github-actions Bot removed the ci:run Approve and re-run CI on the PR's latest commit label Oct 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant