1
0
forked from baron/baron-sso
Files
baron-sso/scripts/summarize_flutter_coverage.mjs

116 lines
2.9 KiB
JavaScript

import { mkdir, readFile, writeFile } from "node:fs/promises";
import path from "node:path";
const repoRoot = process.cwd();
const packageName = process.argv[2] || "userfront";
const lcovPath = path.join(repoRoot, packageName, "coverage", "lcov.info");
const reportsDir = path.join(repoRoot, "reports");
const excludedSourceFiles = new Set(["lib/main.dart", "lib/i18n_data.dart"]);
function normalizeSourcePath(sourcePath) {
const normalized = sourcePath.replace(/\\/g, "/");
const packagePrefix = `${packageName}/`;
return normalized.startsWith(packagePrefix)
? normalized.slice(packagePrefix.length)
: normalized;
}
function shouldExcludeSource(sourcePath) {
const normalized = normalizeSourcePath(sourcePath);
return (
excludedSourceFiles.has(normalized) ||
normalized.endsWith(".g.dart") ||
normalized.endsWith(".freezed.dart")
);
}
function parseLcov(raw) {
const records = [];
let current = null;
for (const line of raw.split(/\r?\n/)) {
if (line.startsWith("SF:")) {
current = { sourceFile: normalizeSourcePath(line.slice(3)), lines: [] };
continue;
}
if (!current) continue;
if (line.startsWith("DA:")) {
const [, hitsValue] = line.slice(3).split(",");
const hits = Number(hitsValue);
current.lines.push(Number.isFinite(hits) ? hits : 0);
continue;
}
if (line === "end_of_record") {
records.push(current);
current = null;
}
}
if (current) {
records.push(current);
}
return records;
}
function formatPct(value) {
return `${value.toFixed(2)}%`;
}
function renderMarkdown(row) {
return [
"# Userfront Flutter Coverage Summary",
"",
"| Package | Lines | Covered / Total | LCOV |",
"| --- | ---: | ---: | --- |",
`| ${row.package} | ${formatPct(row.lines)} | ${row.coveredLines} / ${row.totalLines} | ${row.lcovPath} |`,
"",
"Coverage excludes Flutter bootstrap/generated files: `lib/main.dart`, `lib/i18n_data.dart`, `*.g.dart`, `*.freezed.dart`.",
"",
].join("\n");
}
const lcov = await readFile(lcovPath, "utf8");
const includedRecords = parseLcov(lcov).filter(
(record) => !shouldExcludeSource(record.sourceFile),
);
const totalLines = includedRecords.reduce(
(total, record) => total + record.lines.length,
0,
);
const coveredLines = includedRecords.reduce(
(total, record) => total + record.lines.filter((hits) => hits > 0).length,
0,
);
const lineCoverage = totalLines === 0 ? 0 : (coveredLines / totalLines) * 100;
const row = {
package: packageName,
statements: lineCoverage,
branches: null,
functions: null,
lines: lineCoverage,
coveredLines,
totalLines,
summaryPath: "reports/package-coverage-summary.json",
htmlPath: null,
lcovPath: `${packageName}/coverage/lcov.info`,
};
await mkdir(reportsDir, { recursive: true });
await writeFile(
path.join(reportsDir, "package-coverage-summary.json"),
`${JSON.stringify({ packages: [row] }, null, 2)}\n`,
);
await writeFile(
path.join(reportsDir, `${packageName}-coverage-summary.md`),
renderMarkdown(row),
);
console.log(renderMarkdown(row));