Skip to content

Commit e6120ba

Browse files
committed
extract coverage report scripts of action
1 parent c0cf42f commit e6120ba

File tree

4 files changed

+149
-92
lines changed

4 files changed

+149
-92
lines changed
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
const fs = require('fs');
2+
3+
// Configuration thresholds
4+
const THRESHOLDS = {
5+
good: 80,
6+
needsImprovement: 60,
7+
poor: 40
8+
};
9+
10+
/**
11+
* Parse lcov.info file and extract coverage metrics
12+
* @param {string} content - The lcov.info file content
13+
* @returns {object} Coverage metrics
14+
*/
15+
function parseLcovContent(content) {
16+
const lines = content.split('\n');
17+
let totalLines = 0;
18+
let coveredLines = 0;
19+
let totalFunctions = 0;
20+
let coveredFunctions = 0;
21+
let totalBranches = 0;
22+
let coveredBranches = 0;
23+
24+
// LF:, LH:, FNF:, FNH:, BRF:, BRH: are on separate lines
25+
// We need to track them separately and sum them up
26+
for (let i = 0; i < lines.length; i++) {
27+
const line = lines[i].trim();
28+
29+
// Lines Found and Lines Hit
30+
if (line.startsWith('LF:')) {
31+
totalLines += parseInt(line.substring(3)) || 0;
32+
}
33+
if (line.startsWith('LH:')) {
34+
coveredLines += parseInt(line.substring(3)) || 0;
35+
}
36+
37+
// Functions Found and Functions Hit
38+
if (line.startsWith('FNF:')) {
39+
totalFunctions += parseInt(line.substring(4)) || 0;
40+
}
41+
if (line.startsWith('FNH:')) {
42+
coveredFunctions += parseInt(line.substring(4)) || 0;
43+
}
44+
45+
// Branches Found and Branches Hit
46+
if (line.startsWith('BRF:')) {
47+
totalBranches += parseInt(line.substring(4)) || 0;
48+
}
49+
if (line.startsWith('BRH:')) {
50+
coveredBranches += parseInt(line.substring(4)) || 0;
51+
}
52+
}
53+
54+
return {
55+
totalLines,
56+
coveredLines,
57+
totalFunctions,
58+
coveredFunctions,
59+
totalBranches,
60+
coveredBranches
61+
};
62+
}
63+
64+
/**
65+
* Calculate coverage percentage
66+
* @param {number} covered - Number of covered items
67+
* @param {number} total - Total number of items
68+
* @returns {number} Coverage percentage
69+
*/
70+
function calculateCoverage(covered, total) {
71+
return total > 0 ? Math.round((covered / total) * 100) : 0;
72+
}
73+
74+
/**
75+
* Get badge color based on coverage percentage
76+
* @param {number} coverage - Coverage percentage
77+
* @returns {string} Badge color
78+
*/
79+
function getBadgeColor(coverage) {
80+
if (coverage >= THRESHOLDS.good) return 'brightgreen';
81+
if (coverage >= THRESHOLDS.needsImprovement) return 'yellow';
82+
if (coverage >= THRESHOLDS.poor) return 'orange';
83+
return 'red';
84+
}
85+
86+
/**
87+
* Generate coverage report comment body
88+
* @param {object} metrics - Coverage metrics
89+
* @returns {string} Markdown formatted comment body
90+
*/
91+
function generateCoverageReport(metrics) {
92+
const lineCoverage = calculateCoverage(metrics.coveredLines, metrics.totalLines);
93+
const functionCoverage = calculateCoverage(metrics.coveredFunctions, metrics.totalFunctions);
94+
const branchCoverage = calculateCoverage(metrics.coveredBranches, metrics.totalBranches);
95+
96+
const badgeColor = getBadgeColor(lineCoverage);
97+
const badge = `![Coverage](https://img.shields.io/badge/coverage-${lineCoverage}%25-${badgeColor})`;
98+
99+
return `## Coverage Report\n` +
100+
`${badge}\n\n` +
101+
`| Metric | Coverage | Details |\n` +
102+
`|--------|----------|----------|\n` +
103+
`| **Lines** | ${lineCoverage}% | ${metrics.coveredLines}/${metrics.totalLines} lines |\n` +
104+
`| **Functions** | ${functionCoverage}% | ${metrics.coveredFunctions}/${metrics.totalFunctions} functions |\n` +
105+
`| **Branches** | ${branchCoverage}% | ${metrics.coveredBranches}/${metrics.totalBranches} branches |\n\n`;
106+
}
107+
108+
/**
109+
* Main function to post coverage comment
110+
* @param {object} github - GitHub API object
111+
* @param {object} context - GitHub Actions context
112+
*/
113+
async function postCoverageComment(github, context) {
114+
const file = 'lcov.info';
115+
116+
if (!fs.existsSync(file)) {
117+
console.log('Coverage file not found.');
118+
return;
119+
}
120+
121+
const content = fs.readFileSync(file, 'utf8');
122+
const metrics = parseLcovContent(content);
123+
124+
console.log('Coverage Metrics:');
125+
console.log('- Lines:', metrics.coveredLines, '/', metrics.totalLines);
126+
console.log('- Functions:', metrics.coveredFunctions, '/', metrics.totalFunctions);
127+
console.log('- Branches:', metrics.coveredBranches, '/', metrics.totalBranches);
128+
129+
const body = generateCoverageReport(metrics);
130+
131+
await github.rest.issues.createComment({
132+
owner: context.repo.owner,
133+
repo: context.repo.repo,
134+
issue_number: context.issue.number,
135+
body: body
136+
});
137+
138+
console.log('Coverage comment posted successfully!');
139+
}
140+
141+
module.exports = { postCoverageComment };
142+

