inspector/scripts/run-engine-smokes.mjs
cliffhall 7501dad675 ci: put the Firefox smokes in the pre-push gate instead of GitHub CI
Dropping the CI job left cross-engine checking as something you had to
remember to run, which in practice means nobody runs it. This moves it
into npm run ci, so it happens once per push, in front of a human who can
still reason about the change -- rather than once per CI run, on every
branch, to re-derive an answer we already had.

scripts/run-engine-smokes.mjs is what makes that possible cross-platform:
SMOKE_BROWSER has to reach three child processes, and a POSIX VAR=x npm
run prefix does not work under Windows cmd.exe, which npm uses there.
Setting it in the child env from Node does. smoke:web:firefox passes the
engine as an ARGUMENT rather than relying on the ambient variable, so a
stray SMOKE_BROWSER cannot silently redirect the gate to another engine
-- verified: an explicit argument beats it.

It also gives the smoke list one home. It was previously an && chain in
package.json beside a second chain in the workflow, so adding a fourth
smoke meant remembering both. ENGINE_SMOKES is now the list, with a test
pinning its contents and its order -- a smoke going missing is invisible
at runtime, because a shorter list is still a passing run.

Firefox only. WebKit fails the App smokes for unidentified reasons and
must not be in a gate.

This makes npm run ci a strict superset of GitHub CI rather than a mirror.
That was already true of smoke:tui, which self-skips on CI; Firefox is the
second such step. The direction that matters still holds: passing
npm run ci locally means CI's gates will pass.

Signed-off-by: cliffhall <cliff@futurescale.com>
2026-08-26 00:12:55 -04:00

83 lines
2.9 KiB
JavaScript

#!/usr/bin/env node
/**
* Run the three headless web smokes in one browser engine (#2086).
*
* `SMOKE_BROWSER=firefox npm run smoke:web:engine` needs the variable to reach
* three child processes, and a POSIX `VAR=x npm run …` prefix does not work
* under Windows' `cmd.exe`, which npm uses there. Setting it in the child env
* from Node does, on every platform — the same reason `install-smoke-browser`
* exists rather than an inline shell expansion.
*
* It also gives the smoke list ONE home. It used to be an `&&` chain in
* package.json alongside a second chain in the workflow; adding a fourth smoke
* meant remembering both. Now `ENGINE_SMOKES` is the list, and both the
* on-demand command and the pre-push gate run through it.
*
* Usage: `node scripts/run-engine-smokes.mjs [engine]`. With no argument the
* engine comes from `SMOKE_BROWSER` (default `chromium`).
*/
import { spawnSync } from "node:child_process";
import { join, resolve } from "node:path";
import { pathToFileURL } from "node:url";
import { resolveRequestedBrowser } from "./install-smoke-browser.mjs";
/**
* The smokes that are engine-sensitive, in run order.
*
* Cheapest first, so a bundle that cannot even boot on the engine fails in
* seconds rather than after two full App flows have timed out.
*/
export const ENGINE_SMOKES = [
"smoke-web-browser.mjs",
"smoke-web-app.mjs",
"smoke-web-elicitation.mjs",
];
function main() {
const scriptDir = resolve(import.meta.dirname);
let browserName;
try {
browserName = resolveRequestedBrowser(process.argv.slice(2), process.env);
} catch (err) {
console.error(
`run-engine-smokes: ${err instanceof Error ? err.message : String(err)}`,
);
process.exit(1);
}
// Children inherit this rather than reading the ambient variable, so an
// explicit argument wins over SMOKE_BROWSER all the way down.
const env = { ...process.env, SMOKE_BROWSER: browserName };
const install = spawnSync(
process.execPath,
[join(scriptDir, "install-smoke-browser.mjs"), browserName],
{ stdio: "inherit", env },
);
if (install.status !== 0) process.exit(install.status ?? 1);
for (const smoke of ENGINE_SMOKES) {
const result = spawnSync(process.execPath, [join(scriptDir, smoke)], {
stdio: "inherit",
env,
});
if (result.error) {
console.error(
`run-engine-smokes: could not run ${smoke}: ${result.error.message}`,
);
process.exit(1);
}
if (result.status !== 0) {
// The smoke has already printed its own diagnosis; add only the engine,
// so a failure in the pre-push gate names which run it came from.
console.error(`run-engine-smokes: ${smoke} failed under ${browserName}`);
process.exit(result.status ?? 1);
}
}
}
// Only when run as a script, never on import — see install-smoke-browser.mjs.
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href)
main();