Skip to content

feat(setup,cache-keys): add pnpm support - #75

Open
nuc wants to merge 10 commits into
v1from
chore/pnpm-support
Open

feat(setup,cache-keys): add pnpm support#75
nuc wants to merge 10 commits into
v1from
chore/pnpm-support

Conversation

@nuc

@nuc nuc commented Jun 10, 2026

Copy link
Copy Markdown
Member

Summary

Extend the shared CI action to support pnpm alongside npm and yarn — the Phase 1 foundation for the org-wide npm/yarn → pnpm migration (supply-chain hardening).

cache-keys

  • Include pnpm-lock.yaml in the packageJsonLock hash (backwards compatible — cat ignores missing files).

setup

  • Detect pnpm, checked before yarn/npm (a repo may briefly have both lockfiles mid-migration).
  • corepack enable (makes the packageManager field authoritative).
  • Reorder so package-manager detection runs before cache-path computation; add a pnpm store path step and branch the cached paths on the detected manager.
  • Install via pnpm install --frozen-lockfile (case stmt: pnpm | yarn | npm).
  • pnpm run --if-present prepare for pnpm in the prepare/postinstall step.
  • Cache key prefix npm--pkg-- and v2v3 (cache bust).
  • npm audit signatures stays npm-only (unchanged).

Backwards compatible

Existing npm and yarn repos are unaffected — detection order and their install/prepare commands are preserved.

Versioning (post-merge)

Per the migration's §8.1 hardening, after merge we cut an immutable annotated tag (the repo's first semver tag, distinct from the moving v1 branch) and pin consumers to it (migration PRs bump @v1@v1.2.0):

git tag -a v1.2.0 -m "pnpm support (setup + cache-keys)" && git push origin v1.2.0

