Skip to content

ci: install pinned npm 11 before every dependency install - #2729

Merged
cliffhall merged 1 commit into
v2/mainfrom
v2/chore/2715-ci-npm-11
Oct 20, 2026
Merged

cliffhall merged 1 commit into
v2/mainfrom
v2/chore/2715-ci-npm-11

Conversation

@cliffhall

Copy link
Copy Markdown
Member

Closes #2715

Problem

#2712 denies the esbuild and fsevents install scripts through allowScripts in each v2 install. npm reads that field only from 11.19 onward. Node 22's bundled npm is 10.x, so npm install in the build, coverage and package jobs still ran both scripts. verify:install-scripts enforced the review decision in CI, but nothing actually blocked the scripts there.

Change

  • main.yml now states the CI npm once, at workflow level: CI_NPM_VERSION: '11.20.0', the version publish already pinned for OIDC (Release job runs install-time scripts and unpinned tooling while holding the npm OIDC publish token #2483). build, coverage and package each run npm install -g --ignore-scripts "npm@$CI_NPM_VERSION" right after setup-node, before any install. publish reads the same variable, so there is one place to bump it.
  • dependency-refresh.yml also runs a scripted npm install, so it gets the same step. It's a separate workflow and can't read the variable, so it pins the literal, and comments on both sides say to keep them equal.
  • Comments in verify-install-scripts.mjs and install-clients.test.mjs, and the verify:install-scripts row in docs/quality-gate.md, said CI installs with npm 10. They now describe the current setup, and the docs row separates the decision (the guard, works on any npm) from the blocking (npm ≥ 11.19).

Not changed: sdk-watch and dependabot-alerts already install with npm ci --ignore-scripts, and the dco jobs install nothing.

Answers to the issue's three checks

  • Credentialed-job rules (SHA-pin the GitHub Actions that hold secrets or publish (claude-code-action, release job) #2484): the pin is exact, not a range. package builds the tarball the credentialed publish job ships, so it follows the same reasoning publish uses for its own pin. --ignore-scripts keeps npm's own lifecycle scripts out.
  • Node floor: npm 11 requires Node ^20.17.0 || >=22.9.0, and CI runs 22.x, so it fits. The comment keeps the existing instruction to stay on 11.x until npm 12's floor is checked.
  • Anything else breaking on npm 11: all three lockfile installs already run under npm 11 locally (11.19, the version the gate runs on). I also ran npx npm@11.20.0 install-scripts ls in clients/web, which reports No packages with unreviewed install scripts., so the pinned version reads the denials. The install-clients "premise" test, which skipped on npm 10, will now run in CI. It already passes locally on 11.19.

Verification

npm run local:gate passed (EXIT=0) on this branch. The real proof is this PR's own CI run: the build and coverage jobs install with the pinned npm.

🤖 Generated with Claude Code

Node 22's bundled npm 10.x ignores each install's `allowScripts`, so
the esbuild/fsevents denials from #2712 never applied in CI. Every job
that installs dependencies (build, coverage, package, and the monthly
dependency-refresh sweep) now installs an exact-pinned npm first, with
--ignore-scripts, as `publish` already did for OIDC. main.yml states
the version once as CI_NPM_VERSION, which `publish` now reads too.

Also corrects comments and docs that said CI installs with npm 10.

Closes #2715

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
@cliffhall cliffhall added the v2 Issues and PRs for v2 label Oct 20, 2026
@cliffhall
cliffhall requested a balanced review from Copilot October 20, 2026 00:28

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟢 Approval recommended

The targeted installs consistently use the exact npm pin before dependencies, and publishing safeguards remain intact.

No open issues 🎉

What changed in this PR

Pins CI to npm 11.20.0 so dependency installs enforce the existing allowScripts denials.

Changes:

  • Shares one npm pin across build, coverage, package, and publish jobs.
  • Adds the matching pin to the dependency-refresh workflow.
  • Updates documentation and comments to distinguish policy checks from script blocking.
File Description
scripts/​verify-install-scripts.mjs Updates comments about CI’s npm version.
scripts/​install-clients.test.mjs Corrects the test’s npm-version commentary.
docs/​quality-gate.md Clarifies policy verification versus enforcement.
.github/​workflows/​main.yml Installs the shared npm pin before dependency installs.
.github/​workflows/​dependency-refresh.yml Adds the matching pinned npm installation.

Review effort: Balanced

@cliffhall

Copy link
Copy Markdown
Member Author

Copilot review loop closed: round 1 was clean. No inline comments, no headline finding, no suppressed comments ("No open issues"), so I'm stopping here without a confirming round.

@cliffhall
cliffhall merged commit 44a41d2 into v2/main Oct 20, 2026
8 checks passed
@cliffhall
cliffhall deleted the v2/chore/2715-ci-npm-11 branch October 20, 2026 03:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

v2 Issues and PRs for v2

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CI installs with npm 10, so the allowScripts denials from #2712 do not apply there

2 participants