import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; import { dirname, resolve } from "node:path"; import { fileURLToPath } from "node:url"; const projectRoot = resolve(dirname(fileURLToPath(import.meta.url)), ".."); const readProjectFile = (path) => readFileSync(resolve(projectRoot, path), "utf8"); const pinnedVersion = readProjectFile(".nvmrc").trim(); assert.match( pinnedVersion, /^\d+\.\d+\.\d+$/, ".nvmrc must pin an exact Node.js version", ); const major = Number.parseInt(pinnedVersion.split(".")[0], 10); const packageJson = JSON.parse(readProjectFile("package.json")); assert.equal( packageJson.engines?.node, `>=${pinnedVersion} <${major + 1}`, "package.json engines.node must match the .nvmrc release line", ); assert.equal( Number.parseInt(packageJson.devDependencies?.["@types/node"], 10), major, "@types/node must match the pinned Node.js major", ); const nodeImages = [ ...readProjectFile("Dockerfile").matchAll( /^FROM\s+(?:--platform=\S+\s+)?node:([^\s]+)\s*/gim, ), ].map((match) => match[1]); assert.ok( nodeImages.length > 0, "Dockerfile must declare a pinned Node.js base image", ); for (const image of nodeImages) { assert.equal( image, `${pinnedVersion}-alpine`, "every Docker Node.js stage must match .nvmrc", ); } if (!process.argv.includes("--static")) { assert.equal( process.versions.node, pinnedVersion, "the active Node.js runtime must match .nvmrc", ); } console.log(`Node.js toolchain is aligned on ${pinnedVersion}`);