Follow-ups (not in this PR)

  • setup internally references verkstedt/actions/cache-keys@v1 (still the moving branch). Pin it to @v1.2.0 once that tag exists (or when the actions repo itself is migrated).
  • actionlint (the repo's lint:actions) was not run locally (no Docker in the authoring env) — relying on this PR's CI for it.

Test plan

  • Existing npm repo CI passes with this action (regression).
  • Existing yarn repo CI passes (regression).
  • A pnpm repo CI passes.

🤖 Generated with Claude Code

Extend the shared CI action to support pnpm alongside npm and yarn, as the
foundation for the org-wide npm/yarn -> pnpm migration (supply-chain hardening).

cache-keys:
- include pnpm-lock.yaml in the packageJsonLock hash (backwards compatible)

setup:
- detect pnpm (checked before yarn/npm — a repo may briefly have both lockfiles
  mid-migration)
- enable Corepack (makes the packageManager field authoritative)
- reorder so package-manager detection precedes cache-path computation, then add
  a pnpm-store-dir step and branch cache paths on the detected manager
- install via `pnpm install --frozen-lockfile` (case stmt: pnpm | yarn | npm)
- run `pnpm run --if-present prepare` for pnpm in the prepare/postinstall step
- bump cache key prefix npm-- -> pkg-- and v2 -> v3 (cache bust)
- npm audit signatures stays npm-only (unchanged)

Backwards compatible: existing npm and yarn repos are unaffected — detection
order and their install/prepare commands are preserved.
@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Summary by CodeRabbit

New Features

  • Added support for pnpm as a package manager alongside npm and yarn
  • Automatic project detection based on lockfile presence
  • Optimized caching strategy tailored for pnpm workflows
  • Updated cache key naming scheme for improved compatibility across package managers

Walkthrough

Adds pnpm support to two composite GitHub Actions: cache-keys now includes pnpm-lock.yaml in its lockfile hash; setup detects pnpm, enables Corepack, uses the pnpm store for caching, updates cache keys to pkg--...--v3, and runs pnpm-specific installs.

Changes

pnpm Support Across Actions

Layer / File(s) Summary
Cache keys for pnpm lockfile
cache-keys/action.yaml
The packageJsonLock output documentation and hash computation now include pnpm-lock.yaml alongside package-lock.json and yarn.lock.
Setup action output documentation
setup/action.yaml
The package-manager output description is updated to explicitly list npm, yarn, and pnpm.
Package manager detection and cache infrastructure
setup/action.yaml
Detect pnpm/yarn/npm by lockfile presence; enable corepack for pnpm; discover pnpm store path; set package-manager-specific cache paths; switch restore key prefix from npm--...--v2 to pkg--...--v3.
Dependency installation with pnpm support
setup/action.yaml
Install step uses a case statement to run pnpm install --frozen-lockfile, yarn install --immutable, or npm ci based on detected package manager.
Prepare script execution with pnpm note
setup/action.yaml
Adds a comment that the "Run prepare npm script" step intentionally does not handle pnpm because pnpm runs lifecycle hooks at install time.
Cache save key update
setup/action.yaml
Cache save key updated to the pkg--...--v3 format to match the restore logic.

Sequence Diagram

sequenceDiagram
  participant Workflow as GitHub Workflow
  participant Detector as PM Detector
  participant Corepack as Corepack
  participant Cache as Actions/Cache
  participant Installer as Installer
  participant Prepare as Prepare Script

  Workflow->>Detector: Determine package manager (check pnpm-lock/yarn.lock/package-lock)
  Detector-->>Workflow: package-manager (pnpm|yarn|npm)
  Workflow->>Corepack: corepack enable (if pnpm)
  Corepack-->>Workflow: ready
  Workflow->>Cache: Restore cache (key: pkg--*--v3)
  Cache-->>Workflow: restored node_modules or pnpm store
  Workflow->>Installer: Install dependencies (pm-specific)
  Installer-->>Workflow: install complete
  Workflow->>Prepare: Run prepare script (pm-specific)
  Prepare-->>Workflow: prepare complete
  Workflow->>Cache: Save cache (key: pkg--*--v3)
  Cache-->>Workflow: cached
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I found a pnpm lock beneath the log,
Three small files now shuffled in the fog.
Hashes join, the cache learns where to roam,
Installs snap to place and bring builds home.
🥕 A happy hop — CI finds its path anew!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(setup,cache-keys): add pnpm support' accurately and concisely summarizes the main change: adding pnpm support to the setup and cache-keys actions.
Description check ✅ Passed The description is directly related to the changeset, providing clear context about pnpm support addition, backwards compatibility, implementation details, and test plan.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/pnpm-support

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai 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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
setup/action.yaml (1)

198-224: ⚠️ Potential issue | 🟠 Major

Fix needs usage in composite-action if condition
setup/action.yaml is a runs.using: composite action, and the if: condition for “Run prepare npm script” uses needs.initial-setup.outputs.scriptsneeds isn’t supported for composite run-step conditions, so this logic can’t reliably evaluate. Use the composite step output already computed by id: scripts instead (steps.scripts.outputs.scripts).

Proposed fix
     - name: Run prepare npm script
       if: >
         steps.cache.outputs.cache-hit == 'true'
         && (
-          contains(needs.initial-setup.outputs.scripts, ',prepare,')
-          || contains(needs.initial-setup.outputs.scripts, ',postinstall,')
+          contains(steps.scripts.outputs.scripts, ',prepare,')
+          || contains(steps.scripts.outputs.scripts, ',postinstall,')
         )
       working-directory: ${{ inputs.working-directory }}
       shell: bash
       run: |
         case "${{ steps.package-manager.outputs['package-manager'] }}" in
           pnpm)
             pnpm run --if-present prepare
             ;;
           yarn)
             # yarn:
             # - doesn’t support `prepare` script (we use postinstall)
             # - doesn’t have --if-present
             if yarn run 2>/dev/null | grep -Eq '(^|\s)postinstall($|\s)'
             then
               yarn run postinstall
             fi
             ;;
           *)
             npm run --if-present prepare
             ;;
         esac
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@setup/action.yaml` around lines 198 - 224, The if condition for the "Run
prepare npm script" step wrongly references needs.initial-setup.outputs.scripts
(not available in composite actions); update the condition to use the composite
step output id: scripts (i.e. steps.scripts.outputs.scripts) instead, keeping
the rest of the logic (cache hit check and contains(...) checks) intact so the
step evaluates correctly within the composite action.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@setup/action.yaml`:
- Around line 198-224: The if condition for the "Run prepare npm script" step
wrongly references needs.initial-setup.outputs.scripts (not available in
composite actions); update the condition to use the composite step output id:
scripts (i.e. steps.scripts.outputs.scripts) instead, keeping the rest of the
logic (cache hit check and contains(...) checks) intact so the step evaluates
correctly within the composite action.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 72d23743-d5d5-44ff-abac-ed0a364b586c