.github/workflows/coverage.yml

Lines changed: 2 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -34,94 +34,5 @@ jobs:
3434
with:
3535
github-token: ${{ secrets.GITHUB_TOKEN }}
3636
script: |
37-
const fs = require('fs');
38-
const file = 'lcov.info';
39-
let pct = '-';
40-
if (fs.existsSync(file)) {
41-
const content = fs.readFileSync(file, 'utf8');
42-
const match = content.match(/LF:\s*(\d+)\s*LH:\s*(\d+)/);
43-
if (match) {
44-
const total = Number(match[1]);
45-
const covered = Number(match[2]);
46-
pct = Math.round((covered / total)*100) + '%';
47-
}
48-
49-
// THIS IS THE THRESHOLDS
50-
const goodThreshold = 80;
51-
const needsImprovementThreshold = 60;
52-
const poorThreshold = 40;
53-
54-
// Parse more detailed coverage info - sum all individual file records
55-
const lines = content.split('\n');
56-
let totalLines = 0;
57-
let coveredLines = 0;
58-
let totalFunctions = 0;
59-
let coveredFunctions = 0;
60-
let totalBranches = 0;
61-
let coveredBranches = 0;
62-
63-
// LF:, LH:, FNF:, FNH:, BRF:, BRH: are on separate lines
64-
// We need to track them separately and match them up
65-
for (let i = 0; i < lines.length; i++) {
66-
const line = lines[i].trim();
67-
68-
// Lines Found and Lines Hit
69-
if (line.startsWith('LF:')) {
70-
totalLines += parseInt(line.substring(3)) || 0;
71-
}
72-
if (line.startsWith('LH:')) {
73-
coveredLines += parseInt(line.substring(3)) || 0;
74-
}
75-
76-
// Functions Found and Functions Hit
77-
if (line.startsWith('FNF:')) {
78-
totalFunctions += parseInt(line.substring(4)) || 0;
79-
}
80-
if (line.startsWith('FNH:')) {
81-
coveredFunctions += parseInt(line.substring(4)) || 0;
82-
}
83-
84-
// Branches Found and Branches Hit
85-
if (line.startsWith('BRF:')) {
86-
totalBranches += parseInt(line.substring(4)) || 0;
87-
}
88-
if (line.startsWith('BRH:')) {
89-
coveredBranches += parseInt(line.substring(4)) || 0;
90-
}
91-
}
92-
93-
console.log('Summed totals - Lines:', totalLines, 'Covered:', coveredLines);
94-
console.log('Summed totals - Functions:', totalFunctions, 'Covered:', coveredFunctions);
95-
console.log('Summed totals - Branches:', totalBranches, 'Covered:', coveredBranches);
96-
97-
const lineCoverage = totalLines > 0 ? Math.round((coveredLines / totalLines) * 100) : 0;
98-
const functionCoverage = totalFunctions > 0 ? Math.round((coveredFunctions / totalFunctions) * 100) : 0;
99-
const branchCoverage = totalBranches > 0 ? Math.round((coveredBranches / totalBranches) * 100) : 0;
100-
101-
// Create coverage badge
102-
const getBadgeColor = (coverage) => {
103-
if (coverage >= goodThreshold) return 'brightgreen';
104-
if (coverage >= needsImprovementThreshold) return 'yellow';
105-
if (coverage >= poorThreshold) return 'orange';
106-
return 'red';
107-
};
108-
109-
const badgeColor = getBadgeColor(lineCoverage);
110-
const badge = `![Coverage](https://img.shields.io/badge/coverage-${lineCoverage}%25-${badgeColor})`;
111-
112-
const body = `## Coverage Report\n` +
113-
`${badge}\n\n` +
114-
`| Metric | Coverage | Details |\n` +
115-
`|--------|----------|----------|\n` +
116-
`| **Lines** | ${lineCoverage}% | ${coveredLines}/${totalLines} lines |\n` +
117-
`| **Functions** | ${functionCoverage}% | ${coveredFunctions}/${totalFunctions} functions |\n` +
118-
`| **Branches** | ${branchCoverage}% | ${coveredBranches}/${totalBranches} branches |\n\n`;
119-
await github.rest.issues.createComment({
120-
owner: context.repo.owner,
121-
repo: context.repo.repo,
122-
issue_number: context.issue.number,
123-
body: body
124-
});
125-
} else {
126-
console.log('Coverage file not found.');
127-
}
37+
const { postCoverageComment } = require('./.github/scripts/coverage-comment.js');
38+
await postCoverageComment(github, context);

.github/workflows/slither.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
name: CI
22

3+
34
on:
45
push:
6+
branches: [main]
57
pull_request:
8+
paths-ignore:
9+
- '**.md'
610
workflow_dispatch:
711

812
env:

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ env:
1313

1414
jobs:
1515
check:
16-
name: Foundry project
16+
name: Foundry Tests
1717
runs-on: ubuntu-latest
1818
steps:
1919
- uses: actions/checkout@v4

0 commit comments

Comments
 (0)