FN-7105: add CI print-mode regression guard
Add regression coverage ensuring CI=true no longer forces test-changed into full-suite mode. - Add a reusable --print-mode subprocess helper for synthetic test-changed repositories. - Seed the synthetic repo with changeset config so mode decisions match workspace expectations. - Assert CI=true stays in gate or changed mode while --full and FUSION_TEST_FULL still select full mode. Files changed: scripts/__tests__/test-changed.test.mjs | 54 +++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) Fusion-Task-Id: FN-7105 Fusion-Task-Lineage: f4a26d96-3992-4f25-a456-04f2b9b8a4dc Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
This commit is contained in:
@@ -1501,6 +1501,11 @@ function makeChainRepo(dir) {
|
||||
writeFileSync(path.join(dir, "pnpm-lock.yaml"), "lockfileVersion: '9.0'\n");
|
||||
writeFileSync(path.join(dir, "tsconfig.base.json"), "{}\n");
|
||||
writeFileSync(path.join(dir, "pnpm-workspace.yaml"), "packages:\n - 'packages/*'\n");
|
||||
mkdirSync(path.join(dir, ".changeset"), { recursive: true });
|
||||
writeFileSync(
|
||||
path.join(dir, ".changeset", "config.json"),
|
||||
JSON.stringify({ baseBranch: "main" }, null, 2),
|
||||
);
|
||||
// Shared __test-utils__ tree consumed by every package.
|
||||
mkdirSync(path.join(dir, "packages", "core", "src", "__test-utils__"), { recursive: true });
|
||||
writeFileSync(path.join(dir, "packages", "core", "src", "__test-utils__", "vitest-setup.ts"), "export const setup = 1;\n");
|
||||
@@ -1544,6 +1549,31 @@ function runInRepo(repoDir, snippet) {
|
||||
return JSON.parse(lastLine);
|
||||
}
|
||||
|
||||
function runPrintModeInRepo(repoDir, { args = [], env = {} } = {}) {
|
||||
const subprocessEnv = {
|
||||
...process.env,
|
||||
FUSION_PROJECT_DIR: repoDir,
|
||||
FUSION_TEST_FULL: "",
|
||||
...env,
|
||||
};
|
||||
const r = spawnSync(process.execPath, [scriptModulePath, "--print-mode", ...args], {
|
||||
cwd: repoDir,
|
||||
encoding: "utf8",
|
||||
env: subprocessEnv,
|
||||
});
|
||||
if (r.status !== 0) {
|
||||
throw new Error(`--print-mode subprocess failed: ${r.stderr}\n${r.stdout}`);
|
||||
}
|
||||
const modeLine = r.stdout.split("\n").find((line) => line.startsWith("[test-changed] mode="));
|
||||
assert.ok(
|
||||
modeLine,
|
||||
`expected --print-mode to emit a mode line; stdout:\n${r.stdout}\nstderr:\n${r.stderr}`,
|
||||
);
|
||||
const match = modeLine.match(/\bmode=([^\s]+)/);
|
||||
assert.ok(match, `expected mode line to include mode=<value>: ${modeLine}`);
|
||||
return { mode: match[1], stdout: r.stdout, stderr: r.stderr };
|
||||
}
|
||||
|
||||
const packageHashSnippet = (pkgName) => `(mod) => {
|
||||
const infos = mod.listWorkspacePackageInfos();
|
||||
const dirByName = mod.buildPackageDirByName(infos);
|
||||
@@ -1555,6 +1585,30 @@ const packageHashSnippet = (pkgName) => `(mod) => {
|
||||
}) };
|
||||
}`;
|
||||
|
||||
/*
|
||||
FNXC:TestInfrastructure 2026-06-27-03:46:
|
||||
CI no longer routes through scripts/test-changed.mjs for the merge gate, so CI=true must not force mode=full. Keep paired full-trigger assertions here so this regression guard proves the --print-mode harness can still observe legitimate full-suite opt-ins.
|
||||
*/
|
||||
test("integration: CI=true does not force the full suite (only --full / FUSION_TEST_FULL do)", () => {
|
||||
const dir = mkdtempSync(path.join(tmpdir(), "tc-print-mode-"));
|
||||
try {
|
||||
makeChainRepo(dir);
|
||||
|
||||
const ciOnly = runPrintModeInRepo(dir, { env: { CI: "true", FUSION_TEST_FULL: "" } });
|
||||
assert.notEqual(ciOnly.mode, "full", "CI=true alone must not force the full suite");
|
||||
assert.ok(
|
||||
ciOnly.mode === "gate" || ciOnly.mode === "changed",
|
||||
`CI=true alone should choose gate or changed mode, got ${ciOnly.mode}`,
|
||||
);
|
||||
|
||||
assert.equal(runPrintModeInRepo(dir, { args: ["--full"] }).mode, "full");
|
||||
assert.equal(runPrintModeInRepo(dir, { env: { FUSION_TEST_FULL: "1" } }).mode, "full");
|
||||
assert.equal(runPrintModeInRepo(dir, { args: ["--full"], env: { CI: "true" } }).mode, "full");
|
||||
} finally {
|
||||
rmSync(dir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test("integration: mutating core (a) changes transitive dependents b,c but not unrelated d", () => {
|
||||
const dir = mkdtempSync(path.join(tmpdir(), "tc-chain-"));
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user