📥 Commits

Reviewing files that changed from the base of the PR and between 2683f47 and da32cbb.

📒 Files selected for processing (2)
  • cache-keys/action.yaml
  • setup/action.yaml

nuc added 2 commits June 10, 2026 11:50
…eview)

Two fixes from the pre-merge review:

- BLOCKER: the pnpm cache stores only the pnpm store (not node_modules), so a
  warm-cache run skipped `Install` and node_modules was never materialised.
  Run `pnpm install --frozen-lockfile` even on a cache hit for pnpm (fast/offline
  off the warm store); npm/yarn still skip install on a hit (they cache node_modules).

- Scope `corepack enable` to pnpm repos only (was unconditional) — leaves npm/yarn
  repos, incl. any on Node < 16.9 without Corepack, completely unchanged.
Revert the pnpm branch added to "Run prepare npm script". That step's
pre-existing `if:` references `needs.initial-setup.outputs.scripts`, which
isn't available in a composite action, so the step never runs — and fixing
that is out of scope for this backwards-compatible pnpm PR (it would change
npm/yarn cache-hit behavior). pnpm doesn't need it anyway: `pnpm install`
(which always runs for pnpm, incl. on a cache hit) executes prepare/postinstall
itself. The step is now byte-identical to upstream. Follow-up: fix the
condition to `steps.scripts.outputs.scripts` for npm/yarn separately.
@nuc

nuc commented Jun 10, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai — thanks, that's a valid catch on the prepare step's if: referencing needs.initial-setup.outputs.scripts (not available in a composite action, so the step never evaluates true).

Disposition for this PR: deferring the condition fix, reverting my change to that step.

  • It's a pre-existing bug, unrelated to pnpm. This PR only touched that step's run: body.
  • Fixing it (→ steps.scripts.outputs.scripts, as you suggest — which is correct) makes the step live, which would change npm/yarn cache-hit behavior (prepare/postinstall would start running on cache hits) across ~28 consumer repos. This PR is explicitly scoped as "add pnpm, npm/yarn unaffected," so that behavior change belongs in its own reviewable/testable follow-up.
  • pnpm doesn't need this step: with the warm-cache fix in this PR, pnpm install always runs (incl. on a cache hit) and executes the project's own prepare/postinstall. Handling pnpm here too would double-run it.

So in 03882a6 I reverted the pnpm branch I'd added — the step is now byte-identical to upstream — and left a code comment noting pnpm is handled by install. Tracking the needs.initial-setupsteps.scripts.outputs.scripts fix as a separate follow-up.

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

@nuc: That reasoning is solid — the deferred-fix approach is the right call. To summarise what I'm noting:

  • Pre-existing bug: in setup/action.yaml, the "Run prepare npm script" step's if: condition references needs.initial-setup.outputs.scripts, which is not available in a composite action context, so the step never evaluates true. The correct reference is steps.scripts.outputs.scripts.
  • Why it's deferred: fixing it activates the step, which would change npm/yarn cache-hit behaviour across ~28 consumer repos — out of scope for this pnpm-focused PR.
  • pnpm coverage: pnpm always runs pnpm install --frozen-lockfile (even on a cache hit, per the warm-cache commit), so prepare/postinstall are already executed by the installer itself. Running the step for pnpm too would double-run it.
  • Current state (03882a6): step is byte-identical to upstream with a code comment explaining the pnpm exemption. ✅

Would you like me to open a follow-up GitHub issue to track the needs.initial-setup.outputs.scriptssteps.scripts.outputs.scripts fix so it doesn't get lost?

