Skip to content

Issue 1820 - Enforce free surface boundary #84

Issue 1820 - Enforce free surface boundary

Issue 1820 - Enforce free surface boundary #84

Workflow file for this run

name: Coverage
# LLVM source-based coverage (Clang). Independent of the gcc unittests/compilation
# jobs. Builds the instrumented `coverage` preset, runs the C++ unit tests, and
# uploads the lcov trace to Codecov.
#
# Two modes, same build:
# - push to main/devel -> FULL report (Codecov project baseline + HTML artifact).
# - pull_request -> Codecov computes the PATCH status (coverage of the
# lines the PR changes); blocks if <75% of changed core/
# lines are covered (see codecov.yml). Skips the
# expensive HTML report. Only fires when core/ changes.
#
# A ccache compiler cache (persisted via actions cache) keeps repeat PR pushes fast.
on:
push:
branches:
- main
- devel
pull_request:
types: [opened, synchronize, reopened]
branches:
- main
- devel
paths:
- 'core/**'
jobs:
coverage:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install toolchain
run: |
sudo apt-get update
sudo apt-get install -y clang llvm gfortran lcov ccache
- name: Install uv
uses: astral-sh/setup-uv@v5
- name: Install CMake 3.29
run: |
uv run pip install 'cmake>=3.29'
- name: Build, test, and generate coverage
env:
# Wire ccache as the compiler launcher (CI-only; the coverage preset is
# untouched). CCACHE_BASEDIR normalises absolute paths so cache entries
# are reused across runs.
CMAKE_EXTRA_ARGS: "-DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_C_COMPILER_LAUNCHER=ccache"
CCACHE_BASEDIR: ${{ github.workspace }}
run: |
# Pick llvm tools matching the installed clang so `llvm-profdata merge`
# does not hit a version mismatch; fall back to unversioned names.
LLVM_VER="$(clang --version | sed -nE 's/.*version ([0-9]+).*/\1/p' | head -1)"
export LLVM_PROFDATA="llvm-profdata-${LLVM_VER}"
export LLVM_COV="llvm-cov-${LLVM_VER}"
command -v "$LLVM_PROFDATA" >/dev/null 2>&1 || export LLVM_PROFDATA="llvm-profdata"
command -v "$LLVM_COV" >/dev/null 2>&1 || export LLVM_COV="llvm-cov"
# PRs only need the lcov (Codecov derives the patch status from it) and
# the terminal summary -- skip the costly HTML report. Push builds `all`
# (adds the browsable HTML report uploaded as an artifact below).
TARGETS="${{ github.event_name == 'pull_request' && 'build/coverage/coverage.lcov build/coverage/coverage-summary.txt' || 'all' }}"
uvx --from snakemake==9.13.4 snakemake -s scripts/coverage.smk --cores all $TARGETS
- name: Deduplicate lcov for upload
run: |
# coverage.lcov concatenates one trace per test binary, so most
# core/specfem files appear many times. lcov -a collapses the duplicate
# records into one (much smaller upload). Codecov would merge them
# anyway, so on any lcov error we just keep the raw file.
raw=build/coverage/coverage.lcov
out=build/coverage/coverage.dedup.lcov
if lcov --add-tracefile "$raw" --output-file "$out" \
--ignore-errors inconsistent,corrupt,unused,empty,format,unsupported,range 2>/dev/null \
&& [ -s "$out" ]; then
mv "$out" "$raw"
echo "deduplicated: $(grep -c '^SF:' "$raw") records, $(wc -c < "$raw") bytes"
else
echo "lcov dedup unavailable/failed; uploading raw coverage.lcov" >&2
fi
- name: Upload coverage to Codecov
# On push this is the full project report; on a PR, Codecov uses it to
# compute the patch status (the merge gate). The CODECOV_TOKEN secret is
# unavailable to fork PRs, so the gate only applies to same-repo branches.
uses: codecov/codecov-action@v4
with:
files: build/coverage/coverage.lcov
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: false
- name: Upload HTML report artifact
# Only produced on push (PRs skip the HTML report to save time).
if: github.event_name != 'pull_request'
uses: actions/upload-artifact@v4
with:
name: coverage-html
path: build/coverage/coverage-html