chore(scripts): make the browser rule kind-aware, cover container.env, pin the name (#2146)

Copilot, fifth review:

- The SMOKE_BROWSER rule was a blanket text match across every region, so a
  script that merely PRINTS the variable — `echo "SMOKE_BROWSER: firefox"` —
  or a `with:` input mentioning it was reported as an override. It is
  kind-aware now: an `env:` entry counts only when SMOKE_BROWSER is literally
  its key (recognized structurally, not by regex), a `run:` script only on a
  shell assignment, and a `with:` value not at all — whatever it names is
  already covered by the script rules. A shell assignment inside an `echo` is
  indistinguishable without parsing the shell, and inside `run:` erring toward
  the finding is the safe direction; that is stated in the header.

- `jobs.<id>.container.env` is job-wide too — every step in the container sees
  it — so an override there redirected `npm run smoke` with the guard silent.
  Now traversed, and a `container:` given as a bare image string is ignored
  rather than tripping over.

- Nothing asserted the FIRST acceptance criterion: reintroducing a `ci` or
  `ci:*` root script left test:scripts green. Asserted directly over the
  manifest's keys now, and checked to actually bite by reviving `ci` and
  watching the suite fail.

Signed-off-by: Cliff Hall <cliff@futurescale.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
cliffhall 2026-08-27 01:25:51 -04:00
commit 6d2806de75

View file

@ -188,6 +188,52 @@ describe("findWorkflowViolations", () => {
].join("\n"),
rules: [VIOLATION.BROWSER_ENV],
},
{
// Copilot, fifth review: `container.env` is job-wide too — every step in
// the container sees it, so it redirects `npm run smoke` exactly as a
// job-level `env` would.
name: "flags a SMOKE_BROWSER override under container.env",
text: [
"on: push",
"jobs:",
" build:",
" container:",
" image: node:22",
" env:",
" SMOKE_BROWSER: firefox",
" steps:",
" - run: npm run smoke",
].join("\n"),
rules: [VIOLATION.BROWSER_ENV],
},
{
name: "does not trip over a container given as a bare image string",
text: [
"on: push",
"jobs:",
" build:",
" container: node:22",
" steps:",
" - run: npm run smoke",
].join("\n"),
rules: [],
},
{
// Copilot, fifth review: a blanket text match rejected a script that
// merely PRINTS the variable name, which sets nothing.
name: "does not read a script printing the variable as setting it",
text: workflow(
' - run: |\n echo "SMOKE_BROWSER: firefox"\n npm run smoke',
),
rules: [],
},
{
name: "does not read an action input mentioning it as setting it",
text: workflow(
' - with:\n message: "SMOKE_BROWSER: firefox"',
),
rules: [],
},
{
name: "allows SMOKE_BROWSER set explicitly to chromium",
text: workflow(
@ -334,6 +380,32 @@ describe("findWorkflowViolations", () => {
});
});
describe("the gate's name", () => {
const scripts = JSON.parse(
readFileSync(join(repoRoot, "package.json"), "utf8"),
).scripts;
it("is `local:gate`, and runs the local-only Storybook step", () => {
assert.ok(scripts["local:gate"], "the pre-push gate must exist");
assert.match(scripts["local:gate"], /local:storybook/);
});
it("has no `ci` alias, not even a deprecated one", () => {
// The rename is only worth anything if the old name is GONE (#2146): an
// alias preserves exactly the association being scrubbed, and leaves
// something copy-pasteable for a workflow author. Nothing else notices a
// reintroduced `ci`, so assert it here (Copilot).
const revived = Object.keys(scripts).filter(
(name) => name === "ci" || name.startsWith("ci:"),
);
assert.deepEqual(
revived,
[],
`no root script may be named \`ci\` or \`ci:*\` — found ${revived.join(", ")}`,
);
});
});
describe("extractExecutableRegions", () => {
it("descends the executable paths and skips the metadata beside them", () => {
const regions = extractExecutableRegions(