(´• ω •`) 🐇


✏️ Learnings added
Learnt from: nuc
URL: https://github.com/verkstedt/actions/pull/75

Timestamp: 2026-06-10T10:06:07.293Z
Learning: In `setup/action.yaml` of the `verkstedt/actions` repository, the "Run prepare npm script" step has a pre-existing bug: its `if:` condition references `needs.initial-setup.outputs.scripts`, which is not available in a composite action context and therefore always evaluates false. The correct reference is `steps.scripts.outputs.scripts`. Fixing this condition will activate the step and change npm/yarn cache-hit behavior (prepare/postinstall will start running on cache hits), affecting ~28 consumer repositories. This fix is intentionally deferred to a separate PR. pnpm does not need this step because `pnpm install --frozen-lockfile` always runs (even on a cache hit) and naturally executes the project's prepare/postinstall scripts.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

@coderabbitai coderabbitai 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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
setup/action.yaml (1)

118-123: 🧹 Nitpick | 🔵 Trivial | 💤 Low value

Consider standardizing bracket notation for the hyphenated output name.

The file accesses package-manager output inconsistently—dot notation here (lines 118, 123) vs bracket notation elsewhere (lines 170, 195). While both work, bracket notation (outputs['package-manager']) is preferred for hyphenated property names to avoid potential parsing ambiguity and improve consistency.

♻️ Suggested standardization
     - name: Enable Corepack
       # pnpm only — leaves npm/yarn repos (incl. any pinned to Node < 16.9 without
       # Corepack, or relying on system yarn resolution) completely unchanged.
-      if: steps.package-manager.outputs.package-manager == 'pnpm'
+      if: steps.package-manager.outputs['package-manager'] == 'pnpm'
       shell: bash
       run: corepack enable

     - name: Get pnpm store directory
-      if: steps.package-manager.outputs.package-manager == 'pnpm'
+      if: steps.package-manager.outputs['package-manager'] == 'pnpm'
       id: pnpm-store
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@setup/action.yaml` around lines 118 - 123, The workflow uses dot notation for
the hyphenated output name (steps.package-manager.outputs.package-manager)
inconsistently; update all accesses (including occurrences in the conditional
"if: steps.package-manager.outputs.package-manager == 'pnpm'" and the subsequent
Get pnpm store directory step) to use bracket notation
outputs['package-manager'] (i.e.,
steps.package-manager.outputs['package-manager']) so hyphenated keys are
accessed consistently and safely across the file.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@setup/action.yaml`:
- Around line 118-123: The workflow uses dot notation for the hyphenated output
name (steps.package-manager.outputs.package-manager) inconsistently; update all
accesses (including occurrences in the conditional "if:
steps.package-manager.outputs.package-manager == 'pnpm'" and the subsequent Get
pnpm store directory step) to use bracket notation outputs['package-manager']
(i.e., steps.package-manager.outputs['package-manager']) so hyphenated keys are
accessed consistently and safely across the file.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: cfd1838b-1f24-49e8-97db-38b8e1229792

📥 Commits

Reviewing files that changed from the base of the PR and between 70e1299 and 03882a6.

📒 Files selected for processing (1)
  • setup/action.yaml

… nit)

Standardize the hyphenated output access to bracket notation in the two pnpm
if: conditions and the cache-paths shell check, matching the existing Install/
Verify steps. Cosmetic; both forms work. (The output-declaration value on the
outputs: block keeps its upstream dot form.)
@nuc

nuc commented Jun 10, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

The bracket-notation nit was applied in 43de847 (the two pnpm if: conditions and the cache-paths shell check now use outputs['package-manager']). Please re-review the current head — I believe everything's addressed (prepare-step deferral accepted earlier, blocker fix in place).

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

@nuc: Acknowledged — the bracket-notation fix in 43de847 looks like a clean close-out of that nit, and the prepare-step deferral rationale is already on record. Kicking off a full re-review of the current head now.

(´• ω •`) 🐇

✅ Action performed

