name: Coverage
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
CARGO_TERM_COLOR: always
COVERAGE_FLOOR: "45"
jobs:
coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: llvm-tools-preview
- uses: Swatinem/rust-cache@v2
- name: Install cargo-llvm-cov
uses: taiki-e/install-action@cargo-llvm-cov
- name: Generate coverage (LCOV + summary)
run: |
cargo llvm-cov --workspace \
--ignore-filename-regex 'src/bin/' \
--lcov --output-path lcov.info
cargo llvm-cov report --summary-only | tee coverage-summary.txt
- name: Enforce overall floor
run: |
# Extract the TOTAL line-coverage % from the summary table.
pct=$(awk '/^TOTAL/ {gsub("%", "", $10); print int($10)}' coverage-summary.txt)
echo "Overall line coverage: ${pct}%"
if [ "${pct}" -lt "${COVERAGE_FLOOR}" ]; then
echo "::error::Coverage ${pct}% < floor ${COVERAGE_FLOOR}%"
exit 1
fi
- name: Per-module floors (protocol / layout / workspace)
run: |
# 70% floor on the high-criticality modules.
for module in protocol layout workspace; do
pct=$(cargo llvm-cov report --summary-only \
| awk -v mod="src/${module}.rs" '$1 ~ mod {gsub("%", "", $10); print int($10)}')
if [ -z "${pct}" ]; then
echo "::warning::No coverage data for src/${module}.rs"
continue
fi
echo "src/${module}.rs coverage: ${pct}%"
if [ "${pct}" -lt 70 ]; then
echo "::error::src/${module}.rs coverage ${pct}% < 70%"
exit 1
fi
done
- name: Upload LCOV report
uses: actions/upload-artifact@v4
with:
name: coverage-lcov
path: lcov.info
retention-days: 14
- name: Upload summary
uses: actions/upload-artifact@v4
with:
name: coverage-summary
path: coverage-summary.txt
retention-days: 14
fuzz-smoke:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly
- uses: Swatinem/rust-cache@v2
with:
workspaces: fuzz
- name: Install cargo-fuzz
run: cargo install cargo-fuzz --locked
- name: Fuzz protocol_decode (10 min)
working-directory: fuzz
run: |
cargo fuzz run protocol_decode -- -max_total_time=600 -timeout=10 \
|| echo "::warning::Fuzz target found a crash — see uploaded artifact"
- name: Fuzz snapshot_decode (5 min)
working-directory: fuzz
run: |
cargo fuzz run snapshot_decode -- -max_total_time=300 -timeout=10 \
|| echo "::warning::Fuzz target found a crash — see uploaded artifact"
- name: Upload fuzz crash corpus
if: always()
uses: actions/upload-artifact@v4
with:
name: fuzz-crashes
path: fuzz/artifacts/
if-no-files-found: ignore
retention-days: 30