Skip to content

chore: raise minimum supported Node to 22 and test 24 and 26 - #383

Merged
sametcelikbicak merged 1 commit into
mainfrom
chore/node-22-minimum
Oct 1, 2026
Merged

sametcelikbicak merged 1 commit into
mainfrom
chore/node-22-minimum

Conversation

@sametcelikbicak

Copy link
Copy Markdown
Member

Follow-up to #376, which had to drop the Node 20 job because its test runner flakes on macOS. That fix left a gap: engines and the docs still claimed Node 20 support while CI no longer tested it.

The floor moves to 22

  • Node 20 is EOL (2026-04-30) and its test runner has an unfixed deserialization bug (nodejs/node#64061, fixed in v24.20.0 by #64706). No 20.x release will ever carry it.
  • Node 22 is supported until 2027-04-30, so it becomes the oldest line we test.
  • The fix is already merged to v22.x-staging (#65807), so the one remaining known flake in the matrix should clear on its own.

Why test 26 as well as 22 and 24

Line Status Why in the matrix
22 LTS, EOL 2027-04-30 the floor — catches anything that breaks on the oldest thing we claim to support
24 active LTS, maintenance opens 2026-10-20 the line most installs are on; stays the reference version for audit/coverage/lint
26 Current, LTS on 2026-10-28 what nvm install node gives today

26 becomes the recommended LTS in under a month. Testing it now is how breakage gets found before that happens rather than after. It also already carries the deserialization fix (landed in 26.7.0), so it adds no flake risk.

The floor is defined once

src/api/doctor.js read the minimum from two literals on adjacent lines — the same drift security.js had before #374. It now derives it from package.json:

const MIN_NODE_MAJOR = Number.parseInt(
  (pkg.engines?.node ?? '>=20').replace(/[^\d]/g, ''),
  10,
)

pkg was already loaded from package.json at that point, so this adds no file read and no new constant. npm's install-time enforcement and rolecraft doctor now agree by construction rather than by convention.

Regression test

doctor had no coverage for the floor at all — only a test asserting it reports the current version. Added one that stubs process.versions.node to one below the floor and to the floor itself:

  • below → reports >= 22 required
  • at the floor → no compatibility error

Verified it fails when the comparison is broken (major < MIN_NODE_MAJOR → major < 0).

The test reads the floor from package.json rather than hardcoding 22, deliberately: it pins the agreement between npm and doctor, which is the thing that can silently break. Pinning the literal would just create a second place to update when the floor moves again.

Updated

  • .github/workflows/test.yml — matrix [22, 24, 26], with the Node 20 removal reason and each line's role recorded next to it
  • package.json — engines.node: ">=22"
  • .nvmrc — v20 → v22
  • README.md, CONTRIBUTING.md, docs/install.md, docs/guides/getting-started.md — requirements
  • docs/guides/ci.md — the copy-paste CI example pinned node-version: 20, which would have handed users a version this repo no longer supports
  • docs/commands/doctor.md — documents the check, which now enforces 22
  • MANIFEST-MATRIX.md + generated tokens — test_count 1168 → 1169

1269/1269 pass, lint clean.

Follow-up worth noting

When 26 goes LTS on 2026-10-28 and 24 enters maintenance on 2026-10-20, the reference version for the audit/coverage/lint jobs (matrix.node-version == 24) should probably move to 26. Left alone here to keep this PR to the floor change — worth doing once 26 is actually LTS, not before.

@sametcelikbicak
sametcelikbicak merged commit adf49ca into main Oct 1, 2026
9 checks passed
@sametcelikbicak
sametcelikbicak deleted the chore/node-22-minimum branch October 1, 2026 08:08
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