Skip to content

Update dependencies; vitest 5; one source of truth for the CI Node version - #1332

Merged
amyjko merged 3 commits into
mainfrom
dependency-updates
Sep 4, 2026
Merged

Update dependencies; vitest 5; one source of truth for the CI Node version#1332
amyjko merged 3 commits into
mainfrom
dependency-updates

Conversation

@amyjko

@amyjko amyjko commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator

Context

A dependency update pass. Absorbs both open Dependabot PRs, clears the one high-severity advisory in either tree, takes the one major upgrade that is actually reachable, and collapses three spellings of the Node version in CI into one file.

Security (lockfile only) — fast-uri 3.1.5 → 3.1.7 (the only high; host confusion + SSRF, via ajv), re2 1.24.1 → 1.26.1, and in functions/ qs 6.15.3 → 6.16.0.

In range, no range edits@anthropic-ai/sdk 0.120.0 → 0.123.0 (both workspaces together so the two copies can't drift), zod 4.4.3 → 4.5.4, svelte 5.56.10 → 5.57.0, firebase-tools 15.28.1 → 15.29.0, lint-staged 17.3.0 → 17.4.1, tsx, @wasm-audio-decoders/flac, and nodemailer 9.0.5 → 9.1.1 in functions/.

vitest 4 → 5 needed no test changes. The config was already in v5's shape (extends: true on both projects), and clearMocks defaulting to true is inert here: every file that mocks either clears in beforeEach already, rebuilds its mocks per test, or has no spies at all. It does print a config-loader warning on every run, so the two imports in vitest.config.ts now carry file extensions.

picomatch removed — declared a runtime dependency with zero import sites anywhere in the repo; it arrives transitively via vite regardless.

Node version — the deploy.yml pin at 22.22.0 worked around Node 22.23.0's http.Agent keep-alive change breaking firebase-tools' OAuth, and its own comment said to revert once nodejs/node#64004 shipped. That landed in v22.23.1 on 2026-06-22. The pin had also gone from stale to wrong: lint-staged@17.4.1 requires node >=22.22.1. All eight node-version: lines now read node-version-file: '.nvmrc'. .nvmrc holds an exact version rather than a floating 22 on purpose — a floating range is what let a bad Node release into the deploy job in the first place.

TypeScript stays at 6.0.3. svelte-check@4.7.6 still declares typescript: ^5 || ^6 and ts-json-schema-generator depends on ^5.9.3, so 7.0.2 is only reachable behind svelte-check's experimental --tsgo with both compilers installed side by side. Worth revisiting when svelte-check widens its peer range.

Related issues

Verification

No user-visible change, so no screen-reader / keyboard / color pass applies. This is dependencies, CI config, and one test-config line.

  • npm run check:now — 3394 files, 0 errors, 0 warnings
  • npm run test:run496 files, 10,901 passed, 7 skipped, on vitest 5.0.0
  • Shuffled cold-cache run (rm -rf node_modules/.vite/vitest && npx vitest run --project=fast --sequence.shuffle.files) — 480 files, 10,770 passed. This is the check for the shared-graph class of problem, and the one that would catch mock leakage from the new clearMocks default.
  • npm run locales — zero errors
  • npm run format:check — clean
  • npm run build:ci — succeeds. Because vite.config.js's manualChunks matches node_modules path strings, a dependency that restructures its package directory changes the chunk graph without erroring, so I compared against a pre-update build: 95 chunks before and after, total chunk bytes down 188KB, and the vendor/rapier chunks byte-identical (2,116,649 → 2,116,648).
  • e2e under the emulator — 281 passed, with howto-form.spec.ts:70 and :104 flaking. Those two are not from this branch: they flake on main too, and main's own deploy run for 3ae1b17 logs 2 flaky naming both, with the identical timeout at line 125. They go green because retries: 1 absorbs them on CI (retries: 0 locally, so a single flake reads as a hard failure). Reproduced this branch under CI's settings (CI=true … --workers=2): 2 flaky / 2 passed, exit 0. I also confirmed by reverting the root manifest, npm ci-ing back to the old versions and rebuilding — identical result.

Checklist

  • Both Dependabot PRs superseded rather than merged separately
  • firebase-admin / firebase-tools not downgraded by npm audit fix (never ran with --force)
  • Wiki setup.md has a matching edit ready locally, uncommitted — the Node requirement text and an .nvmrc note. Say the word and I'll push it.

On the audit numbers

Root goes 14 moderate + 1 high → 13 moderate + 0 high; functions/ goes 8 → 7. The remainder is upstream-blocked: npm's only offered fix is downgrading firebase-tools to 10.1.1 or firebase-admin to 10.3.0.

Worth knowing that npm labels qs/express/body-parser as fixable at the root and that label is wrongexpress@4.22.2 is the latest 4.x and pins qs ~6.15.1 while the advisory needs >=6.16.0, and firebase-tools requires express ^4.16.4. npm audit fix correctly declines. The same three are genuinely fixable in functions/, whose express is 5.x, which is why qs moved there and not here.

🤖 Generated with Claude Code

amyjko and others added 2 commits September 3, 2026 17:14
Absorbs both open Dependabot PRs and clears the one high-severity
advisory in either tree.

Security (lockfile only):
- fast-uri 3.1.5 -> 3.1.7 (#1327), via ajv. The only high.
- re2 1.24.1 -> 1.26.1
- functions: qs 6.15.3 -> 6.16.0 (#1328)

In range, no range edits:
- @anthropic-ai/sdk 0.120.0 -> 0.123.0, in both workspaces together so
  the two copies cannot drift. 0.122.0 reshapes beta Files/Skills, which
  nothing here uses; all five call sites use messages.create and
  stop_reason only.
- zod 4.4.3 -> 4.5.4, svelte 5.56.10 -> 5.57.0,
  firebase-tools 15.28.1 -> 15.29.0, lint-staged 17.3.0 -> 17.4.1,
  tsx 4.23.12 -> 4.23.13, @wasm-audio-decoders/flac 0.2.10 -> 0.2.11
- functions: nodemailer 9.0.5 -> 9.1.1

vitest 5 needed no test changes. The config was already in its shape
(extends: true on both projects), and clearMocks defaulting to true is
inert here: every file that mocks either clears in beforeEach already,
rebuilds its mocks per test, or has no spies at all. It does surface a
config-loader warning on every run, so the two config imports now carry
file extensions.

picomatch is dropped: it was declared a runtime dependency with zero
import sites anywhere, and arrives transitively via vite regardless.

engines.node -> ^22.22.1, the strictest floor any dependency now imposes
(lint-staged 17.4.1), which also covers vitest 5's ^22.12.0.

TypeScript stays at 6.0.3. svelte-check 4.7.6 still declares
typescript ^5 || ^6 and ts-json-schema-generator depends on ^5.9.3, so
7.0.2 is only reachable behind svelte-check's experimental --tsgo with
both compilers installed. Revisit when svelte-check widens its range.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CI spelled Node three ways: 22 (playwright), 22.x (unit x5, translate),
and a hard 22.22.0 pin (deploy). All eight now read node-version-file
from a new .nvmrc.

The deploy pin worked around Node 22.23.0's http.Agent keep-alive change
breaking firebase-tools' OAuth, and its comment said to revert once
nodejs/node#64004 shipped. That landed in v22.23.1 on 2026-06-22
(22.23.2 followed on 2026-08-26), so the pin and its comment are both
removed rather than left to describe a workaround that no longer exists.
The pin had also gone from stale to wrong: lint-staged 17.4.1 requires
node >=22.22.1.

.nvmrc holds an exact version rather than a floating 22 on purpose. A
floating range is what let a bad Node release into the deploy job in the
first place; pinning makes a Node bump a reviewed commit, and gives
contributors an `nvm use` that matches CI.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@amyjko
amyjko marked this pull request as draft September 4, 2026 00:32
@amyjko

amyjko commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator Author

Marking this a draft — CI is red and I found the cause, but the fix isn't pushed yet.

Cause

All eight checks failed at npm ci, before running anything:

npm error `npm ci` can only install packages when your package.json and
package-lock.json or npm-shrinkwrap.json are in sync.
npm error Missing: picomatch@4.0.7 from lock file

This is a npm-version mismatch, not a dependency problem. My local npm is 11.12.0 (self-upgraded, independent of Node), while CI uses the npm bundled with Node10.9.8 in Node 22.23.2. The lockfile I generated under npm 11 computes a different ideal tree than npm 10 does, and npm 10's npm ci rejects it.

Verified both directions locally:

  • npm ci under npm 11.12.0 — succeeds
  • npx npm@10.9.8 ci --dry-runreproduces the exact CI error, same Missing: picomatch@4.0.7 line

Two false leads ruled out on the way: it isn't platform (npm ci --dry-run --os=linux --cpu=x64 passes), and it isn't a missing entry (regenerating with npm install --package-lock-only changes exactly one path, a stale node-gyp/undici).

Removing the unused picomatch dependency is what exposed it: with no root-level ^4 requirement, npm 11 hoists picomatch@2.3.2 to the root and nests 4.0.7 under its eight consumers, and npm 10 doesn't agree that lockfile satisfies the tree.

Fix, not yet applied

Regenerate the lockfile with npm 10.9.8 so it matches what CI resolves with, then re-verify with npx npm@10.9.8 ci --dry-run before pushing. If npm 10 also can't produce a stable tree without a root-level pin, the alternative is to keep picomatch — but as an overrides entry rather than a fake runtime dependency, since nothing imports it.

Worth deciding separately: this repo has no npm version floor, so any contributor on npm 11 can regenerate a lockfile that CI rejects. Pinning npm (via engines.npm or packageManager) would turn that into an error at install time instead of eight red checks.

Everything else on the branch was verified green before this surfaced — svelte-check 0/0, 10,901 unit tests on vitest 5, shuffled cold-cache run, locales, format, build with an unchanged chunk graph.

Every job failed at `npm ci`, before running anything:

  npm error `npm ci` can only install packages when your package.json
  and package-lock.json ... are in sync.
  npm error Missing: picomatch@4.0.7 from lock file

CI uses the npm bundled with Node — 10.9.8 in 22.23.2 — not whatever is
on a contributor's PATH. This lockfile was written by a local npm 11.12,
which resolves a different ideal tree, and npm 10 then refuses it.
Dropping the unused root picomatch is what exposed the difference: with
no root-level ^4 requirement, npm 11 hoists picomatch 2.3.2 to the root
and nests 4.0.7 under its consumers, and it omits one nesting that npm 10
requires.

Regenerated with `npx npm@10.9.8 install --package-lock-only`, which
keeps every resolved version and adds exactly one entry:
node_modules/svelte-check/node_modules/picomatch. Zero removals, zero
version changes, so nothing already verified drifted.

Note for next time: `npm ci` under npm 11 succeeds against a lockfile
npm 10 rejects, so a green local install proves nothing. Check with
`npx -y npm@10.9.8 ci --dry-run` before pushing a lockfile change.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@amyjko
amyjko marked this pull request as ready for review September 4, 2026 06:14
@amyjko
amyjko merged commit 861963b into main Sep 4, 2026
12 checks passed
@amyjko
amyjko deleted the dependency-updates branch September 7, 2026 19:34
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.

1 participant