Skip to content

ci: pin bash on the derive-version step (dash lacks ${VAR::7}) #32

ci: pin bash on the derive-version step (dash lacks ${VAR::7})

ci: pin bash on the derive-version step (dash lacks ${VAR::7}) #32

Workflow file for this run

name: coverage
# Build the unit-test binaries with --coverage, run ctest, generate a
# gcov report, upload to Codecov. Drives the badge in README.md.
#
# Scope: src/utils/*.cc (cfg_handler, logs_handler, peer_parser) — the
# files actually exercised by the unit suite under tests/unit/. Coverage
# of the daemon hot path (mdt_dialout_core.cc, dataManipulation/, etc.)
# is provided by the e2e harness in podman containers and isn't merged
# into this report — see README's coverage note.
on:
push:
branches: [main, high-prio-fixes]
pull_request:
branches: [main]
permissions:
contents: write # publish-badge step force-pushes to the `badges` branch.
jobs:
unit-coverage:
runs-on: ubuntu-latest
container:
image: debian:bookworm-slim
steps:
- name: bootstrap
run: |
export DEBIAN_FRONTEND=noninteractive
apt-get update -qq
apt-get install -y --no-install-recommends \
git ca-certificates \
cmake g++ make pkg-config gcovr \
libspdlog-dev libfmt-dev libconfig++-dev libgtest-dev \
curl >/dev/null
- uses: actions/checkout@v5
- name: configure with --coverage
run: |
cmake -S tests -B build-cov \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_CXX_FLAGS="--coverage -O0 -g" \
-DCMAKE_EXE_LINKER_FLAGS="--coverage"
- name: build
run: cmake --build build-cov -j"$(nproc)"
- name: run unit tests
run: ctest --test-dir build-cov --output-on-failure
- name: generate coverage report
run: |
# Filter to the project source files we actually unit-test;
# vendored headers (src/include/, src/proto/) and test files
# themselves are excluded so the % reflects production code.
# The build dir is the positional arg so gcovr finds the
# .gcno/.gcda files generated by --coverage.
gcovr --root . \
--filter 'src/utils/' \
--exclude 'src/include/' \
--exclude 'src/proto/' \
--exclude 'tests/' \
--xml-pretty --output coverage.xml \
--print-summary \
build-cov
- name: upload to Codecov
# codecov-action v5 requires a token even for OSS repos; without one
# this step fails. continue-on-error so it doesn't abort the rest of
# the job (the publish-badge step has to run regardless).
continue-on-error: true
uses: codecov/codecov-action@v5
with:
files: coverage.xml
flags: unit
fail_ci_if_error: false
verbose: true
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
- name: publish coverage badge to `badges` branch
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
shell: bash
run: |
set -eu
# Extract overall line-rate from gcovr's Cobertura XML.
line_rate=$(grep -oE 'line-rate="[0-9.]+"' coverage.xml | head -1 | grep -oE '[0-9.]+')
pct=$(awk -v r="${line_rate}" 'BEGIN{printf "%.1f", r*100}')
if awk -v p="${pct}" 'BEGIN{exit !(p>=90)}'; then color=brightgreen
elif awk -v p="${pct}" 'BEGIN{exit !(p>=80)}'; then color=green
elif awk -v p="${pct}" 'BEGIN{exit !(p>=70)}'; then color=yellowgreen
elif awk -v p="${pct}" 'BEGIN{exit !(p>=50)}'; then color=yellow
else color=red
fi
tmp=$(mktemp -d)
cat > "${tmp}/coverage.json" <<EOF
{"schemaVersion":1,"label":"coverage","message":"${pct}%","color":"${color}"}
EOF
# Force-push a single-commit orphan `badges` branch — keeps it tiny
# and decoupled from main history; only `coverage.json` lives there.
cd "${tmp}"
git init -q -b badges
git -c user.name="github-actions[bot]" \
-c user.email="41898282+github-actions[bot]@users.noreply.github.com" \
add coverage.json
git -c user.name="github-actions[bot]" \
-c user.email="41898282+github-actions[bot]@users.noreply.github.com" \
commit -q -m "coverage: ${pct}%"
git remote add origin \
"https://x-access-token:${GH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git"
git push -q --force origin badges
echo "::notice title=coverage badge::${pct}% (${color})"