feat: cross-platform CI matrix, sandbox hardening, and operator tooling #145
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Coverage | |
| on: | |
| push: | |
| branches: [main, develop] | |
| pull_request: | |
| branches: [main, develop] | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| defaults: | |
| run: | |
| shell: bash | |
| env: | |
| DEBIAN_FRONTEND: noninteractive | |
| COMMON_DEPS: >- | |
| cmake make pkg-config | |
| gcc lcov | |
| libsnmp-dev default-libmysqlclient-dev help2man libssl-dev | |
| libseccomp-dev libuv1-dev | |
| COVERAGE_MIN_LINE_PCT: '10.0' | |
| CFLAGS_COVERAGE: >- | |
| -O0 -g3 --coverage | |
| LDFLAGS_COVERAGE: --coverage | |
| jobs: | |
| gcc-coverage: | |
| name: gcc coverage | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | |
| - name: Install coverage dependencies | |
| uses: ./.github/actions/install-apt-deps | |
| with: | |
| packages: ${{ env.COMMON_DEPS }} | |
| - name: Configure | |
| env: | |
| LDFLAGS: ${{ env.LDFLAGS_COVERAGE }} | |
| run: | | |
| set -euo pipefail | |
| cmake -B build -DCMAKE_BUILD_TYPE=Debug \ | |
| -DCMAKE_C_COMPILER=gcc \ | |
| -DCMAKE_C_FLAGS="${CFLAGS_COVERAGE}" | |
| - name: Build | |
| run: | | |
| set -euo pipefail | |
| cmake --build build -j"$(nproc)" | |
| - name: Test | |
| run: | | |
| set -euo pipefail | |
| ctest --test-dir build --output-on-failure || echo "::notice::ctest returned non-zero; continuing to collect coverage." | |
| - name: Generate lcov + genhtml report | |
| run: | | |
| set -euo pipefail | |
| if lcov --capture --directory build --output-file coverage.raw.info --ignore-errors mismatch; then | |
| lcov \ | |
| --remove coverage.raw.info \ | |
| '/usr/*' \ | |
| '*/build/*' \ | |
| '*/tests/*' \ | |
| '*/test/*' \ | |
| --output-file coverage.filtered.info \ | |
| --ignore-errors unused | |
| genhtml coverage.filtered.info --output-directory coverage-html | |
| else | |
| echo "::warning::No coverage data files were found." | |
| mkdir -p coverage-html | |
| echo "No coverage data generated." > coverage-html/index.html | |
| : > coverage.filtered.info | |
| fi | |
| - name: Enforce minimum line coverage | |
| run: | | |
| set -euo pipefail | |
| if [[ ! -s coverage.filtered.info ]]; then | |
| echo "::error::coverage.filtered.info is empty. Coverage gating requires generated coverage data." | |
| exit 1 | |
| fi | |
| summary="$(lcov --summary coverage.filtered.info)" | |
| echo "${summary}" | |
| line_pct="$(printf '%s\n' "${summary}" | awk '/lines\.*:/ {gsub("%","",$2); print $2; exit}')" | |
| if [[ -z "${line_pct}" ]]; then | |
| echo "::error::Unable to parse line coverage percentage from lcov summary." | |
| exit 1 | |
| fi | |
| if ! awk -v actual="${line_pct}" -v min="${COVERAGE_MIN_LINE_PCT}" 'BEGIN { exit ((actual + 0) >= (min + 0) ? 0 : 1) }'; then | |
| echo "::error::Line coverage ${line_pct}% is below minimum ${COVERAGE_MIN_LINE_PCT}%." | |
| exit 1 | |
| fi | |
| echo "Coverage gate passed: ${line_pct}% >= ${COVERAGE_MIN_LINE_PCT}%." | |
| - name: Upload coverage artifacts | |
| if: always() | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.1 | |
| with: | |
| name: coverage-report | |
| path: | | |
| coverage.filtered.info | |
| coverage-html | |
| if-no-files-found: ignore |