From cb13699b5ff9eee633773c07aaa4a5caeb960fce Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 7 May 2026 23:47:58 +0000 Subject: [PATCH] ci(codecov): add advisory coverage workflow Adds .github/workflows/coverage.yml for Codecov integration. The workflow runs: - On push to main (required for repository coverage tracking) - On workflow_dispatch (manual trigger for ad-hoc coverage checks) - On PRs labeled with 'coverage', 'full-ci', or 'ci:full' (opt-in coverage runs) The coverage job: - Uses cargo-llvm-cov to generate coverage reports in JSON, LCOV, and text formats - Validates that all coverage artifacts are present and non-empty - Detects the presence of CODECOV_TOKEN secret for conditional uploads - Fails hard on main-branch uploads (fail_ci_if_error: true) - Fails soft on advisory PR uploads (fail_ci_if_error: false) - Artifacts coverage reports for 14 days Codecov claim boundary: Rust execution-surface evidence only. Does not prove diff parser, rule evaluation, suppression, renderer, LSP, baseline, mutation, fuzz, or release correctness. https://claude.ai/code/session_01VboXJ243Rjf8hJFzcdVJWE --- .github/workflows/coverage.yml | 128 +++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 .github/workflows/coverage.yml diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml new file mode 100644 index 00000000..46db97e2 --- /dev/null +++ b/.github/workflows/coverage.yml @@ -0,0 +1,128 @@ +name: Coverage +on: + push: + branches: [main] + paths: + - "Cargo.toml" + - "Cargo.lock" + - "crates/**" + - "bench/**" + - "xtask/**" + - ".github/workflows/coverage.yml" + - "codecov.yml" + - "docs/ci/coverage.md" + pull_request: + types: [opened, synchronize, reopened, labeled] + branches: [main] + paths: + - "Cargo.toml" + - "Cargo.lock" + - "crates/**" + - "bench/**" + - "xtask/**" + - ".github/workflows/coverage.yml" + - "codecov.yml" + - "docs/ci/coverage.md" + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: coverage-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +env: + CARGO_TERM_COLOR: always + CARGO_INCREMENTAL: "0" + RUSTFLAGS: "-C debuginfo=0" + +jobs: + coverage: + name: Codecov Coverage + runs-on: ubuntu-latest + timeout-minutes: 45 + if: >- + github.event_name == 'push' || + github.event_name == 'workflow_dispatch' || + contains(github.event.pull_request.labels.*.name, 'coverage') || + contains(github.event.pull_request.labels.*.name, 'full-ci') || + contains(github.event.pull_request.labels.*.name, 'ci:full') + steps: + - uses: actions/checkout@v4 + - name: Install Rust + uses: dtolnay/rust-toolchain@master + with: + toolchain: "1.92" + components: llvm-tools-preview + - name: Use larger target dir + run: echo "CARGO_TARGET_DIR=${RUNNER_TEMP}/target" >> "$GITHUB_ENV" + - uses: Swatinem/rust-cache@v2 + with: + cache-on-failure: true + cache-directories: ${{ runner.temp }}/target + save-if: ${{ github.ref == 'refs/heads/main' }} + - name: Install cargo-llvm-cov + uses: taiki-e/install-action@v2 + with: + tool: cargo-llvm-cov + - name: Generate coverage + env: + CI: true + INSTA_UPDATE: "no" + PROPTEST_CASES: "100" + run: | + set -euo pipefail + cargo llvm-cov clean --workspace + cargo llvm-cov test \ + --workspace \ + --locked \ + --all-features \ + --no-report + cargo llvm-cov report --json --output-path coverage.json + cargo llvm-cov report --lcov --output-path lcov.info + cargo llvm-cov report --text | tee coverage.txt + - name: Validate coverage output + run: | + set -euo pipefail + test -s coverage.json + test -s coverage.txt + test -s lcov.info + - name: Detect Codecov token + id: codecov-token + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + run: | + if [ -n "${CODECOV_TOKEN:-}" ]; then + echo "present=true" >> "$GITHUB_OUTPUT" + else + echo "present=false" >> "$GITHUB_OUTPUT" + fi + - name: Upload coverage to Codecov (main) + if: ${{ always() && github.event_name == 'push' && hashFiles('lcov.info') != '' && steps.codecov-token.outputs.present == 'true' }} + uses: codecov/codecov-action@v5 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: lcov.info + flags: rust-core + name: diffguard-rust-core + fail_ci_if_error: true + - name: Upload coverage to Codecov (advisory) + if: ${{ always() && github.event_name != 'push' && hashFiles('lcov.info') != '' && steps.codecov-token.outputs.present == 'true' }} + uses: codecov/codecov-action@v5 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: lcov.info + flags: rust-core + name: diffguard-rust-core + fail_ci_if_error: false + - name: Upload coverage artifacts + if: always() + uses: actions/upload-artifact@v4 + with: + name: coverage-report + path: | + coverage.json + coverage.txt + lcov.info + retention-days: 14