Skip to content

CI

CI #6

Workflow file for this run

name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
- cron: '0 4 * * 1' # Weekly: Monday 04:00 UTC
jobs:
# ── Build matrix ─────────────────────────────────────────────────────────────
build-and-test:
name: ${{ matrix.name }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
# Linux / GCC
- name: "Linux GCC Debug"
os: ubuntu-24.04
cc: gcc-14
cxx: g++-14
build_type: Debug
- name: "Linux GCC Release"
os: ubuntu-24.04
cc: gcc-14
cxx: g++-14
build_type: Release
# Linux / Clang
- name: "Linux Clang Debug"
os: ubuntu-24.04
cc: clang-18
cxx: clang++-18
build_type: Debug
- name: "Linux Clang Release"
os: ubuntu-24.04
cc: clang-18
cxx: clang++-18
build_type: Release
# macOS / AppleClang
- name: "macOS Debug"
os: macos-14
cc: clang
cxx: clang++
build_type: Debug
- name: "macOS Release"
os: macos-14
cc: clang
cxx: clang++
build_type: Release
# Windows / MSVC
- name: "Windows Debug"
os: windows-2022
build_type: Debug
- name: "Windows Release"
os: windows-2022
build_type: Release
steps:
- uses: actions/checkout@v4
- name: Install GCC 14 (Linux)
if: runner.os == 'Linux' && startsWith(matrix.cxx, 'g++')
run: |
sudo apt-get update -y
sudo apt-get install -y gcc-14 g++-14
- name: Install Clang 18 (Linux)
if: runner.os == 'Linux' && startsWith(matrix.cxx, 'clang++')
run: |
sudo apt-get update -y
sudo apt-get install -y clang-18
# Cache FetchContent downloads (GTest) to avoid re-downloading on every run.
- name: Cache CMake dependencies
uses: actions/cache@v4
with:
path: build/_deps
key: deps-${{ runner.os }}-${{ matrix.cxx }}-${{ hashFiles('tests/CMakeLists.txt') }}
restore-keys: deps-${{ runner.os }}-${{ matrix.cxx }}-
- name: Configure (non-Windows)
if: runner.os != 'Windows'
env:
CC: ${{ matrix.cc }}
CXX: ${{ matrix.cxx }}
run: |
cmake -B build \
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \
-DONPAIR_BUILD_TESTS=ON
- name: Configure (Windows)
if: runner.os == 'Windows'
run: |
cmake -B build `
-DONPAIR_BUILD_TESTS=ON
- name: Build
run: cmake --build build --config ${{ matrix.build_type }} --parallel
- name: Test
run: ctest --test-dir build --build-config ${{ matrix.build_type }} --output-on-failure --parallel 4
# ── Performance configuration (LTO + native arch) ───────────────────────────
#
# The default portability matrix above never exercises the configuration that
# real benchmark users will run (-DONPAIR_ENABLE_LTO=ON -DONPAIR_NATIVE_ARCH=ON).
# This dedicated job keeps that path green: it catches code that builds in the
# portable configuration but breaks under aggressive inlining or LTO link-time
# whole-program analysis. -march=native is safe within a single CI job because
# build and test execute on the same runner (no cross-machine binary reuse).
perf-build:
name: "Linux Clang Release + LTO + native"
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Install Clang 18
run: |
sudo apt-get update -y
sudo apt-get install -y clang-18
- name: Cache CMake dependencies
uses: actions/cache@v4
with:
path: build_perf/_deps
key: deps-perf-${{ hashFiles('tests/CMakeLists.txt') }}
- name: Configure
env:
CC: clang-18
CXX: clang++-18
run: |
cmake -B build_perf \
-DCMAKE_BUILD_TYPE=Release \
-DONPAIR_BUILD_TESTS=ON \
-DONPAIR_ENABLE_LTO=ON \
-DONPAIR_NATIVE_ARCH=ON
- name: Build
run: cmake --build build_perf --parallel
- name: Test
run: ctest --test-dir build_perf --output-on-failure --parallel 4
# ── Sanitizers ───────────────────────────────────────────────────────────────
sanitizers:
name: ${{ matrix.name }}
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
include:
- name: "ASan + UBSan"
flags: "-fsanitize=address,undefined -fno-omit-frame-pointer"
env: "ASAN_OPTIONS=detect_leaks=0 UBSAN_OPTIONS=halt_on_error=1:print_stacktrace=1"
- name: "TSan"
flags: "-fsanitize=thread"
env: "TSAN_OPTIONS=halt_on_error=1"
steps:
- uses: actions/checkout@v4
- name: Install Clang 18
run: |
sudo apt-get update -y
sudo apt-get install -y clang-18
- name: Cache CMake dependencies
uses: actions/cache@v4
with:
path: build_san/_deps
key: deps-san-${{ matrix.name }}-${{ hashFiles('tests/CMakeLists.txt') }}
- name: Configure
env:
CC: clang-18
CXX: clang++-18
run: |
cmake -B build_san \
-DCMAKE_BUILD_TYPE=Debug \
-DONPAIR_BUILD_TESTS=ON \
-DCMAKE_CXX_FLAGS="${{ matrix.flags }}" \
-DCMAKE_EXE_LINKER_FLAGS="${{ matrix.flags }}"
- name: Build
run: cmake --build build_san --parallel
- name: Test
run: |
${{ matrix.env }} ctest --test-dir build_san --output-on-failure --parallel 4
# ── Coverage (merge to main only) ────────────────────────────────────────────
coverage:
name: "Code Coverage"
runs-on: ubuntu-24.04
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update -y
sudo apt-get install -y gcc-14 g++-14 lcov
- name: Cache CMake dependencies
uses: actions/cache@v4
with:
path: build_cov/_deps
key: deps-cov-${{ hashFiles('tests/CMakeLists.txt') }}
- name: Configure
env:
CC: gcc-14
CXX: g++-14
run: |
cmake -B build_cov \
-DCMAKE_BUILD_TYPE=Debug \
-DONPAIR_BUILD_TESTS=ON \
-DCMAKE_CXX_FLAGS="--coverage -O0" \
-DCMAKE_EXE_LINKER_FLAGS="--coverage"
- name: Build
run: cmake --build build_cov --parallel
- name: Test
run: ctest --test-dir build_cov --output-on-failure --parallel 4
- name: Generate coverage report
run: |
lcov --gcov-tool gcov-14 --capture --directory build_cov --output-file coverage.info --ignore-errors mismatch
lcov --remove coverage.info \
'*/googletest/*' '*/gtest/*' '*/tests/*' '/usr/*' \
--output-file coverage_filtered.info --ignore-errors mismatch,unused
lcov --list coverage_filtered.info
- name: Upload to Codecov
uses: codecov/codecov-action@v4
with:
files: coverage_filtered.info
fail_ci_if_error: false