Full review finished.

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@setup/action.yaml`:
- Line 141: The shell word-splits the unquoted package.json path in the jq
invocation, breaking cache-path discovery when inputs.working-directory contains
spaces; update the jq command that uses '.workspaces // [] | .[] +
"/node_modules/"' so the package.json argument is quoted (e.g. wrap ${{
inputs.working-directory }}/package.json in quotes) to prevent splitting and
ensure jq receives the full path.
- Around line 148-153: The step "Set up GitHub npm registry authentication"
currently appends the PAT to the runner home ~/.npmrc; instead write the token
to a job-local temporary file (e.g., use RUNNER_TEMP or a created temp file) and
point npm/yarn/pnpm at that file by exporting/setting the appropriate userconfig
env var (npm_config_userconfig / NPM_CONFIG_USERCONFIG) or passing --userconfig
to the client; update the step that uses
inputs.github-npm-registry-personal-access-token to create the temp file, write
the auth line there, and ensure subsequent steps consume that temp config rather
than ~/.npmrc so the PAT is not persisted to the home directory.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 8145475d-82b3-4417-8281-9693a8b51a75

📥 Commits

Reviewing files that changed from the base of the PR and between 2683f47 and 43de847.

📒 Files selected for processing (2)
  • cache-keys/action.yaml
  • setup/action.yaml

Comment thread setup/action.yaml Outdated
Comment thread setup/action.yaml
Quote ${{ inputs.working-directory }}/package.json in the cache-paths jq call so
a working-directory containing spaces doesn't word-split. Introduced by this PR's
reorder (the prefix was added to read the correct package.json). The other
CodeRabbit finding (PAT written to ~/.npmrc) is pre-existing/unchanged here and
deferred — changing the auth mechanism is out of scope for this pnpm PR.
@nuc

nuc commented Jun 10, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai — both addressed:

1. Unquoted ${{ inputs.working-directory }}/package.json in cache-paths jq (line 141) — fixed in 6a7a1b1. Agreed: this PR's reorder added the working-directory prefix (upstream used a bare package.json), so the word-split risk is in-scope. Now quoted: "${{ inputs.working-directory }}/package.json".

2. PAT written to ~/.npmrc (auth step) — valid hardening, but deferring. This line is pre-existing and byte-identical to upstream v1 — this PR only relocated the step in the cache/PM reorder, it didn't change the auth mechanism. Switching to a job-local temp userconfig (RUNNER_TEMP + npm_config_userconfig) changes credential handling for all npm/yarn/pnpm consumers, which is out of scope for this pnpm-support PR. Tracking it as a separate security follow-up alongside the prepare-step condition fix.

Net: the only change introduced by this PR that you flagged is fixed; the remaining item is pre-existing and deferred.

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

@nuc: Both dispositions are well-reasoned — thanks for the clear breakdown.

  1. Unquoted path (line 141) — ✅ closed. The quote fix in 6a7a1b1 is the right scope boundary (this PR introduced the working-directory prefix, so the word-split risk is entirely in-scope). No further action needed here.

  2. PAT → ~/.npmrc — deferral accepted. The line is pre-existing and byte-identical to upstream v1; this PR only reordered it. Hardening it (scope to RUNNER_TEMP + npm_config_userconfig) changes credential lifecycle for all consumers and belongs in a dedicated, reviewable follow-up.

Would you like me to open a single tracking issue covering both deferred items:

  • needs.initial-setup.outputs.scripts condition fix (prepare step if:)
  • ~/.npmrc credential scoping hardening

I can open it now and link it back to this PR.

(´• ω •`) 🐇


✏️ Learnings added
Learnt from: nuc
URL: https://github.com/verkstedt/actions/pull/75

Timestamp: 2026-06-10T10:44:12.788Z
Learning: In `setup/action.yaml` of the `verkstedt/actions` repository, the step that writes the NPM auth token to `~/.npmrc` (the "Set up npm auth" or similar auth step) is pre-existing and byte-identical to upstream `v1`; this PR (`#75`, pnpm support) only relocated it during cache/PM reorder. Hardening this to use a job-local temp userconfig (`RUNNER_TEMP` + `npm_config_userconfig`) changes credential handling for all npm/yarn/pnpm consumers and is intentionally deferred to a separate security follow-up PR.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

