Skip to content

Commit ec1bfeb

Browse files
committed
Require Node.js 22.11 or newer
1 parent 3abf30a commit ec1bfeb

11 files changed

Lines changed: 53 additions & 15 deletions

File tree

‎.github/workflows/ci.yml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ jobs:
107107
--redact --no-banner --config .gitleaks.toml .
108108
109109
npm-install:
110-
name: npm install (${{ matrix.os }}, Node 22.0.0)
110+
name: npm install (${{ matrix.os }}, Node 22.11.0)
111111
strategy:
112112
fail-fast: false
113113
matrix:
@@ -118,7 +118,7 @@ jobs:
118118
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
119119
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
120120
with:
121-
node-version: "22.0.0"
121+
node-version: "22.11.0"
122122
cache: npm
123123
- run: npm ci
124124
- run: npm run build

‎.github/workflows/npm-release.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ jobs:
6767
ref: ${{ github.event.release.tag_name }}
6868
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
6969
with:
70-
node-version: "22.0.0"
70+
node-version: "22.11.0"
7171
package-manager-cache: false
7272
- name: Install and execute the exact npm release
7373
run: node scripts/check-npm-install.mjs --spec "screenrig@${{ needs.publish.outputs.version }}"

‎AGENTS.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ notes and examples live in `src/cli-commands/guidance.ts`.
8585

8686
## Product and security boundaries
8787

88-
- Package metadata requires Node.js 22 or newer.
88+
- Package metadata requires Node.js 22.11 or newer.
8989
- `agent enroll --email ADDRESS` is the explicit first-agent step. Other
9090
authenticated commands do not enroll as a side effect; they fail with
9191
`not_enrolled` (exit 3). Keep that code stable.

