From b212e92f9be972fae2093a323d76473918d09fcb Mon Sep 17 00:00:00 2001 From: Kaoru0822 Date: Sat, 10 Oct 2026 19:41:40 -0700 Subject: [PATCH] ci: select semantic tests and fixture lanes for their guarded inputs (#1675) Edits to `release.yml` or `real-ghidra-windows.yml` selected only the workflow lane, so the shards holding releaseWorkflow, releaseCheckpoint and realGhidraWindowsWorkflow tests were skipped. Actionlint checks syntax only, so a PR could drop the package-before-publish gate, the registry canary or the default-branch-only self-hosted runner restriction without CI noticing. Conformance fixture sources under tests/ set only the code lane, so the conformance-fixtures and reconstruction-readiness jobs, the only callers of `verify:fixtures` and `verify:readiness`, never ran for them. Route the directories that build-conformance-fixtures.mjs compiles to both lanes, and readiness applications to the readiness lane. Both were raised by the Codex review of #1660 after it merged. Co-authored-by: Claude Opus 5.5 --- scripts/ci/plan.mjs | 24 +++++++++++++++++++ .../boundary/filesystem/ciChangeScope.test.ts | 24 +++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/scripts/ci/plan.mjs b/scripts/ci/plan.mjs index 40ec03a6b3..46ee8d0393 100644 --- a/scripts/ci/plan.mjs +++ b/scripts/ci/plan.mjs @@ -14,6 +14,24 @@ const flags = [ "workflows", ...Object.keys(SCOPES), ]; +// Actionlint validates workflow syntax only. The semantic suite asserts these +// workflows' release, publication and self-hosted runner safeguards. +const GUARDED_WORKFLOWS = new Set([ + ".github/workflows/release.yml", + ".github/workflows/real-ghidra-windows.yml", +]); +// Sources compiled by build-conformance-fixtures.mjs. The readiness journey +// analyzes the built C fixture as well as its own applications. +const FIXTURE_SOURCES = [ + "tests/conformance/c/**", + "tests/conformance/napi/**", + "tests/conformance/objc/**", + "tests/conformance/swift/**", + "tests/conformance/versions/**", +]; +const READINESS_SOURCES = ["tests/conformance/readiness/**"]; +const matchesAny = (file, patterns) => + patterns.some((pattern) => matchesGlob(file, pattern)); const selected = Object.fromEntries(flags.map((flag) => [flag, false])); const reasons = []; const full = (reason) => { @@ -122,6 +140,7 @@ if ( file === ".github/actionlint.yaml" ) { selected.workflows = true; + if (GUARDED_WORKFLOWS.has(file)) selected.code = true; if (file !== ".github/workflows/ci.yml") continue; } if (owners.length === 1 && owners[0] === "website") continue; @@ -131,6 +150,11 @@ if ( continue; } selected.code = true; + if (matchesAny(file, FIXTURE_SOURCES)) { + selected.fixtures = true; + selected.readiness = true; + } + if (matchesAny(file, READINESS_SOURCES)) selected.readiness = true; if (file.startsWith("tests/")) continue; if ( /^(src\/process\/|src\/filesystem\/|src\/contracts\/tool|src\/server\/createServer|src\/cli\.ts|scripts\/ci\/)/.test( diff --git a/tests/boundary/filesystem/ciChangeScope.test.ts b/tests/boundary/filesystem/ciChangeScope.test.ts index b8924d34c0..9de12fcefd 100644 --- a/tests/boundary/filesystem/ciChangeScope.test.ts +++ b/tests/boundary/filesystem/ciChangeScope.test.ts @@ -368,6 +368,30 @@ it.each([ { code: true, docs: true, evm: true, package: false }, ], ["scripts/unknown-website-helper.mjs", { code: true, package: true }], + [ + ".github/workflows/release.yml", + { workflows: true, code: true, package: false, website: false }, + ], + [ + ".github/workflows/real-ghidra-windows.yml", + { workflows: true, code: true, package: false, website: false }, + ], + [ + "tests/conformance/c/fixture.c", + { code: true, fixtures: true, readiness: true, package: false }, + ], + [ + "tests/conformance/swift/fixture.swift", + { code: true, fixtures: true, readiness: true, package: false }, + ], + [ + "tests/conformance/readiness/javascript-cli/package.json", + { code: true, fixtures: false, readiness: true, package: false }, + ], + [ + "tests/conformance/ghidra/no-return.c", + { code: true, fixtures: false, readiness: false, package: false }, + ], ])("preserves scope boundaries for %s", async (path, expected) => { const { directory, base } = await fixture(); const head = await change(directory, [path]);