Files
clean-architecture-frontend…/scripts/check-risk-coverage.mjs
T

89 lines
2.5 KiB
JavaScript

import { mkdir, readFile, writeFile } from "node:fs/promises";
import path from "node:path";
/** @param {string} name @param {string} fallback */
function argumentValue(name, fallback) {
const index = process.argv.indexOf(name);
return index >= 0 && process.argv[index + 1]
? process.argv[index + 1]
: fallback;
}
const policyPath = argumentValue(
"--policy",
"config/testing/risk-coverage.json",
);
const summaryPath = argumentValue(
"--summary",
"artifacts/tests/coverage/coverage-summary.json",
);
const artifactPath = argumentValue(
"--artifact",
"artifacts/quality/risk-coverage.json",
);
const policy = JSON.parse(await readFile(policyPath, "utf8"));
const summary = JSON.parse(await readFile(summaryPath, "utf8"));
const failures = [];
/** @type {Array<{
* scope: string,
* metric: string,
* threshold: number,
* received: number | undefined,
* passed: boolean
* }>} */
const results = [];
/**
* @param {string} scope
* @param {Record<string, {pct: number}>} actual
* @param {Record<string, number>} minimum
*/
function evaluate(scope, actual, minimum) {
for (const [metric, threshold] of Object.entries(minimum)) {
const received = actual?.[metric]?.pct;
const passed =
typeof received === "number" &&
Number.isFinite(received) &&
received >= threshold;
results.push({ scope, metric, threshold, received, passed });
if (!passed) {
failures.push(
`${scope}.${metric} expected >= ${threshold}, received ${String(received)}`,
);
}
}
}
evaluate("total", summary.total, policy.summary);
for (const modulePolicy of policy.criticalModules) {
const key = Object.keys(summary).find(
(candidate) =>
candidate !== "total" &&
candidate.replaceAll("\\", "/").endsWith(`/${modulePolicy.path}`),
);
if (!key) {
failures.push(`critical module missing from coverage: ${modulePolicy.path}`);
continue;
}
evaluate(modulePolicy.path, summary[key], modulePolicy.minimum);
}
const artifact = {
schemaVersion: 1,
policy: policyPath,
summary: summaryPath,
status: failures.length === 0 ? "PASS" : "FAIL",
results,
failures,
};
await mkdir(path.dirname(artifactPath), { recursive: true });
await writeFile(artifactPath, `${JSON.stringify(artifact, null, 2)}\n`);
if (failures.length > 0) {
process.stderr.write(`Risk coverage failed:\n- ${failures.join("\n- ")}\n`);
process.exit(1);
}
process.stdout.write(
`Risk coverage: PASS (${results.length} scoped thresholds)\n`,
);