chore(node): adopt runtime-parity Node versioning, devcontainer, and docs - #510
Conversation
…docs Pin every Node reference to the GitHub Actions runtime major (24) — the only non-deprecated JS action runtime (Node 20 was default-migrated 2026-06-16; no node26 runtime exists or is announced). .node-version, the devcontainer, CI, engines.node, and @types/node now share one major, moving together only when GitHub ships a new runtime. - Downgrade @types/node to ^24 so post-runtime APIs fail typecheck; the codebase already passes clean on Node 24 types - Ignore @types/node semver-major in dependabot; minors/patches flow - Rebase devcontainer on javascript-node:24-trixie (Node baked in, node feature removed) and add an npm cache volume + npm ci --prefer-offline - Add __tests__/devcontainer.test.ts enforcing strict version parity across runs.using/engines/@types/node/.node-version/devcontainer image and banning the node feature (nvm PATH-shadowing hazard) - Add docs/node.md as the canonical policy doc (runner execution model, guards, runtime timeline, GHES 3.16+ / runner 2.327.1+ requirements); rewrite the node-versioning skill as a protocol layered on it - Fix drift: CONTRIBUTING Node prerequisite, development.md compile target ECMAScript 2022→2024, README GHES runner requirement
…alls The real-system installation suite downloads the terraform-docs binary from the live CDN; network latency intermittently blows the default 5s timeout. Give the suite 10s per attempt and up to 2 retries, covering both CDN-dependent tests. Unit tests keep the fast global default.
There was a problem hiding this comment.
Pull request overview
Adopts a runtime-parity Node.js versioning policy for this GitHub Action so that local development, CI, type-checking, and the GitHub Actions runtime all target the same Node major (Node 24), reducing the risk of shipping code that breaks on runners.
Changes:
- Pins Node references to 24 (engine floor,
.node-version, devcontainer image,@types/node) and documents the policy. - Adds a guard test to enforce version alignment and bans the devcontainers Node feature that can shadow the image’s Node.
- Reduces flakiness in the real terraform-docs install test suite via higher timeout + retries.
Reviewed changes
Copilot reviewed 16 out of 17 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| README.md | Updates GHES minimums to reflect the node24 runtime requirement. |
| package.json | Pins @types/node to the Node 24 major and keeps engines.node at >=24. |
| package-lock.json | Updates lockfile for @types/node@^24 and related transitive changes (undici-types). |
| docs/node.md | Adds canonical Node runtime-parity policy documentation and upgrade protocol references. |
| docs/development.md | Aligns dev docs with the Node 24 devcontainer and parity policy. |
| CONTRIBUTING.md | Updates contributor prerequisites to Node 24 by policy. |
| CLAUDE.md | Updates repository agent guidance to the Node 24 parity policy and points to docs/node.md. |
| .node-version | Pins local/CI Node to major 24. |
| .github/dependabot.yml | Adds ignore rule intended to block @types/node major bumps (runtime-coupled). |
| .devcontainer/postCreateCommand.bash | Updates post-create to npm ci with offline-friendly settings and fixes volume ownership. |
| .devcontainer/devcontainer.json | Switches to javascript-node:24-trixie, adds npm cache volume, removes Node feature, sets remoteUser. |
| .devcontainer/devcontainer-lock.json | Removes the devcontainers Node feature lock entry. |
| .claude/skills/node-versioning/SKILL.md | Updates the node-versioning skill to defer to docs/node.md and reflect parity rules. |
| .claude/skills/node-versioning/references/runtime-boundary.md | Removes redundant reference doc (superseded by docs/node.md). |
| .claude/skills/action-inputs/SKILL.md | Adjusts checklist formatting (ordered-list marker style). |
| tests/terraform-docs.test.ts | Makes real-CDN terraform-docs install tests less flaky (timeout + retry). |
| tests/devcontainer.test.ts | Adds a guard suite validating Node version alignment + banning devcontainer Node feature. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…t update-type Address Copilot review: assert .node-version is a bare major (a pinned 24.0.0 would freeze patch floats yet still pass the parity check), and quote the dependabot update-types entry. The unquoted form already parsed as a plain scalar string (verified with js-yaml), so the ignore was effective as written — quoting just matches GitHub's documented style.
📋 Release Plan
📝 Changelog
|
|
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 16 out of 17 changed files in this pull request and generated no new comments.
Suppressed comments (2)
docs/development.md:24
- This sentence implies any Node version satisfying
engines.nodeis equally acceptable for development, which conflicts with the parity policy described in docs/node.md (develop/test on the same major as the Actions runtime). Consider clarifying that newer Node versions may work but are not the supported setup.
1. Install the Node.js version pinned in `.node-version`; anything satisfying `engines.node` also works (see
[node.md](node.md) for the version policy)
tests/devcontainer.test.ts:48
runtimeMajoris computed fromactionYml.runs.usingat module load time. Ifaction.ymlis malformed oryaml.load()returns an unexpected shape, this can throw before Vitest runs any assertions, producing a less-informative failure. Extractruns.usingdefensively (defaulting to an empty string) and assert on that value instead.
const runtimeMajor = Number(/^node(\d+)$/.exec(actionYml.runs.using)?.[1]);



Summary
Adopts a runtime-parity Node policy: every Node reference —
.node-version, the devcontainer image, CI,engines.node, and@types/node— now pins to the GitHub Actions runtime major (24), the only non-deprecatedJS action runtime (Node 20 was default-migrated on 2026-06-16; no
node26runtime exists or is announced). What wedevelop and test on is exactly what consumers' runners execute. The whole set moves together, as a breaking major
release, only when GitHub ships a new runtime (likely
node28, ~2028).What Changed
@types/node^26→^24— post-runtime APIs now failnpm run typecheck; the codebase already passesclean. Surgical lockfile diff (types +
undici-typesonly).@types/nodesemver-majors; minors/patches keep flowing weekly.javascript-node:24-trixie(Node baked into the image; thenodefeature isremoved and banned — it silently shadows the image's Node via nvm PATH order). Added an npm cache volume; postCreate
now runs
npm ci --no-fund --no-audit --prefer-offlinefor fast rebuilds.__tests__/devcontainer.test.ts) — 6 assertions enforcing strict version parity acrossruns.using↔engines↔@types/node↔.node-version↔ devcontainer image, and banning the node feature.docs/node.md) — how runners execute JS actions, the failure modes parity prevents, thefive guards, August-2026 runtime facts (node20→24 timeline, release lines, GHES 3.16+/runner 2.327.1+), and the
single upgrade path. The
node-versioningskill is now a lean protocol layered on it.timeout: 10s, retry: 2(unit tests keep thefast 5s global default).
docs/development.mdcompile target (ECMAScript 2022 → 2024),README GHES runner requirement, ordered-list style per markdownlint config.
Validation
tsc --noEmitclean under Node 24 types.node-versionfailsexactly the parity assertions; restoring returns green)
javascript-node:24-trixieconfirmed on MCR;@types/node@24.13.3confirmed newest in the ^24 linesrc/changes —dist/untouchedRisks / Notes
image rebuild; subsequent rebuilds are faster via the npm cache volume.
@types/nodemajor bumps — by design; the major moves only with the runtime.dist/under the production runtime line — a parity win with no output change expected.