|
1 | 1 | name: coverage |
2 | 2 |
|
3 | 3 | on: |
4 | | - push: |
5 | | - branches: [prerelease] |
6 | | - pull_request: |
7 | | - branches: [prerelease] |
| 4 | + push: |
| 5 | + branches: [prerelease] |
| 6 | + pull_request: |
| 7 | + branches: [prerelease] |
8 | 8 |
|
9 | 9 | jobs: |
10 | | - coverage: |
11 | | - runs-on: ubuntu-latest |
12 | | - |
13 | | - steps: |
14 | | - - uses: actions/checkout@v4 |
15 | | - |
16 | | - - name: Install dependencies |
17 | | - run: | |
18 | | - sudo apt-get update |
19 | | - sudo apt-get install -y lcov cmake build-essential |
20 | | -
|
21 | | - - name: Configure |
22 | | - run: | |
23 | | - cmake -S . -B build -DENABLE_COVERAGE=ON |
24 | | -
|
25 | | - - name: Build |
26 | | - run: cmake --build build |
27 | | - |
28 | | - - name: Test |
29 | | - run: ctest --test-dir build --output-on-failure |
30 | | - |
31 | | - - name: Generate coverage report |
32 | | - run: | |
33 | | - lcov --capture --directory build --output-file coverage.info |
34 | | - lcov --remove coverage.info '/usr/*' --output-file coverage.info |
35 | | - genhtml coverage.info --output-directory docs/coverage --title "yafl Code Coverage" |
36 | | -
|
37 | | - - name: Normalize coverage HTML timestamps |
38 | | - run: | |
39 | | - # Remove or normalize timestamps from generated HTML to avoid merge conflicts |
40 | | - find docs/coverage -name "*.html" -type f -exec sed -i 's/<td class="headerValue">[^<]*<\/td>/<td class="headerValue">Generated<\/td>/g' {} \; |
41 | | - echo "Normalized timestamps in coverage HTML files" |
42 | | -
|
43 | | - - name: Generate coverage badge |
44 | | - run: | |
45 | | - chmod +x scripts/make_coverage_badge.sh |
46 | | - scripts/make_coverage_badge.sh docs/coverage.svg coverage.info |
47 | | -
|
48 | | - - name: Create GitHub Pages configuration |
49 | | - run: | |
50 | | - touch docs/.nojekyll |
51 | | -
|
52 | | - - name: Commit and push coverage badge to prerelease |
53 | | - if: github.event_name == 'push' && github.ref == 'refs/heads/prerelease' |
54 | | - run: | |
55 | | - git config user.name "GitHub Actions" |
56 | | - git config user.email "actions@github.com" |
57 | | - git add docs/coverage.svg |
58 | | - if git diff --quiet --cached; then |
59 | | - echo "No coverage badge changes to commit" |
60 | | - else |
61 | | - git commit -m "Update code coverage badge [skip ci]" && git push origin prerelease |
62 | | - fi |
| 10 | + coverage-linux: |
| 11 | + strategy: |
| 12 | + fail-fast: false |
| 13 | + matrix: |
| 14 | + include: |
| 15 | + - arch: x86_64 |
| 16 | + runner: ubuntu-latest |
| 17 | + - arch: aarch64 |
| 18 | + runner: ubuntu-24.04-arm |
| 19 | + runs-on: ${{ matrix.runner }} |
| 20 | + |
| 21 | + steps: |
| 22 | + - uses: actions/checkout@v4 |
| 23 | + |
| 24 | + - name: Install dependencies |
| 25 | + run: | |
| 26 | + sudo apt-get update |
| 27 | + sudo apt-get install -y lcov cmake build-essential |
| 28 | +
|
| 29 | + - name: Configure |
| 30 | + run: | |
| 31 | + cmake -S . -B build -DENABLE_COVERAGE=ON |
| 32 | +
|
| 33 | + - name: Build |
| 34 | + run: cmake --build build |
| 35 | + |
| 36 | + - name: Test |
| 37 | + run: ctest --test-dir build --output-on-failure |
| 38 | + |
| 39 | + - name: Generate coverage report |
| 40 | + run: | |
| 41 | + lcov --capture --directory build --output-file coverage.info |
| 42 | + lcov --ignore-errors unused --remove coverage.info '/usr/*' --output-file coverage.info |
| 43 | + genhtml coverage.info --output-directory docs/coverage --title "yafl Code Coverage" |
| 44 | +
|
| 45 | + - name: Generate coverage badge |
| 46 | + run: | |
| 47 | + chmod +x scripts/make_coverage_badge.sh |
| 48 | + scripts/make_coverage_badge.sh docs/coverage_linux_${{ matrix.arch }}.svg coverage.info |
| 49 | +
|
| 50 | + - name: Upload Coverage Artifacts |
| 51 | + uses: actions/upload-artifact@v4 |
| 52 | + with: |
| 53 | + name: coverage-linux-${{ matrix.arch }} |
| 54 | + path: | |
| 55 | + docs/coverage |
| 56 | + docs/coverage_linux_${{ matrix.arch }}.svg |
| 57 | +
|
| 58 | + coverage-windows: |
| 59 | + strategy: |
| 60 | + fail-fast: false |
| 61 | + matrix: |
| 62 | + include: |
| 63 | + - arch: x86_64 |
| 64 | + runner: windows-latest |
| 65 | + cmake_arch: x64 |
| 66 | + # Note: ARM64 Windows coverage skipped - OpenCppCoverage doesn't support ARM64 PE binaries |
| 67 | + # ARM64 coverage is validated via Linux and macOS ARM64 coverage jobs |
| 68 | + runs-on: ${{ matrix.runner }} |
| 69 | + steps: |
| 70 | + - uses: actions/checkout@v4 |
| 71 | + |
| 72 | + - name: Install OpenCppCoverage |
| 73 | + run: | |
| 74 | + choco install opencppcoverage |
| 75 | + echo "C:\Program Files (x86)\OpenCppCoverage" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append |
| 76 | +
|
| 77 | + - name: Configure |
| 78 | + run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -A ${{ matrix.cmake_arch }} |
| 79 | + |
| 80 | + - name: Build |
| 81 | + run: cmake --build build --config Debug |
| 82 | + |
| 83 | + - name: Generate Coverage Report |
| 84 | + run: | |
| 85 | + # Find OpenCppCoverage installation |
| 86 | + $opencppcoverage = Get-ChildItem -Path "C:\Program Files*" -Recurse -Filter "OpenCppCoverage.exe" -ErrorAction SilentlyContinue | Select-Object -First 1 |
| 87 | + if (-not $opencppcoverage) { |
| 88 | + Write-Error "OpenCppCoverage.exe not found" |
| 89 | + exit 1 |
| 90 | + } |
| 91 | + Write-Host "Using OpenCppCoverage from: $($opencppcoverage.FullName)" |
| 92 | + & $opencppcoverage.FullName --sources "${{ github.workspace }}" --cover_children --export_type=html:build/coverage_report --export_type=cobertura:build/cobertura.xml -- ctest --test-dir build -C Debug --output-on-failure |
| 93 | + shell: pwsh |
| 94 | + |
| 95 | + - name: Generate Coverage Badge |
| 96 | + shell: powershell |
| 97 | + run: | |
| 98 | + if (-Not (Test-Path build/cobertura.xml)) { Write-Error "Cobertura XML not found"; exit 1 } |
| 99 | + [xml]$xml = Get-Content build/cobertura.xml |
| 100 | + $rate = $xml.coverage.'line-rate' |
| 101 | + $percentage = [math]::Round([double]$rate * 100) |
| 102 | +
|
| 103 | + if ($percentage -ge 90) { $color = "brightgreen" } |
| 104 | + elseif ($percentage -ge 75) { $color = "yellow" } |
| 105 | + else { $color = "red" } |
| 106 | +
|
| 107 | + $svg = @" |
| 108 | + <svg xmlns="http://www.w3.org/2000/svg" width="120" height="20"> |
| 109 | + <linearGradient id="b" x2="0" y2="100%"> |
| 110 | + <stop offset="0" stop-color="#bbb" stop-opacity=".1"/> |
| 111 | + <stop offset="1" stop-opacity=".1"/> |
| 112 | + </linearGradient> |
| 113 | + <mask id="a"> |
| 114 | + <rect width="120" height="20" rx="3" fill="#fff"/> |
| 115 | + </mask> |
| 116 | + <g mask="url(#a)"> |
| 117 | + <rect width="70" height="20" fill="#555"/> |
| 118 | + <rect x="70" width="50" height="20" fill="$color"/> |
| 119 | + <rect width="120" height="20" fill="url(#b)"/> |
| 120 | + </g> |
| 121 | + <g fill="#fff" text-anchor="middle" |
| 122 | + font-family="DejaVu Sans,Verdana,Geneva,sans-serif" |
| 123 | + font-size="11"> |
| 124 | + <text x="35" y="14">coverage</text> |
| 125 | + <text x="95" y="14">${percentage}%</text> |
| 126 | + </g> |
| 127 | + </svg> |
| 128 | + "@ |
| 129 | +
|
| 130 | + New-Item -ItemType Directory -Force -Path docs |
| 131 | + $badgePath = "docs/coverage_windows_${{ matrix.arch }}.svg" |
| 132 | + Set-Content -Path $badgePath -Value $svg |
| 133 | + if (Test-Path $badgePath) { |
| 134 | + Write-Host "Badge created: $badgePath (${percentage}% coverage)" |
| 135 | + Get-Content $badgePath | Select-Object -First 5 |
| 136 | + } else { |
| 137 | + Write-Error "Failed to create badge file" |
| 138 | + exit 1 |
| 139 | + } |
| 140 | +
|
| 141 | + - name: Upload Coverage Report |
| 142 | + uses: actions/upload-artifact@v4 |
| 143 | + with: |
| 144 | + name: coverage-windows-${{ matrix.arch }} |
| 145 | + path: | |
| 146 | + build/coverage_report |
| 147 | + docs/coverage_windows_${{ matrix.arch }}.svg |
| 148 | +
|
| 149 | + coverage-macos: |
| 150 | + strategy: |
| 151 | + fail-fast: false |
| 152 | + matrix: |
| 153 | + include: |
| 154 | + - arch: x86_64 |
| 155 | + runner: macos-15-intel |
| 156 | + cmake_arch: x86_64 |
| 157 | + - arch: aarch64 |
| 158 | + runner: macos-latest |
| 159 | + cmake_arch: arm64 |
| 160 | + runs-on: ${{ matrix.runner }} |
| 161 | + steps: |
| 162 | + - uses: actions/checkout@v4 |
| 163 | + |
| 164 | + - name: Install dependencies |
| 165 | + run: brew install lcov |
| 166 | + |
| 167 | + - name: Configure |
| 168 | + run: | |
| 169 | + cmake -S . -B build \ |
| 170 | + -DENABLE_COVERAGE=ON \ |
| 171 | + -DCMAKE_BUILD_TYPE=Debug \ |
| 172 | + -DCMAKE_OSX_ARCHITECTURES=${{ matrix.cmake_arch }} |
| 173 | +
|
| 174 | + - name: Build |
| 175 | + run: cmake --build build |
| 176 | + |
| 177 | + - name: Test |
| 178 | + run: ctest --test-dir build --output-on-failure |
| 179 | + |
| 180 | + - name: Create gcov wrapper |
| 181 | + run: | |
| 182 | + cat > /usr/local/bin/llvm-gcov << 'EOF' |
| 183 | + #!/bin/bash |
| 184 | + exec xcrun llvm-cov gcov "$@" |
| 185 | + EOF |
| 186 | + chmod +x /usr/local/bin/llvm-gcov |
| 187 | +
|
| 188 | + - name: Generate Coverage Report |
| 189 | + run: | |
| 190 | + lcov --gcov-tool llvm-gcov --capture --directory build --output-file coverage.info |
| 191 | + lcov --gcov-tool llvm-gcov --ignore-errors unused --remove coverage.info '/usr/*' --output-file coverage.info |
| 192 | + genhtml coverage.info --output-directory docs/coverage --title "yafl Code Coverage" |
| 193 | +
|
| 194 | + - name: Generate Coverage Badge |
| 195 | + run: | |
| 196 | + chmod +x scripts/make_coverage_badge.sh |
| 197 | + scripts/make_coverage_badge.sh docs/coverage_macos_${{ matrix.arch }}.svg coverage.info |
| 198 | +
|
| 199 | + - name: Upload Coverage Report |
| 200 | + uses: actions/upload-artifact@v4 |
| 201 | + with: |
| 202 | + name: coverage-macos-${{ matrix.arch }} |
| 203 | + path: | |
| 204 | + docs/coverage |
| 205 | + docs/coverage_macos_${{ matrix.arch }}.svg |
| 206 | +
|
| 207 | + commit-badges: |
| 208 | + needs: [coverage-linux, coverage-macos, coverage-windows] |
| 209 | + runs-on: ubuntu-latest |
| 210 | + if: always() && github.event_name == 'push' && github.ref == 'refs/heads/prerelease' |
| 211 | + steps: |
| 212 | + - uses: actions/checkout@v4 |
| 213 | + |
| 214 | + - name: Download all artifacts |
| 215 | + uses: actions/download-artifact@v4 |
| 216 | + with: |
| 217 | + path: artifacts |
| 218 | + |
| 219 | + - name: Move badges |
| 220 | + run: | |
| 221 | + mkdir -p docs |
| 222 | + find artifacts -name "coverage_*.svg" -exec cp {} docs/ \; |
| 223 | +
|
| 224 | + - name: Create GitHub Pages configuration |
| 225 | + run: | |
| 226 | + touch docs/.nojekyll |
| 227 | +
|
| 228 | + - name: Commit and push coverage badges |
| 229 | + run: | |
| 230 | + git config user.name "GitHub Actions" |
| 231 | + git config user.email "actions@github.com" |
| 232 | + git add docs/coverage_*.svg docs/.nojekyll |
| 233 | + if git diff --quiet --cached; then |
| 234 | + echo "No coverage badge changes to commit" |
| 235 | + else |
| 236 | + git commit -m "Update code coverage badges [skip ci]" && git push origin prerelease |
| 237 | + fi |
0 commit comments