Skip to content

Commit 849a785

Browse files
committed
add codeCoverageSummary.ts and change testResultsSummary.ts to add the view in between
1 parent 7cb6e57 commit 849a785

2 files changed

Lines changed: 118 additions & 1 deletion

File tree

src/codeCoverageSummary.ts

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
2+
import * as core from "@actions/core";
3+
import { readFileSync, existsSync } from "fs";
4+
import * as path from "path";
5+
6+
interface CoverageMetric {
7+
Executed: number;
8+
Total: number;
9+
Percentage: number;
10+
}
11+
12+
interface CoverageData {
13+
MetricLevel?: string;
14+
StatementCoverage?: CoverageMetric; // Made optional with ?
15+
FunctionCoverage?: CoverageMetric; // Made optional with ?
16+
DecisionCoverage?: CoverageMetric; // Made optional with ?
17+
ConditionCoverage?: CoverageMetric; // Made optional with ?
18+
MCDCCoverage?: CoverageMetric; // Made optional with ?
19+
}
20+
21+
export function getCoverageData(): CoverageData | null {
22+
const runnerTemp = process.env.RUNNER_TEMP || "";
23+
const runId = process.env.GITHUB_RUN_ID || "";
24+
const coveragePath = path.join(runnerTemp, `matlabCoverageResults${runId}.json`);
25+
26+
core.info(`Looking for coverage at: ${coveragePath}`);
27+
28+
if (!existsSync(coveragePath)) {
29+
core.info("No coverage data found");
30+
return null;
31+
}
32+
33+
try {
34+
const coverageData: CoverageData[] = JSON.parse(readFileSync(coveragePath, "utf8"));
35+
if (!coverageData || coverageData.length === 0) {
36+
core.info("Coverage data is empty");
37+
return null;
38+
}
39+
return coverageData[coverageData.length - 1];
40+
} catch (error) {
41+
core.error(`Error reading coverage data: ${error}`);
42+
return null;
43+
}
44+
}
45+
46+
function formatPercentage(percentage: number): string {
47+
if (percentage === null || percentage === undefined || isNaN(percentage)) {
48+
return '0.00%';
49+
}
50+
return percentage.toFixed(2) + '%';
51+
}
52+
53+
export function generateCoverageTableHTML(coverage: CoverageData): string {
54+
try {
55+
core.info(`Generating coverage table for metric level: ${coverage.MetricLevel}`);
56+
57+
// Define all possible columns
58+
const allColumns = [
59+
{ name: 'Statement', data: coverage.StatementCoverage },
60+
{ name: 'Function', data: coverage.FunctionCoverage },
61+
{ name: 'Decision', data: coverage.DecisionCoverage },
62+
{ name: 'Condition', data: coverage.ConditionCoverage },
63+
{ name: 'MC/DC', data: coverage.MCDCCoverage }
64+
];
65+
66+
// Filter to only include columns where data actually exists
67+
const visibleColumns = allColumns.filter(col => col.data !== undefined && col.data !== null);
68+
69+
if (visibleColumns.length === 0) {
70+
core.warning('No visible columns found');
71+
return '<p>No coverage data available</p>';
72+
}
73+
74+
core.info(`Visible columns: ${visibleColumns.map(c => c.name).join(', ')}`);
75+
76+
// Build header row
77+
const headers = visibleColumns.map(col => `<th>${col.name}</th>`).join('');
78+
const headerRow = `<tr align="center"><th>Metric</th>${headers}</tr>`;
79+
80+
// Build percentage row
81+
const percentages = visibleColumns.map(col =>
82+
`<td>${formatPercentage(col.data!.Percentage)}</td>`
83+
).join('');
84+
const percentageRow = `<tr align="center"><td><b>Percentage</b></td>${percentages}</tr>`;
85+
86+
// Build covered/total row
87+
const coveredTotals = visibleColumns.map(col =>
88+
`<td>${col.data!.Executed}/${col.data!.Total}</td>`
89+
).join('');
90+
const coveredTotalRow = `<tr align="center"><td><b>Covered/Total</b></td>${coveredTotals}</tr>`;
91+
92+
const tableHTML = `<table>${headerRow}${percentageRow}${coveredTotalRow}</table>`;
93+
core.info(`Generated table HTML: ${tableHTML}`);
94+
95+
return tableHTML;
96+
} catch (error) {
97+
core.error(`Error generating coverage table: ${error}`);
98+
return '<p>Error generating coverage table</p>';
99+
}
100+
}

src/testResultsSummary.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import { readFileSync, unlinkSync, existsSync } from "fs";
44
import * as path from "path";
55
import * as core from "@actions/core";
6+
import { getCoverageData, generateCoverageTableHTML } from "./codeCoverageSummary";
67

78
export enum MatlabTestStatus {
89
PASSED = "PASSED",
@@ -143,9 +144,25 @@ export function addSummary(
143144
const header = getTestHeader(testResultsData.Stats);
144145
const detailedResults = getDetailedResults(testResultsData.TestResults);
145146

147+
// core.summary
148+
// .addHeading("MATLAB Test Results (" + actionName + ") " + helpLink)
149+
// .addRaw(header, true)
150+
// .addHeading("All tests", 3)
151+
// .addRaw(detailedResults, true);
146152
core.summary
147153
.addHeading("MATLAB Test Results (" + actionName + ") " + helpLink)
148-
.addRaw(header, true)
154+
.addRaw(header, true);
155+
156+
// Add coverage table if available
157+
const coverageData = getCoverageData();
158+
if (coverageData) {
159+
core.summary
160+
.addHeading("MATLAB Code Coverage", 3)
161+
.addRaw(generateCoverageTableHTML(coverageData), true);
162+
}
163+
164+
// Add detailed test results
165+
core.summary
149166
.addHeading("All tests", 3)
150167
.addRaw(detailedResults, true);
151168
} catch (e) {

0 commit comments

Comments
 (0)