name: Coverage
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
concurrency:
group: coverage-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
permissions:
contents: read
id-token: write
jobs:
coverage-rust:
runs-on: ubuntu-22.04
name: rust coverage
strategy:
matrix:
llvm-version: [20]
env:
CMAKE_C_COMPILER: clang-${{ matrix.llvm-version }}
CMAKE_CXX_COMPILER: clang++-${{ matrix.llvm-version }}
CC: clang-${{ matrix.llvm-version }}
CXX: clang++-${{ matrix.llvm-version }}
steps:
- uses: actions/checkout@v6
- name: Setup LLVM
run: |
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh ${{ matrix.llvm-version }}
sudo apt-get update
sudo apt-get install --no-install-recommends -y clang-${{ matrix.llvm-version }}
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
components: llvm-tools-preview
- name: Install cargo-llvm-cov
uses: taiki-e/install-action@cargo-llvm-cov
- uses: prefix-dev/setup-pixi@v0.9.4
with:
cache: true
environments: default
- name: Generate rust code coverage
id: coverage
env:
READCON_COV_FEATURES: parallel,chemfiles,zstd,grammar,metatensor
run: |
unset RUSTC_WRAPPER || true
CAPNP_BIN="$(pixi r -e default bash -c 'dirname "$(command -v capnp)"')"
export PATH="${CAPNP_BIN}:${PATH}"
bash scripts/run_coverage_rust.sh rust_codecov.json lcov.info
test -s lcov.info
test -s rust_codecov.json
- name: Upload rust coverage artifact
uses: actions/upload-artifact@v4
with:
name: coverage-rust
path: |
lcov.info
rust_codecov.json
if-no-files-found: error
- name: Upload rust coverage to Codecov
uses: codecov/codecov-action@v5
with:
files: lcov.info,rust_codecov.json
flags: rust
name: readcon-core-rust
use_oidc: true
fail_ci_if_error: false
verbose: true
coverage-python:
runs-on: ubuntu-22.04
name: python coverage
strategy:
matrix:
llvm-version: [20]
env:
CMAKE_C_COMPILER: clang-${{ matrix.llvm-version }}
CMAKE_CXX_COMPILER: clang++-${{ matrix.llvm-version }}
CC: clang-${{ matrix.llvm-version }}
CXX: clang++-${{ matrix.llvm-version }}
steps:
- uses: actions/checkout@v6
- name: Setup LLVM
run: |
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh ${{ matrix.llvm-version }}
sudo apt-get update
sudo apt-get install --no-install-recommends -y \
clang-${{ matrix.llvm-version }} emacs-nox
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
components: llvm-tools-preview
- name: Install cargo-llvm-cov
uses: taiki-e/install-action@cargo-llvm-cov
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Generate python binding coverage (src/python.rs LCOV)
id: coverage
env:
READCON_PY_FEATURES: python,chemfiles
READCON_PY_VENV: ${{ github.workspace }}/.venv-coverage-python
RUSTFLAGS: "-C link-arg=-fuse-ld=bfd"
run: |
unset RUSTC_WRAPPER || true
bash scripts/run_coverage_python.sh python_lcov.info
test -s python_lcov.info
grep -E '^(SF:|DA:)' python_lcov.info | head -20
- name: Upload python coverage artifact
uses: actions/upload-artifact@v4
with:
name: coverage-python
path: python_lcov.info
if-no-files-found: error
- name: Upload python coverage to Codecov
uses: codecov/codecov-action@v5
with:
files: python_lcov.info
flags: python
name: readcon-core-python
use_oidc: true
fail_ci_if_error: false
verbose: true
coverage-julia:
runs-on: ubuntu-22.04
name: julia coverage
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable
- uses: julia-actions/setup-julia@v2
with:
version: '1.10'
- name: Build libreadcon_core
run: cargo build --release --features chemfiles
- name: Julia tests with Coverage.jl
env:
READCON_CORE_LIB: ${{ github.workspace }}/target/release/libreadcon_core.so
READCON_LIB_PATH: ${{ github.workspace }}/target/release/libreadcon_core.so
LD_LIBRARY_PATH: ${{ github.workspace }}/target/release
run: |
set -euo pipefail
ROOT="${{ github.workspace }}"
cd "$ROOT/julia/ReadCon"
julia --project=. -e '
using Pkg
Pkg.instantiate()
Pkg.add("Coverage")
Pkg.test(; coverage=true)
using Coverage
cov = process_folder("src")
LCOV.writefile("lcov.info", cov)
println("Julia coverage files: ", length(cov))
'
test -s lcov.info
# Rewrite SF: paths so Codecov maps under julia/ReadCon/src/**
python3 "$ROOT/scripts/rewrite_julia_lcov.py" \
lcov.info "$ROOT/julia_lcov.info" \
--package-root "$ROOT/julia/ReadCon"
test -s "$ROOT/julia_lcov.info"
grep -E '^(SF:|DA:)' "$ROOT/julia_lcov.info" | head -10
- name: Upload julia coverage artifact
uses: actions/upload-artifact@v4
with:
name: coverage-julia
path: julia_lcov.info
if-no-files-found: error
- name: Upload julia coverage to Codecov
uses: codecov/codecov-action@v5
with:
files: julia_lcov.info
flags: julia
name: readcon-core-julia
use_oidc: true
fail_ci_if_error: false
verbose: true
coverage-fortran:
runs-on: ubuntu-22.04
name: fortran coverage
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable
- name: Install gfortran, fpm, lcov
run: |
sudo apt-get update
sudo apt-get install -y gfortran build-essential cmake lcov
curl -LO https://github.com/fortran-lang/fpm/releases/download/v0.10.1/fpm-0.10.1-linux-x86_64
sudo install -m 755 fpm-0.10.1-linux-x86_64 /usr/local/bin/fpm
- name: Build libreadcon_core (chemfiles)
run: |
for attempt in 1 2 3; do
if cargo build --release --features chemfiles; then
break
fi
if [[ "$attempt" -eq 3 ]]; then
exit 1
fi
echo "cargo build failed (attempt $attempt), retrying..." >&2
sleep 5
done
- name: Fortran instrumented tests + gcov/lcov
env:
GFORTRAN_ERROR_BACKTRACE: "0"
run: |
set -euo pipefail
ROOT="${{ github.workspace }}"
export LD_LIBRARY_PATH="$ROOT/target/release:${LD_LIBRARY_PATH:-}"
FFLAGS="-cpp -ffpe-summary=none --coverage"
EXTRA="-lstdc++ --coverage"
cd "$ROOT/fortran/ReadCon"
rm -rf build
fpm test --flag "-L$ROOT/target/release $FFLAGS" \
--link-flag "-L$ROOT/target/release -lreadcon_core -ldl -lpthread -lm $EXTRA"
find build -name '*.gcda' | head -20
lcov --directory build --capture --output-file "$ROOT/fortran_coverage.info" \
--rc lcov_branch_coverage=1 || \
lcov --directory build --capture --output-file "$ROOT/fortran_coverage.info"
lcov --extract "$ROOT/fortran_coverage.info" '*/fortran/ReadCon/src/*' \
--output-file "$ROOT/fortran_coverage.info" || true
if ! grep -q '^SF:' "$ROOT/fortran_coverage.info" 2>/dev/null; then
lcov --directory build --capture --output-file "$ROOT/fortran_coverage.info"
lcov --remove "$ROOT/fortran_coverage.info" '/usr/*' '*/fpm/*' \
--output-file "$ROOT/fortran_coverage.info" || true
fi
test -s "$ROOT/fortran_coverage.info"
grep -E '^(SF:|DA:)' "$ROOT/fortran_coverage.info" | head -20
- name: Upload fortran coverage artifact
uses: actions/upload-artifact@v4
with:
name: coverage-fortran
path: fortran_coverage.info
if-no-files-found: error
- name: Upload fortran coverage to Codecov
uses: codecov/codecov-action@v5
with:
files: fortran_coverage.info
flags: fortran
name: readcon-core-fortran
use_oidc: true
fail_ci_if_error: false
verbose: true