Skip to content

Commit 90b8d6c

Browse files
committed
Replace Madrapps/jacoco-report with per-package coverage table
Swap the third-party JaCoCo action for a custom github-script step that parses the JaCoCo XML and posts a per-package coverage breakdown (line, branch, method) as a PR comment. Also uploads the full HTML report as a build artifact for class-level drill-down. https://claude.ai/code/session_01R1nvwA9Gc7gv8Uxwyvy83u
1 parent e6f1336 commit 90b8d6c

File tree

1 file changed

+92
-7
lines changed

1 file changed

+92
-7
lines changed

.github/workflows/pull_request.yml

Lines changed: 92 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,103 @@ jobs:
3131
distribution: 'corretto'
3232
- name: build and test
3333
run: ./gradlew ${{matrix.gradle-argument}} --info --stacktrace
34-
- name: Publish Coverage Report
35-
uses: Madrapps/jacoco-report@50d3aff4548aa991e6753342d9ba291084e63848 # v1.7.2
34+
- name: Upload Coverage HTML Report
35+
uses: actions/upload-artifact@v4
36+
if: >
37+
always() &&
38+
contains(matrix.gradle-argument, 'jacocoTestReport')
39+
with:
40+
name: jacoco-html-report
41+
path: build/reports/jacoco/test/html/
42+
retention-days: 14
43+
- name: Publish Per-Package Coverage Comment
3644
if: >
3745
always() &&
3846
github.event_name == 'pull_request' &&
3947
contains(matrix.gradle-argument, 'jacocoTestReport')
48+
uses: actions/github-script@v7
4049
with:
41-
paths: ${{ github.workspace }}/build/reports/jacoco/test/jacocoTestReport.xml
42-
token: ${{ secrets.GITHUB_TOKEN }}
43-
min-coverage-overall: 0
44-
min-coverage-changed-files: 0
45-
update-comment: true
50+
script: |
51+
const fs = require('fs');
52+
const path = require('path');
53+
const xmlFile = path.join(process.env.GITHUB_WORKSPACE, 'build/reports/jacoco/test/jacocoTestReport.xml');
54+
if (!fs.existsSync(xmlFile)) {
55+
core.warning('JaCoCo XML report not found');
56+
return;
57+
}
58+
const xml = fs.readFileSync(xmlFile, 'utf8');
59+
60+
function extractCounters(element) {
61+
const counters = {};
62+
const re = /<counter type="(\w+)" missed="(\d+)" covered="(\d+)"\/>/g;
63+
let m;
64+
while ((m = re.exec(element)) !== null) {
65+
counters[m[1]] = { missed: parseInt(m[2]), covered: parseInt(m[3]) };
66+
}
67+
return counters;
68+
}
69+
70+
function pct(c) {
71+
if (!c) return 'N/A';
72+
const total = c.missed + c.covered;
73+
return total === 0 ? 'N/A' : (c.covered / total * 100).toFixed(1) + '%';
74+
}
75+
76+
// Parse overall counters (last set of <counter> tags at report level)
77+
const reportMatch = xml.match(/<report[^>]*>([\s\S]*)<\/report>/);
78+
const reportBody = reportMatch ? reportMatch[1] : xml;
79+
80+
// Extract packages
81+
const pkgRegex = /<package name="([^"]*)">([\s\S]*?)<\/package>/g;
82+
const packages = [];
83+
let pm;
84+
while ((pm = pkgRegex.exec(reportBody)) !== null) {
85+
const name = pm[1].replace(/\//g, '.');
86+
const counters = extractCounters(pm[2]);
87+
packages.push({ name, counters });
88+
}
89+
90+
// Sort by package name
91+
packages.sort((a, b) => a.name.localeCompare(b.name));
92+
93+
// Overall counters (direct children of <report>, after all packages)
94+
const overallCounters = extractCounters(reportBody.replace(/<package[\s\S]*?<\/package>/g, ''));
95+
96+
let body = '## JaCoCo Coverage Report\n\n';
97+
body += '| Package | Line | Branch | Method |\n';
98+
body += '|:--------|-----:|-------:|-------:|\n';
99+
100+
for (const pkg of packages) {
101+
const c = pkg.counters;
102+
body += `| \`${pkg.name}\` | ${pct(c.LINE)} | ${pct(c.BRANCH)} | ${pct(c.METHOD)} |\n`;
103+
}
104+
105+
body += `| **Overall** | **${pct(overallCounters.LINE)}** | **${pct(overallCounters.BRANCH)}** | **${pct(overallCounters.METHOD)}** |\n`;
106+
body += '\n> Full HTML report available as build artifact `jacoco-html-report`\n';
107+
108+
// Find and update or create the comment
109+
const { data: comments } = await github.rest.issues.listComments({
110+
owner: context.repo.owner,
111+
repo: context.repo.repo,
112+
issue_number: context.issue.number,
113+
});
114+
const marker = '## JaCoCo Coverage Report';
115+
const existing = comments.find(c => c.body && c.body.startsWith(marker));
116+
if (existing) {
117+
await github.rest.issues.updateComment({
118+
owner: context.repo.owner,
119+
repo: context.repo.repo,
120+
comment_id: existing.id,
121+
body,
122+
});
123+
} else {
124+
await github.rest.issues.createComment({
125+
owner: context.repo.owner,
126+
repo: context.repo.repo,
127+
issue_number: context.issue.number,
128+
body,
129+
});
130+
}
46131
- name: Publish Test Results
47132
uses: EnricoMi/publish-unit-test-result-action@v2.23.0
48133
if: always()

0 commit comments

Comments
 (0)