Skip to content

Commit ec047b2

Browse files
committed
hopefully fix
1 parent 66593cf commit ec047b2

1 file changed

Lines changed: 67 additions & 1 deletion

File tree

scripts/unit-coverage.mjs

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1-
import { existsSync, mkdirSync, readdirSync, unlinkSync, writeFileSync } from "node:fs";
1+
import {
2+
existsSync,
3+
mkdirSync,
4+
readFileSync,
5+
readdirSync,
6+
unlinkSync,
7+
writeFileSync,
8+
} from "node:fs";
29
import { spawnSync } from "node:child_process";
310

411
const args = new Set(process.argv.slice(2));
@@ -159,6 +166,56 @@ function parseMetricsFromCoverageOutput(rawCoverageOutput) {
159166
return metricsByFile;
160167
}
161168

169+
/**
170+
* Parse LCOV records into the same metric shape used by the text-coverage parser.
171+
* This is used as a resilient fallback when Node's text coverage table is empty in CI.
172+
*/
173+
function parseMetricsFromLcovFile(lcovPath) {
174+
const metricsByFile = new Map();
175+
if (!existsSync(lcovPath)) return metricsByFile;
176+
177+
const content = readFileSync(lcovPath, "utf8");
178+
const records = content.split("end_of_record");
179+
for (const record of records) {
180+
const lines = record
181+
.split("\n")
182+
.map((line) => line.trim())
183+
.filter(Boolean);
184+
if (lines.length === 0) continue;
185+
186+
const sourceLine = lines.find((line) => line.startsWith("SF:"));
187+
if (!sourceLine) continue;
188+
const sourceFile = normalizeCoveragePath(sourceLine.slice(3));
189+
190+
let lf = 0;
191+
let lh = 0;
192+
let brf = 0;
193+
let brh = 0;
194+
let fnf = 0;
195+
let fnh = 0;
196+
197+
for (const line of lines) {
198+
if (line.startsWith("LF:")) lf = Number(line.slice(3)) || 0;
199+
else if (line.startsWith("LH:")) lh = Number(line.slice(3)) || 0;
200+
else if (line.startsWith("BRF:")) brf = Number(line.slice(4)) || 0;
201+
else if (line.startsWith("BRH:")) brh = Number(line.slice(4)) || 0;
202+
else if (line.startsWith("FNF:")) fnf = Number(line.slice(4)) || 0;
203+
else if (line.startsWith("FNH:")) fnh = Number(line.slice(4)) || 0;
204+
}
205+
206+
const pct = (hit, total) => (total > 0 ? (hit / total) * 100 : 100);
207+
metricsByFile.set(sourceFile, {
208+
file: sourceFile,
209+
linePct: pct(lh, lf),
210+
branchPct: pct(brh, brf),
211+
funcPct: pct(fnh, fnf),
212+
uncovered: "",
213+
});
214+
}
215+
216+
return metricsByFile;
217+
}
218+
162219
let metricsByFile = parseMetricsFromCoverageOutput(activeAttempt.combinedOutput);
163220
const primaryMissing = trackedFiles.filter(
164221
(file) => !resolveMetricForFile(metricsByFile, file)
@@ -189,6 +246,13 @@ if (primaryMissing.length === trackedFiles.length) {
189246
if (retryAttempt.result.status === 0) {
190247
activeAttempt = retryAttempt;
191248
metricsByFile = parseMetricsFromCoverageOutput(activeAttempt.combinedOutput);
249+
const retryMissing = trackedFiles.filter(
250+
(file) => !resolveMetricForFile(metricsByFile, file)
251+
);
252+
// If table output is still empty, fall back to LCOV metrics produced by retry reporter.
253+
if (retryMissing.length === trackedFiles.length) {
254+
metricsByFile = parseMetricsFromLcovFile(lcovPath);
255+
}
192256
} else if (quiet) {
193257
if (retryAttempt.result.stdout) process.stdout.write(retryAttempt.result.stdout);
194258
if (retryAttempt.result.stderr) process.stderr.write(retryAttempt.result.stderr);
@@ -303,6 +367,8 @@ if (failures.length > 0) {
303367
trackedFiles,
304368
advisoryFiles,
305369
coverageIncludeArgs,
370+
retryLcovPath: `${process.cwd()}/coverage/unit-retry.lcov`,
371+
retryLcovExists: existsSync(`${process.cwd()}/coverage/unit-retry.lcov`),
306372
attempts: [
307373
{
308374
label: primaryAttempt.label,

0 commit comments

Comments
 (0)