import { mkdir, readFile, writeFile } from "node:fs/promises"; import path from "node:path"; import { buildProductionModuleInventory, evaluateRiskCoverage, parseRepositoryRiskCoveragePolicy, } from "./lib/risk-coverage.ts"; function argumentValue(name: string, fallback?: string): string | undefined { const index = process.argv.indexOf(name); return index >= 0 ? process.argv[index + 1] : fallback; } function requiredArgument(name: string, fallback: string): string { const value = argumentValue(name, fallback); if (!value) throw new TypeError(`${name} requires a path`); return value; } function parseChangedFiles(value: unknown): readonly string[] { if ( !Array.isArray(value) || value.some((entry) => typeof entry !== "string") || new Set(value).size !== value.length ) { throw new TypeError("changed files input must be an array of unique paths"); } return Object.freeze([...value] as string[]); } const repositoryRoot = path.resolve( requiredArgument("--repository-root", process.cwd()), ); const policyPath = requiredArgument( "--policy", "config/testing/risk-coverage.json", ); const summaryPath = requiredArgument( "--summary", "artifacts/tests/coverage/coverage-summary.json", ); const artifactPath = requiredArgument( "--artifact", "artifacts/quality/risk-coverage.json", ); const changedFilesPath = argumentValue("--changed-files"); const policy = parseRepositoryRiskCoveragePolicy( JSON.parse(await readFile(path.resolve(repositoryRoot, policyPath), "utf8")) as unknown, ); const inventory = await buildProductionModuleInventory({ repositoryRoot, generatedPaths: policy.generatedPaths, }); const changedFiles = changedFilesPath ? parseChangedFiles( JSON.parse( await readFile(path.resolve(repositoryRoot, changedFilesPath), "utf8"), ) as unknown, ) : []; const result = evaluateRiskCoverage({ repositoryRoot, inventory, policy, summary: JSON.parse( await readFile(path.resolve(repositoryRoot, summaryPath), "utf8"), ) as unknown, changedFiles, }); const artifact = { schemaVersion: 2, policy: policyPath, summary: summaryPath, changedFiles: changedFilesPath ?? null, ...result, }; const resolvedArtifactPath = path.resolve(repositoryRoot, artifactPath); await mkdir(path.dirname(resolvedArtifactPath), { recursive: true }); await writeFile(resolvedArtifactPath, `${JSON.stringify(artifact, null, 2)}\n`); if (result.failures.length > 0) { process.stderr.write( `Risk coverage failed:\n- ${result.failures.join("\n- ")}\n`, ); process.exit(1); } process.stdout.write( `Risk coverage: PASS (${result.selectedTotal}/${result.repositoryTotal} production modules, ${result.results.length} thresholds)\n`, );