Skip to content

Commit e7c83e9

Browse files
committed
ci: compare coverage
1 parent 6c76fef commit e7c83e9

File tree

2 files changed

+114
-1
lines changed

2 files changed

+114
-1
lines changed
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
name: Coverage Delta
2+
3+
on:
4+
pull_request:
5+
branches: [main]
6+
7+
jobs:
8+
compare-coverage:
9+
runs-on: ubuntu-latest
10+
steps:
11+
- uses: actions/setup-node@v3
12+
with:
13+
node-version: 24
14+
15+
- name: Checkout Main
16+
uses: actions/checkout@v4
17+
with:
18+
ref: main
19+
20+
- name: Install & Test (Main)
21+
run: |
22+
npm ci
23+
npm run coverage
24+
mv ./coverage/coverage-summary.json ./coverage-main-summary.json
25+
26+
- name: Checkout PR Branch
27+
uses: actions/checkout@v4
28+
with:
29+
clean: true
30+
31+
- name: Install & Test (PR)
32+
run: |
33+
npm ci
34+
npm run coverage
35+
36+
- name: Report Coverage Delta
37+
uses: actions/github-script@v6
38+
with:
39+
script: |
40+
const fs = require('fs');
41+
42+
const loadSummary = (path) => {
43+
try {
44+
return JSON.parse(fs.readFileSync(path, 'utf8'));
45+
} catch (error) {
46+
console.log(`Could not load ${path}: ${error.message}`);
47+
return null;
48+
}
49+
};
50+
51+
const mainSummary = loadSummary('./coverage-main-summary.json');
52+
const prSummary = loadSummary('./coverage/coverage-summary.json');
53+
54+
if (!mainSummary || !prSummary) {
55+
core.setFailed('Could not load coverage summaries for comparison.');
56+
return;
57+
}
58+
59+
const metrics = ['lines', 'statements', 'functions', 'branches'];
60+
61+
const getPct = (summary, metric) => summary.total[metric].pct;
62+
63+
let markdown = `### 🧪 Code Coverage Delta\n\n`;
64+
markdown += `| Metric | Main | PR | Delta |\n`;
65+
markdown += `| :--- | :---: | :---: | :---: |\n`;
66+
67+
metrics.forEach(metric => {
68+
const oldPct = getPct(mainSummary, metric);
69+
const newPct = getPct(prSummary, metric);
70+
const diff = (newPct - oldPct).toFixed(2);
71+
72+
let icon = '';
73+
if (diff > 0) icon = '🟢';
74+
else if (diff < 0) icon = '🔴';
75+
else icon = '⚪️';
76+
77+
// Format with + sign for positive numbers
78+
const diffStr = diff > 0 ? `+${diff}%` : `${diff}%`;
79+
80+
markdown += `| **${metric}** | ${oldPct}% | ${newPct}% | ${icon} ${diffStr} |\n`;
81+
});
82+
83+
markdown += `\n_Generated by c8 and GitHub Actions_`;
84+
85+
const { owner, repo } = context.repo;
86+
const issue_number = context.issue.number;
87+
88+
const comments = await github.rest.issues.listComments({
89+
owner,
90+
repo,
91+
issue_number,
92+
});
93+
94+
const botComment = comments.data.find(c =>
95+
c.body.includes('### 🧪 Code Coverage Delta') &&
96+
c.user.type === 'Bot'
97+
);
98+
99+
if (botComment) {
100+
await github.rest.issues.updateComment({
101+
owner,
102+
repo,
103+
comment_id: botComment.id,
104+
body: markdown
105+
});
106+
} else {
107+
await github.rest.issues.createComment({
108+
owner,
109+
repo,
110+
issue_number,
111+
body: markdown
112+
});
113+
}

vitest.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export default defineConfig({
77
include: ['test/**/*.spec.ts'],
88
coverage: {
99
provider: 'v8',
10-
reporter: ['text', 'json', 'html'],
10+
reporter: ['text', 'json', 'html', 'json-summary'],
1111
},
1212
},
1313
});

0 commit comments

Comments
 (0)