Contents
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:
- Never fail the build on overall project coverage — the uninstrumentable pgrx modules structurally suppress the percentage below any reasonable gate.
- Enforce coverage on patch (PR diffs) for
src/dvm/— this is the pure-Rust differential engine where quality matters most and coverage is meaningful. - Ignore uninstrumentable modules from all reporting to avoid noise.
# 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:
- 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_TOKENsecret added to GitHub repository - [x]
coverage.ymlworkflow collectslcov.infoviacargo-llvm-cov - [x]
LD_PRELOADstub (libpg_stub.so) enables linking on Linux - [ ] Move
CODECOV_TOKENfromenv:towith:in upload step - [ ] Create
codecov.ymlat 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:
- Compile PostgreSQL itself with coverage instrumentation
- Build the extension
.sowithRUSTFLAGS="-C instrument-coverage" - Run E2E tests against that PostgreSQL
- Merge LLVM profdata from the
.sowith 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.