feat(lanes): add isIntegrationEnabled toggle check (F3a)
This commit is contained in:
@@ -111,3 +111,32 @@ describe("resolveProfile — E2 declarations", () => {
|
|||||||
assert.deepEqual(profile.generatedMergePaths, ["api/openapi.json", "api/client.ts"]);
|
assert.deepEqual(profile.generatedMergePaths, ["api/openapi.json", "api/client.ts"]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("isIntegrationEnabled", () => {
|
||||||
|
it("returns false when integrations.env doesn't exist at all", () => {
|
||||||
|
const lane = makeLane();
|
||||||
|
writeProfile(lane.cwd, "PORTS=api\n");
|
||||||
|
assert.equal(profileLib.isIntegrationEnabled(lanesLib.getLane(lane.id), "tracker"), false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns true when <NAME>_ENABLED=1 is set", () => {
|
||||||
|
const lane = makeLane();
|
||||||
|
writeProfile(lane.cwd, "PORTS=api\n");
|
||||||
|
fsMod.writeFileSync(
|
||||||
|
pathMod.join(lane.cwd, ".ccam", "profile", "integrations.env"),
|
||||||
|
"TRACKER_ENABLED=1\nTRACKER_PROJECT=demo\n"
|
||||||
|
);
|
||||||
|
assert.equal(profileLib.isIntegrationEnabled(lanesLib.getLane(lane.id), "tracker"), true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns false when the flag is 0 or absent from an existing file", () => {
|
||||||
|
const lane = makeLane();
|
||||||
|
writeProfile(lane.cwd, "PORTS=api\n");
|
||||||
|
fsMod.writeFileSync(
|
||||||
|
pathMod.join(lane.cwd, ".ccam", "profile", "integrations.env"),
|
||||||
|
"DEV_QC_ENABLED=0\n"
|
||||||
|
);
|
||||||
|
assert.equal(profileLib.isIntegrationEnabled(lanesLib.getLane(lane.id), "dev_qc"), false);
|
||||||
|
assert.equal(profileLib.isIntegrationEnabled(lanesLib.getLane(lane.id), "ci_wait"), false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -195,6 +195,34 @@ function profileSearchPaths(lane) {
|
|||||||
.map((root) => path.join(root, PROFILE_SUBDIR));
|
.map((root) => path.join(root, PROFILE_SUBDIR));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether a named integration is turned on for this lane — reads
|
||||||
|
* .ccam/profile/integrations.env (same two-location search as profile.env:
|
||||||
|
* the lane's own working copy first, the source repo second) and checks
|
||||||
|
* <NAME>_ENABLED=1. A missing file or missing key is off, never an error —
|
||||||
|
* same off-by-default shape every other optional declaration follows.
|
||||||
|
*
|
||||||
|
* @param {object} lane - Lane row (`cwd`, `source_repo`).
|
||||||
|
* @param {string} name - Lowercase integration name, e.g. "tracker", "dev_qc", "ci_wait".
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
function isIntegrationEnabled(lane, name) {
|
||||||
|
const candidates = [lane.cwd, lane.source_repo].filter(Boolean);
|
||||||
|
const key = `${name.toUpperCase()}_ENABLED`;
|
||||||
|
for (const root of candidates) {
|
||||||
|
const filePath = path.join(root, PROFILE_SUBDIR, "integrations.env");
|
||||||
|
if (!fs.existsSync(filePath)) continue;
|
||||||
|
let declared;
|
||||||
|
try {
|
||||||
|
declared = parseEnvFile(fs.readFileSync(filePath, "utf8"));
|
||||||
|
} catch {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return declared[key] === "1";
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A `harness_spawn` shell function, injected into every hook.
|
* A `harness_spawn` shell function, injected into every hook.
|
||||||
*
|
*
|
||||||
@@ -428,6 +456,7 @@ module.exports = {
|
|||||||
parseQcBootEnv,
|
parseQcBootEnv,
|
||||||
resolveProfile,
|
resolveProfile,
|
||||||
profileSearchPaths,
|
profileSearchPaths,
|
||||||
|
isIntegrationEnabled,
|
||||||
hookEnv,
|
hookEnv,
|
||||||
runHook,
|
runHook,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user