From 38b7403dfb600a195a613b15035e82d62a956855 Mon Sep 17 00:00:00 2001 From: quality Date: Thu, 8 Oct 2026 01:45:17 -0400 Subject: [PATCH] test(dev-environment): pin package.json engines.node into the Node-major parity chain The repository pins Node 22 in the devcontainer, in every workflow and in CONTRIBUTING.md, and tests/dev-environment.test.mjs already guards the agreement between those three. package.json declared no engines field, so the one Node pin npm itself reads was absent: a contributor who clones outside the devcontainer got no signal at all, and `npm ci` endorsed whatever major was installed. Add "engines": { "node": "22.x" } and a parity test beside the two existing ones, reusing devcontainerNodeMajor(), so a future bump that misses the field fails the suite instead of leaving npm silently permissive. The field is advisory: the repository ships no .npmrc with engine-strict, so this warns on a mismatched major without failing anyone's install. Closes #1182 Signed-off-by: quality --- package.json | 3 +++ tests/dev-environment.test.mjs | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/package.json b/package.json index 500fe921..5dc33e4f 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,9 @@ "name": "endusers", "version": "0.9.0", "description": "Community resources for CNCF end users.", + "engines": { + "node": "22.x" + }, "scripts": { "_build": "npm run docus:build", "_check:format:any": "npx prettier --check --ignore-path ''", diff --git a/tests/dev-environment.test.mjs b/tests/dev-environment.test.mjs index 37b2ea7a..f7869dbd 100644 --- a/tests/dev-environment.test.mjs +++ b/tests/dev-environment.test.mjs @@ -380,6 +380,27 @@ test('devcontainer Node major matches the Node major every workflow pins', () => ); }); +// package.json's engines field is the only Node pin npm itself reads. The +// devcontainer, the workflows and CONTRIBUTING.md all have to be opened to be +// seen, so a contributor who clones outside the devcontainer gets no signal at +// all: `npm ci` endorses whatever major is installed. Pinning the field here +// puts it in the same parity chain as the two assertions above, so a Node bump +// that misses it fails the suite rather than leaving npm silently permissive. +test('package.json engines.node matches the pinned Node major', () => { + const devcontainerMajor = devcontainerNodeMajor(); + const engines = packageJson.engines?.node; + assert.ok( + engines, + 'package.json declares no engines.node; npm has no Node pin to enforce', + ); + const major = String(engines).match(/\d+/)?.[0]; + assert.equal( + major, + devcontainerMajor, + `package.json engines.node (${engines}) pins a different Node major than the devcontainer (${devcontainerMajor})`, + ); +}); + // CONTRIBUTING.md tells a contributor which Node to install. If that drifts // below the major CI and the devcontainer run on, the documented setup is one // a maintainer never reproduces.