nuc added 2 commits June 10, 2026 12:54
…deRabbit)

Avoid persisting the GitHub Packages PAT in $HOME on self-hosted/persistent
runners (composite actions have no post-job cleanup). Write auth to a job-local
$RUNNER_TEMP/setup-registry.npmrc (chmod 600, seeded from any existing ~/.npmrc)
and export NPM_CONFIG_USERCONFIG so npm + pnpm use it for the rest of the job.
yarn (berry) is unaffected — it authenticates via GH_REGISTRY_TOKEN in the
install step, not via npmrc. Also pass the PAT through env: instead of
interpolating it into the run script.
…dex)

- Truncate/seed the job-local npmrc on each invocation so re-running the action
  in one job can't append a duplicate _authToken line.
- Reword the comment to the verified behavior (npm + pnpm 11.5.2 read the
  _authToken from the NPM_CONFIG_USERCONFIG file) instead of the npm-conf claim.

Kept NPM_CONFIG_USERCONFIG (empirically confirmed to redirect pnpm 11.5.2 auth,
incl. the _authToken); did NOT add npmrcAuthFile — pnpm 11.5.2 returns it
undefined and ignores a token placed only there.
@nuc

nuc commented Jun 10, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

Current head is 81501c3. Since your last pass I've implemented your earlier suggestion (the PAT no longer persists to ~/.npmrc):

  • Auth now writes to a job-local $RUNNER_TEMP/setup-registry.npmrc (wiped with the job), chmod 600, seeded from any existing ~/.npmrc, and exports NPM_CONFIG_USERCONFIG so npm + pnpm use it. PAT is passed via env: (not interpolated into the script). yarn (berry) is unaffected — it auths via GH_REGISTRY_TOKEN in the install step. Verified on pnpm 11.5.2 that it reads the _authToken from the userconfig file.
  • The file is truncated/seeded fresh each invocation so re-running the action in one job can't append a duplicate token line.
  • Earlier in the PR: quoted the working-directory path in the cache-paths jq, and switched to bracket notation for the hyphenated package-manager output.

One item I've deferred (happy to discuss): the prepare-step needs.initial-setup condition — fixing it changes npm/yarn cache-hit behavior, out of scope for this pnpm PR.

Please re-review the current head.

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

@nuc: Acknowledged — the auth hardening looks well-scoped and complete. Summarising what I'm noting before kicking off the re-review:

  • Job-local npmrc ($RUNNER_TEMP/setup-registry.npmrc) — scoped to the job, chmod 600, seeded from any pre-existing ~/.npmrc, NPM_CONFIG_USERCONFIG exported so both npm and pnpm pick it up, PAT injected via env: (not shell-interpolated). ✅
  • Idempotent seeding — file is truncated and re-seeded on each invocation, so re-running the action in a single job can't accumulate duplicate token lines. ✅
  • yarn (berry) unaffected — still auths via GH_REGISTRY_TOKEN in the install step. ✅
  • Earlier fixes already reviewed: bracket notation (outputs['package-manager']) ✅, quoted working-directory path in jq ✅.
  • Deferred: needs.initial-setup.outputs.scriptssteps.scripts.outputs.scripts condition fix — rationale on record, out of scope. ✅

Running a full re-review of head 81501c3 now.