‎README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ npm install --global screenrig@<YY.MM.SERIAL>
2626
screenrig version
2727
```
2828

29-
Node.js 22 or newer is required. `media upload` additionally requires ffmpeg
29+
Node.js 22.11 or newer is required. `media upload` additionally requires ffmpeg
3030
and ffprobe, as do batch uploads and playlist preparation from local media files. Run `screenrig doctor` to inspect
3131
the optional media toolchain before an upload.
3232

‎RELEASING.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ fetch.
5555
and attach the offline archive. It rejects a tag that is not `vYY.MM.N`.
5656
5. Require all Linux, macOS, and Windows clean-install jobs to pass. Each installs
5757
the exact registry version and runs `screenrig --json version` plus
58-
`screenrig --json compose catalog` on Node 22.0.0.
58+
`screenrig --json compose catalog` on Node 22.11.0.
5959
6. Confirm the workflow attached `screenrig-cli.tgz` and its SHA-256 file to the
6060
same GitHub release.
6161
7. Verify the npm package page shows provenance before announcing availability.

‎package-lock.json‎

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
"!dist/transport/fake.d.ts.map"
5555
],
5656
"engines": {
57-
"node": ">=22"
57+
"node": ">=22.11"
5858
},
5959
"packageManager": "npm@10.9.4",
6060
"scripts": {

‎scripts/check-npm-install.mjs‎

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,18 @@ import { PLACEHOLDER_VERSION, isReleaseVersion, resolvePackVersion, versionFromT
99

1010
const root = fileURLToPath(new URL("..", import.meta.url));
1111
const packageJson = JSON.parse(await readFile(path.join(root, "package.json"), "utf8"));
12-
const npm = process.platform === "win32" ? "npm.cmd" : "npm";
12+
// Windows command shims cannot be spawned without a shell. Invoke npm's JS
13+
// entry point with this Node runtime so paths and arguments need no shell quoting.
14+
const npm = process.platform === "win32" ? process.execPath : "npm";
15+
const npmArgs = process.platform === "win32"
16+
? [process.env.npm_execpath || path.join(path.dirname(process.execPath), "node_modules", "npm", "bin", "npm-cli.js")]
17+
: [];
1318

1419
function run(args, options = {}) {
15-
const result = spawnSync(npm, args, { encoding: "utf8", ...options });
20+
const result = spawnSync(npm, [...npmArgs, ...args], { encoding: "utf8", ...options });
21+
if (result.error) throw result.error;
1622
if (result.status !== 0) {
17-
throw new Error(`${npm} ${args.join(" ")}: ${result.stderr.trim() || result.stdout.trim()}`);
23+
throw new Error(`npm ${args.join(" ")}: ${result.stderr?.trim() || result.stdout?.trim() || `exit ${result.status}`}`);
1824
}
1925
return result;
2026
}

‎scripts/check-public-repo.py‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ def check_metadata(errors: list[str]) -> None:
4949
"version": PLACEHOLDER_VERSION,
5050
"private": False,
5151
"license": "Apache-2.0",
52+
"engines": {"node": ">=22.11"},
5253
}
5354
for field, value in expected.items():
5455
if package.get(field) != value:
@@ -81,7 +82,7 @@ def check_metadata(errors: list[str]) -> None:
8182
errors.append("commands.ts must not freeze CLI_VERSION to the committed placeholder")
8283

8384
root_lock = (lock.get("packages") or {}).get("") or {}
84-
for field in ("name", "version", "license"):
85+
for field in ("name", "version", "license", "engines"):
8586
if root_lock.get(field) != package.get(field):
8687
errors.append(f"package-lock.json root {field!r} drifts from package.json")
8788

@@ -101,7 +102,8 @@ def check_public_tree(errors: list[str]) -> None:
101102
"npm run check",
102103
"npm audit --audit-level=high --package-lock-only",
103104
"name: screenrig-cli",
104-
"name: npm install (${{ matrix.os }}, Node 22.0.0)",
105+
"name: npm install (${{ matrix.os }}, Node 22.11.0)",
106+
'node-version: "22.11.0"',
105107
"os: [ubuntu-24.04, macos-14, windows-2022]",
106108
"npm run check:npm-install",
107109
"gitleaks\" git",
@@ -144,6 +146,7 @@ def check_public_tree(errors: list[str]) -> None:
144146
"npm publish --access public",
145147
"screenrig@${{ needs.publish.outputs.version }}",
146148
"ubuntu-24.04, macos-14, windows-2022",
149+
'node-version: "22.11.0"',
147150
"gh release upload",
148151
):
149152
if fact not in npm_release:

‎src/cli.test.ts‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2604,6 +2604,35 @@ test("events follow --timeout exits during backoff without hanging", async () =>
26042604
await rm(configDir, { recursive: true, force: true });
26052605
});
26062606

2607+
test("doctor requires Node.js 22.11 or newer", async () => {
2608+
const descriptor = Object.getOwnPropertyDescriptor(process.versions, "node")!;
2609+
try {
2610+
for (const [version, status] of [
2611+
["20.19.0", "fail"],
2612+
["22.0.0", "fail"],
2613+
["22.10.0", "fail"],
2614+
["22.11.0", "pass"],
2615+
["22.11.1", "pass"],
2616+
["22.12.0", "pass"],
2617+
["23.0.0", "pass"],
2618+
["24.0.0", "pass"],
2619+
]) {
2620+
Object.defineProperty(process.versions, "node", { ...descriptor, value: version });
2621+
resetFfmpegToolchainCache();
2622+
const { code, stdout, configDir } = await withRuntime(["--json", "doctor"], memoryBackend(), { runProcess: fullToolchainProbe() });
2623+
try {
2624+
const envelope = JSON.parse(stdout) as { data: { checks: Array<{ name: string; status: string }> } };
2625+
assert.equal(envelope.data.checks.find((check) => check.name === "node")?.status, status, version);
2626+
assert.equal(code === ExitCode.Success, status === "pass", version);
2627+
} finally {
2628+
await rm(configDir, { recursive: true, force: true });
2629+
}
2630+
}
2631+
} finally {
2632+
Object.defineProperty(process.versions, "node", descriptor);
2633+
}
2634+
});
2635+
26072636
test("doctor reports checks over the published foundation routes", async () => {
26082637
resetFfmpegToolchainCache();
26092638
const transport = memoryBackend();

0 commit comments

Comments
 (0)