ci: measure PyO3 binding Rust-layer coverage (cargo-llvm-cov + pytest)#64
Conversation
The core coverage.yml job is scoped -p ordvec, so the binding's FFI guard layer (ordvec-python/src/lib.rs) had no coverage signal. coverage-python.yml fills the gap: cargo-llvm-cov instruments the cdylib via show-env's RUSTC_WRAPPER, maturin builds that instrumented extension into a venv, pytest drives it, and report -p ordvec-python aggregates the per-process profraw. Uploaded to Codecov under a python-binding flag (tracked apart from the core line); informational, no floor yet. Measured locally against the full pytest suite (incl. the binding red-team from #63) at 84.1% line / 70.0% function — the uncovered share is mostly unreachable FFI error arms (from_shape_vec map_err; checked_mul usize-overflow guards that can't fire on 64-bit). The job reports whatever the suite exercises, so the number rises once #63's red-team tests reach main. Signed-off-by: Nelson Spence <nelson@projectnavi.ai>
|
Note Gemini is unable to generate a review for this pull request due to the file types involved not being currently supported. |
Review Summary by QodoAdd PyO3 binding Rust-layer coverage measurement workflow
WalkthroughsDescription• Adds coverage measurement for PyO3 binding's Rust FFI layer • Uses cargo-llvm-cov to instrument cdylib via RUSTC_WRAPPER • Integrates maturin build with pytest suite for coverage collection • Uploads binding coverage separately to Codecov under python-binding flag Diagramflowchart LR
A["cargo llvm-cov show-env"] -->|RUSTC_WRAPPER| B["maturin develop"]
B -->|instrumented extension| C["pytest suite"]
C -->|profraw files| D["cargo llvm-cov report"]
D -->|lcov output| E["Codecov python-binding flag"]
File Changes1. .github/workflows/coverage-python.yml
|
Code Review by Qodo
1.
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Address qodo round 1 on #64: the coverage step used bash-only process substitution (source <(...)) without pinning the shell, and a cargo llvm-cov show-env failure would not stop the step — risking pytest/report running uninstrumented and uploading misleading coverage. Pin shell: bash and write show-env to a file before sourcing, so a failure aborts the step under set -e. Verified locally: the file-sourced env sets RUSTC_WRAPPER / LLVM_PROFILE_FILE / CARGO_LLVM_COV; yaml parses. Signed-off-by: Nelson Spence <nelson@projectnavi.ai>
|
Addressed the Bash-dependent env sourcing finding in 8f19860: pinned |
|
/review |
PR Reviewer Guide 🔍Warning
Here are some key observations to aid the review process:
|
Round 2 (qodo) on #64: make the strict bash options explicit in the multi-command coverage step. shell: bash already runs -eo pipefail (so each command already fails the step), and this adds -u (error on unset vars) plus states the intent in the script. Verified python -m venv activate is set -u-safe on 3.13. Signed-off-by: Nelson Spence <nelson@projectnavi.ai>
|
Addressed in 3cb3660: added set -euo pipefail to the coverage step. shell: bash was already running -eo pipefail (so each command already fails the step); this makes it explicit and adds -u (error on unset vars). Verified python -m venv activate is set -u-safe on 3.13. |
There was a problem hiding this comment.
Pull request overview
Adds a dedicated GitHub Actions workflow to measure and report Rust-layer code coverage for the PyO3 Python bindings (ordvec-python) as exercised by the existing pytest suite, and uploads that coverage to Codecov under a separate flag.
Changes:
- Introduces
.github/workflows/coverage-python.ymlto build an llvm-cov-instrumented binding viacargo llvm-cov show-env+maturin develop. - Runs
pytestto generate.profrawcoverage data across test processes, then aggregates viacargo llvm-cov report -p ordvec-python. - Uploads the resulting LCOV to Codecov under the
python-bindingflag (non-blocking upload).
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Round 3 (copilot) on #64: switch pip install to python -m pip install so the pip instance always matches the active venv interpreter, consistent with the repo's other workflows and robust to PATH/activation changes. Signed-off-by: Nelson Spence <nelson@projectnavi.ai>
Summary
Completes the "measure Python binding coverage" piece of the coverage push. The core
coverage.ymljob is scoped-p ordvec, so the binding's FFI guard layer —ordvec-python/src/lib.rs, ~890 lines ofensure_finite/check_width/ contiguity / bounds / overflow guards — had no coverage signal at all.Adds
coverage-python.yml, which measures the Rust binding layer as exercised by the existing pytest suite, with no new dependency (reuses cargo-llvm-cov + maturin + pytest):cargo llvm-cov show-envexports aRUSTC_WRAPPERthat instruments the listed crates (incl._ordvec).maturin developbuilds that instrumented extension into a venv.pytestdrives it — each test process (including the red-team suite's subprocess-isolated abort probes) emits its own.profraw.cargo llvm-cov report -p ordvec-pythonaggregates them.Uploaded to Codecov under a
python-bindingflag so the binding's number is tracked separately from the core line.Result (measured locally, full suite)
ordvec-python/src/lib.rs— 84.1% line / 84.8% region / 70.0% function. The uncovered ~16% is overwhelmingly unreachable FFI error arms: thefrom_shape_vec(...).map_err(...)reshape-failure paths (the shape is computed correctly upstream) and thechecked_mulusize-overflow guards (can't fire on a 64-bit target). Function coverage reads lower because each of those error closures is its own uncovered function.Notes
--fail-under-linesfloor can follow.fail_ci_if_error: false, so it never blocks a PR). The corecoverage.ymlauthenticates its upload via the repo's Codecov credential; I left that off here to stay within the write-content guardrail — happy to wire that credential in for consistency if you'd prefer.main, so until Coverage hardening: regression floor, experimental coverage, and adversarial red-team #63 merges this job exercises the 155 pre-existing binding tests (a few points lower); it settles to ~84% once Coverage hardening: regression floor, experimental coverage, and adversarial red-team #63's tests reachmain. The job is correct either way.Test plan
show-env→ instrumentedmaturin develop→pytest(365 tests, exit 0) →report -p ordvec-python= 84.1% linecoverage-python.ymlparses as YAMLcoverage-pythonjob runs green on this PR (its first real run) + actionlint