Raised while reviewing #332 (closes #330). Not folded into that PR, because resolving it means reversing a deliberate decision made in f95424cc and that is a maintainer's call.
What happened
f95424cc ("node version fixes") did three linked things:
frontend/package.json: engines.node "22.x" → ">=22"
release-traceway.yml: deleted node-version-file: frontend/package.json, replaced with a literal node-version: 22
flake.nix:29: patched the regex from ([0-9]+).* to [^0-9]*([0-9]+).* so it survives the leading >=
The causal chain is sound and the comment left behind states it plainly: setup-node's node-version-file reads engines.node and resolves it as a semver range to the newest satisfying release. "22.x" pinned the major; ">=22" silently means latest. Loosening the floor broke the pin, and the fix taken was to drop the mechanism and hardcode.
#332 then followed that precedent at two more sites (release-docs.yml, release-website.yml, both previously node-version: "latest").
Why it's worth revisiting
Node's major is now named literally in six places with nothing asserting they agree:
| site |
value |
.github/workflows/release-traceway.yml:67 |
22 |
.github/workflows/release-docs.yml |
22 |
.github/workflows/release-website.yml |
22 |
.github/workflows/benchmark-processor.yml:88 |
22 |
Dockerfile, Dockerfile.minimal, Dockerfile.sqlite, Dockerfile.duckdb, Dockerfile.browser:18 |
node:22-alpine |
Dockerfile.browser:57 |
node:22-bookworm-slim |
Compare the Go convention in the same repo: 14 of 15 Go version references use go-version-file: against a go.mod. Only benchmark-hardware.yml:154 hardcodes. Node is the outlier.
This is also the pin-drift shape #330 was about. testing/devtesting-nestjs/Dockerfile is already on node:20-alpine — drift that exists today and that nothing reports.
Option worth considering
A root .nvmrc containing 22, with node-version-file: .nvmrc at all four setup-node sites. node-version-file and cache-dependency-path are independent inputs, so the existing cache-dependency-path: docs/package-lock.json etc. are unaffected.
engines.node: ">=22" then stays what >= is actually for — the npm-enforced floor — while .nvmrc carries the pin. flake.nix could read .nvmrc directly and the regex workaround from f95424cc deletes itself.
Two things this deliberately would not fix: the Dockerfiles (Docker can't read .nvmrc without ARG plumbing from the caller, five files plus a consistency check — genuinely separate), and docs/pages/client/js-sdk/sourcemap-upload.mdx:93, which should stay a literal since it is a copy-pasteable recipe for readers who have no .nvmrc.
Worth deciding either way: if hardcoding is the intended long-term shape, that is fine, but then the six sites want something that notices when they disagree — which is the same gap #330 opened.
Raised while reviewing #332 (closes #330). Not folded into that PR, because resolving it means reversing a deliberate decision made in
f95424ccand that is a maintainer's call.What happened
f95424cc("node version fixes") did three linked things:frontend/package.json:engines.node"22.x"→">=22"release-traceway.yml: deletednode-version-file: frontend/package.json, replaced with a literalnode-version: 22flake.nix:29: patched the regex from([0-9]+).*to[^0-9]*([0-9]+).*so it survives the leading>=The causal chain is sound and the comment left behind states it plainly:
setup-node'snode-version-filereadsengines.nodeand resolves it as a semver range to the newest satisfying release."22.x"pinned the major;">=22"silently means latest. Loosening the floor broke the pin, and the fix taken was to drop the mechanism and hardcode.#332 then followed that precedent at two more sites (
release-docs.yml,release-website.yml, both previouslynode-version: "latest").Why it's worth revisiting
Node's major is now named literally in six places with nothing asserting they agree:
.github/workflows/release-traceway.yml:6722.github/workflows/release-docs.yml22.github/workflows/release-website.yml22.github/workflows/benchmark-processor.yml:8822Dockerfile,Dockerfile.minimal,Dockerfile.sqlite,Dockerfile.duckdb,Dockerfile.browser:18node:22-alpineDockerfile.browser:57node:22-bookworm-slimCompare the Go convention in the same repo: 14 of 15 Go version references use
go-version-file:against ago.mod. Onlybenchmark-hardware.yml:154hardcodes. Node is the outlier.This is also the pin-drift shape #330 was about.
testing/devtesting-nestjs/Dockerfileis already onnode:20-alpine— drift that exists today and that nothing reports.Option worth considering
A root
.nvmrccontaining22, withnode-version-file: .nvmrcat all foursetup-nodesites.node-version-fileandcache-dependency-pathare independent inputs, so the existingcache-dependency-path: docs/package-lock.jsonetc. are unaffected.engines.node: ">=22"then stays what>=is actually for — the npm-enforced floor — while.nvmrccarries the pin.flake.nixcould read.nvmrcdirectly and the regex workaround fromf95424ccdeletes itself.Two things this deliberately would not fix: the Dockerfiles (Docker can't read
.nvmrcwithoutARGplumbing from the caller, five files plus a consistency check — genuinely separate), anddocs/pages/client/js-sdk/sourcemap-upload.mdx:93, which should stay a literal since it is a copy-pasteable recipe for readers who have no.nvmrc.Worth deciding either way: if hardcoding is the intended long-term shape, that is fine, but then the six sites want something that notices when they disagree — which is the same gap #330 opened.