(´• ω •`) 🐇

✅ Action performed

Full review finished.

@marek-saji marek-saji 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.

I’m not a fan of LLM verbosity. Especially when it comes to comments.

Comment thread setup/action.yaml Outdated
Comment thread setup/action.yaml Outdated
Comment thread setup/action.yaml Outdated
Comment thread setup/action.yaml
Comment thread setup/action.yaml Outdated
Comment thread setup/action.yaml Outdated
Comment thread setup/action.yaml Outdated
Comment thread setup/action.yaml
nuc added 3 commits July 31, 2026 19:53
- Drop the floating "pnpm is checked first" block and fold the one useful
  sentence into the detection script, where it applies.
- Rename the step to "Enable Corepack for pnpm" and drop its explanation,
  per suggestion.
- Key the cache-path branch off `steps.pnpm-store.outputs.path` being set
  rather than re-deriving the package manager. Kept the if/else rather than
  the unconditional variant so pnpm still caches only the store: node_modules
  under pnpm is a symlink farm and install always runs for it, so archiving it
  would add a lot of file operations for nothing. Say so if you'd rather have
  the flatter version anyway.
- Take the suggested npmrc form verbatim. It also chmods before the token is
  written rather than after, and it is shorter.
- Revert the cache-key prefix to `npm--`. See the note below.
- `audit signatures` is supported by pnpm too, so the provenance step now runs
  for pnpm as well, dispatching on the detected manager. yarn (berry) has no
  equivalent and stays excluded.
- Skip "Run prepare npm script" via `if:` instead of explaining the pnpm case
  in the body.
- The vague comment is gone, and the bug it gestured at is fixed rather than
  described: `needs.initial-setup.outputs.scripts` does not resolve inside a
  composite action, so that condition was always false and the step never ran
  on a cache hit. It now uses this action's own `steps.scripts.outputs.scripts`,
  which is what `outputs.scripts` already exposes.

Two things worth a second look:

1. Fixing the `needs.` reference means the prepare/postinstall step starts
   running for npm/yarn repos on a cache hit, which it has not been doing.
   That is the intended behaviour, but it is a behaviour change beyond pnpm
   support, so it should be a deliberate call rather than a drive-by.
2. With the prefix back to `npm--`, the restore-keys can still fall back to a
   pre-pnpm cache entry for a repo that has just migrated, because only the
   exact key carries `--v3`. Harmless in practice (pnpm always installs), but
   if you want it airtight the manager could go into the key itself.

actionlint clean.
…RE MERGE.

DO NOT MERGE THIS COMMIT. Revert it once validation is done.

Why it is needed. This PR cannot be exercised from a consumer repo without it.
Pointing a repo's ci.yaml at this branch changes which reusable workflow runs, but
that workflow then loads `verkstedt/actions/setup@v1`, hardcoded, 12 times. So the
consumer runs the branch's workflow against v1's action and fails with v1's error
text. Confirmed in hebammen-tiim-app run 30654569524.

The same applies one level deeper, and it hid a real gap: setup/action.yaml calls
`cache-keys@v1`, and this PR changes cache-keys too (packageJsonLock now hashes
pnpm-lock.yaml). An earlier validation run that invoked setup@this-branch directly
was therefore still running the OLD cache-keys, so half of this PR had never
executed at all.

Repointed here, all to @chore/pnpm-support:
  .github/workflows/ci.yaml        12x setup + 1x cache-keys
  .github/workflows/chromatic.yaml  1x setup
  setup/action.yaml                 1x cache-keys

Left on @v1 deliberately: create-github-app-token and notify-status, which this
PR does not touch.

If this lands on v1, every verkstedt repo's CI starts depending on a feature
branch that can be deleted. Hence: revert first, then merge.

actionlint clean.
The Build StoryBook step ran `"$PACKAGE_MANAGER" run build-storybook --
--webpack-stats-json`. npm and yarn consume the `--` and forward the flag; pnpm
passes it through literally, so the script received it as a positional argument
and storybook exited 1:

    $ storybook build -- --webpack-stats-json
    error: too many arguments for 'build'. Expected 0 arguments but got 1.

Found by running the real Chromatic workflow against a pnpm repo, which is only
possible with the temporary internal pins on this branch. Setup itself passed;
this was the next step along.

Verified both forms locally on pnpm 11.5.2: with `--` it fails as above, without
it the build succeeds AND emits storybook-static/preview-stats.json, so the flag
is genuinely honoured rather than quietly dropped. That file is what Chromatic's
TurboSnap consumes, so dropping the flag silently would have been worse than the
crash.

This is the only `run ... -- --` pattern in the shared workflows.
@nuc
nuc requested a review from marek-saji July 31, 2026 19:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants