Skip to content

Commit d237944

Browse files
committed
feat(ci): Add code coverage analysis and reporting workflow
- Add coverage job that builds with GCC 11 and coverage instrumentation - Configure CMake with --coverage flags for gcov data collection - Run full test suite and capture coverage with lcov - Filter out external dependencies and test files from coverage - Generate HTML coverage reports with genhtml - Display coverage summary and check 90% threshold - Upload coverage reports to Codecov (optional with token) - Upload HTML coverage report as artifact (30-day retention) - Comment coverage summary on pull requests - Trigger on pushes, PRs, weekly schedule, and manual dispatch
1 parent f947567 commit d237944

File tree

1 file changed

+168
-0
lines changed

1 file changed

+168
-0
lines changed

.github/workflows/coverage.yml

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
# SPDX-FileCopyrightText: 2025 VTT Technical Research Centre of Finland Ltd
2+
# SPDX-License-Identifier: AGPL-3.0-or-later
3+
4+
name: Coverage
5+
6+
on:
7+
push:
8+
branches: [ "master", "main", "develop" ]
9+
pull_request:
10+
branches: [ "master", "main" ]
11+
schedule:
12+
# Run coverage weekly on Sunday at 00:00 UTC
13+
- cron: '0 0 * * 0'
14+
workflow_dispatch:
15+
16+
jobs:
17+
# ============================================================================
18+
# Code Coverage Analysis
19+
# ============================================================================
20+
coverage:
21+
name: Code Coverage
22+
runs-on: ubuntu-22.04
23+
steps:
24+
- name: Checkout repository
25+
uses: actions/checkout@v4
26+
27+
- name: Install dependencies
28+
run: |
29+
sudo apt-get update
30+
sudo apt-get install -y \
31+
gcc-11 \
32+
g++-11 \
33+
cmake \
34+
ninja-build \
35+
libopenmpi-dev \
36+
openmpi-bin \
37+
libfftw3-dev \
38+
libfftw3-mpi-dev \
39+
nlohmann-json3-dev \
40+
lcov
41+
42+
- name: Cache HeFFTe
43+
id: cache-heffte
44+
uses: actions/cache@v4
45+
with:
46+
path: ~/opt/heffte
47+
key: heffte-2.4.0-ubuntu-22.04-coverage
48+
49+
- name: Build HeFFTe (if not cached)
50+
if: steps.cache-heffte.outputs.cache-hit != 'true'
51+
env:
52+
CC: gcc-11
53+
CXX: g++-11
54+
run: |
55+
wget -q https://github.com/icl-utk-edu/heffte/archive/refs/tags/v2.4.0.tar.gz
56+
tar xzf v2.4.0.tar.gz
57+
cmake -S heffte-2.4.0 -B heffte-build \
58+
-GNinja \
59+
-DCMAKE_BUILD_TYPE=Debug \
60+
-DCMAKE_INSTALL_PREFIX=$HOME/opt/heffte \
61+
-DHeffte_ENABLE_FFTW=ON \
62+
-DBUILD_SHARED_LIBS=ON
63+
cmake --build heffte-build -j2
64+
cmake --install heffte-build
65+
66+
- name: Configure OpenPFC with Coverage
67+
env:
68+
CC: gcc-11
69+
CXX: g++-11
70+
CMAKE_PREFIX_PATH: ${{ github.workspace }}/~/opt/heffte
71+
run: |
72+
cmake -S . -B build \
73+
-GNinja \
74+
-DCMAKE_BUILD_TYPE=Debug \
75+
-DCMAKE_PREFIX_PATH=$HOME/opt/heffte \
76+
-DCMAKE_CXX_FLAGS="--coverage -fprofile-arcs -ftest-coverage" \
77+
-DCMAKE_C_FLAGS="--coverage -fprofile-arcs -ftest-coverage" \
78+
-DCMAKE_EXE_LINKER_FLAGS="--coverage" \
79+
-DOpenPFC_BUILD_TESTS=ON \
80+
-DOpenPFC_BUILD_EXAMPLES=OFF \
81+
-DOpenPFC_BUILD_APPS=OFF \
82+
-DOpenPFC_BUILD_DOCUMENTATION=OFF
83+
84+
- name: Build OpenPFC
85+
run: cmake --build build -j2
86+
87+
- name: Run Tests
88+
working-directory: build
89+
run: |
90+
ctest --output-on-failure -j2 \
91+
--exclude-regex "benchmark" \
92+
--timeout 600
93+
94+
- name: Generate coverage report
95+
working-directory: build
96+
run: |
97+
# Capture coverage data
98+
lcov --directory . --capture --output-file coverage.info
99+
100+
# Remove external dependencies and test files from coverage
101+
lcov --remove coverage.info \
102+
'/usr/*' \
103+
'*/tests/*' \
104+
'*/examples/*' \
105+
'*/extern/*' \
106+
'*/build/*' \
107+
'*/_deps/*' \
108+
--output-file coverage.info
109+
110+
# Generate HTML report
111+
genhtml coverage.info --output-directory coverage-html
112+
113+
# Generate summary
114+
lcov --list coverage.info > coverage-summary.txt
115+
116+
- name: Display coverage summary
117+
working-directory: build
118+
run: |
119+
echo "=== Coverage Summary ==="
120+
cat coverage-summary.txt
121+
122+
# Extract overall coverage percentage
123+
COVERAGE=$(lcov --summary coverage.info 2>&1 | grep "lines" | awk '{print $2}')
124+
echo "Overall line coverage: $COVERAGE"
125+
126+
# Check if coverage meets threshold (90%)
127+
COVERAGE_NUM=$(echo $COVERAGE | sed 's/%//')
128+
if (( $(echo "$COVERAGE_NUM < 90.0" | bc -l) )); then
129+
echo "⚠️ Warning: Coverage $COVERAGE is below 90% threshold"
130+
else
131+
echo "✅ Coverage $COVERAGE meets 90% threshold"
132+
fi
133+
134+
- name: Upload coverage to Codecov
135+
uses: codecov/codecov-action@v4
136+
with:
137+
token: ${{ secrets.CODECOV_TOKEN }}
138+
files: ./build/coverage.info
139+
fail_ci_if_error: false
140+
verbose: true
141+
142+
- name: Upload coverage HTML report
143+
uses: actions/upload-artifact@v4
144+
with:
145+
name: coverage-report
146+
path: build/coverage-html
147+
retention-days: 30
148+
149+
- name: Comment coverage on PR
150+
if: github.event_name == 'pull_request'
151+
uses: actions/github-script@v7
152+
with:
153+
script: |
154+
const fs = require('fs');
155+
const summary = fs.readFileSync('build/coverage-summary.txt', 'utf8');
156+
const lines = summary.split('\n');
157+
const coverageLine = lines.find(line => line.includes('Total:'));
158+
159+
if (coverageLine) {
160+
const comment = `## 📊 Code Coverage Report\n\n\`\`\`\n${coverageLine}\n\`\`\`\n\n[View detailed report](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})`;
161+
162+
github.rest.issues.createComment({
163+
issue_number: context.issue.number,
164+
owner: context.repo.owner,
165+
repo: context.repo.repo,
166+
body: comment
167+
});
168+
}

0 commit comments

Comments
 (0)