/** * Fail CI if coverage is below thresholds. * Reads coverage/coverage-summary.json produced by Vitest (v8 provider). */ import fs from "node:fs"; import path from "node:path"; const SUMMARY = path.join("coverage", "coverage-summary.json"); if (!fs.existsSync(SUMMARY)) { console.error("coverage/coverage-summary.json not found. Did tests run with --coverage?"); process.exit(1); } const data = JSON.parse(fs.readFileSync(SUMMARY, "utf8")); const total = data.total || {}; const want = { lines: Number(process.env.COV_LINES || 70), branches: Number(process.env.COV_BRANCHES || 70), functions: Number(process.env.COV_FUNCTIONS || 50), statements: Number(process.env.COV_STATEMENTS || 70), }; const got = { lines: total.lines?.pct ?? 0, branches: total.branches?.pct ?? 0, functions: total.functions?.pct ?? 0, statements: total.statements?.pct ?? 0, }; function fail(msg) { console.error(msg); console.error("Coverage totals:", JSON.stringify(got)); process.exit(1); } let ok = true; for (const k of Object.keys(want)) { if (got[k] < want[k]) { ok = false; console.error(`✖ ${k} coverage ${got[k]}% < required ${want[k]}%`); } else { console.log(`✔ ${k} coverage ${got[k]}% >= required ${want[k]}%`); } } if (!ok) { fail("Coverage thresholds not met."); } console.log("All coverage thresholds satisfied.");