ci: give Node one source of truth, and move it to 26 - #346
Open
FrameAutomata wants to merge 1 commit into
Open
Conversation
Node's major was written out at ten sites with nothing asserting they
agree, and the two release-site values did not even name a major --
node-version: "latest" resolves to Node Current, which the runner tool
cache never ships, so every docs/website deploy re-downloaded a tarball.
.nvmrc now holds the pin and everything that can read it, does:
4x setup-node node-version: 22 | "latest" -> node-version-file
flake.nix engines.node regex -> .nvmrc
5 Dockerfiles node:22-* -> node:${NODE_VERSION}-*
release-traceway --build-arg NODE_VERSION read from .nvmrc,
passed to all five image builds
engines.node stays a floor (">=22") rather than becoming the pin. That
is what npm enforces on consumers, and it is also what f95424c was
fixing: node-version-file pointed at a range resolves to the newest
satisfying release, so ">=22" there silently meant "latest". Reading
.nvmrc gives the mechanism back without reintroducing that.
The Dockerfiles keep an ARG default because a bare `docker build` has no
way to read .nvmrc. That default is now the only value that can drift,
so scripts/check-node-pins.sh asserts it matches -- and also fails on a
literal node:<major> tag reintroduced in a FROM, which would ignore both
.nvmrc and the ARG. release-traceway.yml runs it before it builds.
The bump itself is 22 -> 26. Node is a build-time dependency everywhere
except the :browser image, which copies the binary into its runtime
stage to execute Playwright specs -- so that image is the one place the
major is load-bearing at runtime, and worth naming since Node 26 does
not reach LTS until October 2026. If you would rather ship the current
LTS, 24 is a one-line change to .nvmrc plus the five ARG defaults, and
the script tells you if you miss one.
Verified: frontend npm ci, build, test (25 passed) and check (0 errors)
all pass on nodejs 26.7.0; all four nix dev shells evaluate and hand out
v26.7.0; the check script passes and was confirmed to fail on both drift
shapes (a changed ARG default, a reintroduced literal tag).
Not verified: no container runtime here, so the five image builds were
not run. The ARGs are global (declared before the first FROM in every
file, confirmed) which is what makes them usable in FROM.
Closes #333.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
FrameAutomata
added a commit
that referenced
this pull request
Aug 28, 2026
This PR changed release-docs.yml and release-website.yml from node-version: "latest" to a literal 22, and documented "Node is pinned per site rather than read from one file" as the intended shape. #346 (closing #333) makes .nvmrc the single source of truth instead, so both are superseded: the two workflows now take node-version-file: .nvmrc, which fixes "latest" for the same reason and without adding a third and fourth hand-maintained literal. Dropping them here rather than reconciling them, since they touched the exact lines #346 does -- the two PRs would otherwise conflict, and this one is about Dependabot. What remains is the watcher and the docs recipe's node20 actions, which is what the PR was for. Refs #330, #333. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #333. You asked to lock it down and tighten it "to like 26" — this does both:
.nvmrcbecomes the single source of truth, and the pin moves 22 → 26.Before
Ten sites naming a Node major, nothing asserting they agree — and two of them not naming one at all:
release-traceway.ymlnode-version: 22benchmark-processor.ymlnode-version: 22release-docs.yml,release-website.ymlnode-version: "latest"Dockerfile,.minimal,.sqlite,.duckdb,.browser(×2)node:22-alpine/node:22-bookworm-slimflake.nixengines.node"latest"resolves to Node Current, which the runner tool cache never ships — so every docs and website deploy was re-downloading a Node tarball before it could start.After
engines.nodestays">=22". It is deliberately not the pin. That field is the floor npm enforces on consumers, and pointingnode-version-fileat it is exactly whatf95424ccwas fixing —node-version-fileresolves a range to the newest satisfying release, so">=22"silently meant "latest". Reading.nvmrcrestores the mechanismf95424cchad to abandon, without reintroducing the bug that made it abandon it.The Dockerfiles keep an
ARG NODE_VERSION=26default, because a baredocker buildhas no way to read.nvmrc. That default is now the only value in the repo that can drift — soscripts/check-node-pins.shasserts it matches, andrelease-traceway.ymlruns it before it builds anything. It also fails on a literalnode:<major>tag reintroduced into aFROM, which would ignore both.nvmrcand the ARG.I confirmed it actually catches both, rather than assuming:
One thing worth your call: 26 is not LTS until October
Node is a build-time dependency in every image except
:browser, which copies the node binary into its runtime stage to execute Playwright specs (Dockerfile.browser:80). So that image is the one place the major is load-bearing at runtime, and Node 26 reaches LTS in October 2026 — about five weeks out.I've shipped 26 as asked. If you'd rather be on the current LTS, 24 is a one-line change to
.nvmrcplus the five ARG defaults, and the check script tells you if you miss one. That is the point of the change more than the number is.Verification
npm ci/build/test/checkon nodejs 26.7.0v26.7.0scripts/check-node-pins.shnode-version:remainsNot verified: no container runtime available here, so the five image builds were not run. The
ARGs are global — declared before the firstFROMin every file, which I checked mechanically — which is what makes them usable in aFROM.Out of scope, deliberately
testing/devtesting-nestjs/Dockerfilestays onnode:20-alpine. The issue names it as existing drift, but it pins the runtime of a sample third-party app rather than anything Traceway builds; coupling it to our frontend's pin would be wrong. (It is on an EOL major, which is its own question.)docs/pages/client/js-sdk/sourcemap-upload.mdxkeeps a literal — it is a copy-pasteable recipe for readers who have no.nvmrc.frontend.ymlusesnode-version-file: frontend/package.json, which has the resolve-to-latest behaviour described above. Different file, so no conflict either way; whichever of the two lands second should switch it to.nvmrc. I'll do that on ci: test the frontend on every labelled PR #315 if this goes first.🤖 Generated with Claude Code