# Codecov Integration Plan ## Status: Done Confirmed live at https://app.codecov.io/github/grove/pg-trickle (March 2026). The `CODECOV_TOKEN` secret has been added to the GitHub repository. The coverage workflow (`coverage.yml`) already collects `lcov.info` via `cargo-llvm-cov` and uploads it to Codecov. This plan captures scope decisions, configuration, and known limitations for the project record. --- ## What Codecov covers in this project This is a pgrx extension. Coverage instrumentation runs against the Rust test binary (`cargo test --lib`), not against the `.so` loaded by the PostgreSQL server process. This shapes what Codecov can and cannot measure. ### Covered (meaningful signal) | Module | Why it's well-covered | |---|---| | `src/dvm/parser.rs` | 910+ pure-Rust unit tests, no pgrx boundary | | `src/dvm/operators/` | Exhaustive operator unit tests | | `src/dvm/diff.rs` | Delta SQL generation, fully unit-tested | | `src/dag.rs` | Graph logic, property tests | | `src/hash.rs` | Deterministic hashing, unit-tested | | `src/error.rs` | Enum variants, trivially covered | | `src/refresh.rs` (pure logic only) | `classify_relkind`, `strip_view_definition_suffix` | ### Not covered (structural limitation, not a gap) | Module | Why it can't be covered | |---|---| | `src/api.rs` | `#[pg_extern]` functions — execute inside postgres process | | `src/cdc.rs` | Trigger-based CDC — runs as a PostgreSQL trigger callback | | `src/wal_decoder.rs` | WAL polling — runs inside postgres backend | | `src/scheduler.rs` | Background worker — separate postgres process | | `src/hooks.rs` | DDL event trigger planner hook | | `src/shmem.rs` | Shared memory init — postgres startup only | These modules are covered by the E2E test suite (384 tests in Docker) but that coverage is not instrumentable without a full PostgreSQL coverage build. --- ## Codecov configuration (`codecov.yml`) Placed at the repository root. Key decisions: 1. **Never fail the build on overall project coverage** — the uninstrumentable pgrx modules structurally suppress the percentage below any reasonable gate. 2. **Enforce coverage on patch (PR diffs) for `src/dvm/`** — this is the pure-Rust differential engine where quality matters most and coverage is meaningful. 3. **Ignore uninstrumentable modules** from all reporting to avoid noise. ```yaml # codecov.yml coverage: status: project: default: informational: true # never fail CI on overall % patch: dvm-engine: target: 70% paths: - "src/dvm/**" - "src/dag.rs" - "src/hash.rs" ignore: - "src/api.rs" - "src/cdc.rs" - "src/wal_decoder.rs" - "src/scheduler.rs" - "src/hooks.rs" - "src/shmem.rs" - "src/bin/**" - "tests/**" - "benches/**" ``` --- ## Workflow (`coverage.yml`) ### Current state The workflow already: - Installs `cargo-llvm-cov` via `taiki-e/install-action` - Builds `libpg_stub.so` for `LD_PRELOAD` (provides NULL stubs for PG symbols) - Runs `cargo llvm-cov --lib --features pg18` to produce `lcov.info` - Uploads to Codecov via `codecov/codecov-action@v5` - Uploads `lcov.info` as a workflow artifact ### Token placement The `CODECOV_TOKEN` must be in `with:`, not `env:`, for `codecov-action@v5`: ```yaml - name: Upload coverage to Codecov uses: codecov/codecov-action@v5 with: token: ${{ secrets.CODECOV_TOKEN }} files: coverage/lcov.info flags: unittests fail_ci_if_error: false ``` ### Triggers Coverage runs on: - Push to `main` when `src/**`, `Cargo.toml`, or `Cargo.lock` change - Manual `workflow_dispatch` It does NOT run on every PR (cost-saving decision — unit tests run on PR, coverage upload is post-merge). --- ## Implementation checklist - [x] `CODECOV_TOKEN` secret added to GitHub repository - [x] `coverage.yml` workflow collects `lcov.info` via `cargo-llvm-cov` - [x] `LD_PRELOAD` stub (`libpg_stub.so`) enables linking on Linux - [ ] Move `CODECOV_TOKEN` from `env:` to `with:` in upload step - [ ] Create `codecov.yml` at repository root - [ ] Add Codecov badge to `README.md` - [ ] Verify first upload shows coverage on Codecov dashboard --- ## Expected baseline numbers Based on module analysis: | Scope | Expected coverage | |---|---| | `src/dvm/**` | ~75–85% | | `src/dag.rs` | ~80% | | `src/hash.rs` | ~90% | | Overall project | ~25–35% (structurally limited by pgrx) | The overall number will look low to outside observers. The Codecov badge should link to the `src/dvm/` coverage view, or the README should note the structural limitation. --- ## Future: E2E coverage (stretch goal) To get meaningful coverage for `api.rs`, `cdc.rs`, etc., a PostgreSQL coverage build would be needed: 1. Compile PostgreSQL itself with coverage instrumentation 2. Build the extension `.so` with `RUSTFLAGS="-C instrument-coverage"` 3. Run E2E tests against that PostgreSQL 4. Merge LLVM profdata from the `.so` with the server's gcov data This is a significant engineering investment and is not planned for v1.0. Tracked as a potential post-1.0 improvement.