Skip to content

ci: show pull requests the nvx-rs lines that they add and no test reaches - #1353

Merged
Pedro Henrique Penna (ppenna) merged 1 commit into
devfrom
agents/nvx-issue-1324-fix
Nov 7, 2026
Merged

Pedro Henrique Penna (ppenna) merged 1 commit into
devfrom
agents/nvx-issue-1324-fix

Conversation

@ppenna

@ppenna Pedro Henrique Penna (ppenna) commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #1324.

A pull request that changes the nvx crate could not tell which of the lines that it adds or changes no test reaches: nvx-rs-coverage.yml (#1333) ran only for pushes to dev and on dispatch, and its summary gave totals and a row per module. This runs the measurement for ready pull requests too, and adds to each OS's summary the changed lines of production code that no test reaches.

Decisions

  • Where it runs: a pull_request trigger of nvx-rs-coverage.yml, rather than jobs of ci.yml, as module-diagrams.yml draws its diagrams for pull requests, so that no required check depends on it. As in ci.yml, it runs for any base, so that a pull request stacked on another's branch lists the lines of its own changes, and drafts skip it with the condition of ci.yml's jobs.
  • Inputs: the paths that start it for dev: nvx-rs/**, and also rust-toolchain.toml, the tool manifest, the script, and the workflow, so that a pull request that changes how the crate is measured, this one included, runs the measurement before it merges. Such a pull request lists no line unless it changes nvx-rs/.
  • Measured revision: the pull request's head, rather than the merge commit that pull_request checks out by default, so that the lines, from the diff against the merge base of the base's commit and the head, are those of the pull request's own changes. A pull request's checkout fetches the full history, as ci.yml's Detect CI workload inputs does in about 6 s; pushes keep a depth of 1.
  • Per OS: each job lists the lines that its OS instruments, so a changed line of code that only Windows compiles shows only in the Windows job's summary, and a shared line that only the Linux tests reach shows in the Windows job's.
  • Branches: the pinned Rust release measures none, so the summary lists branches only under a compiler that measures them, and then lists the changed lines with branches that no test takes, unreached lines included, as the issue asks.
  • Working tree: --base compares the working tree, which the measurement builds, so that on a development host uncommitted changes count too, but untracked files, which no diff holds, don't. In CI, they are the same.

Changes

  • .github/workflows/nvx-rs-coverage.yml: the pull_request trigger (opened, synchronize, reopened, ready_for_review), the draft condition, the checkout of the head with its history, and --base "${BASE}" for pull requests in the Measure step.
  • scripts/nvx_rs_coverage.py: --base REVISION. It takes the lines of nvx-rs/ that the working tree adds or changes since the merge base of REVISION and HEAD from git diff --find-renames --unified=0, with options that override what Git's configuration says of colors, prefixes, renames, context, external diff drivers, text conversions, and relative paths, reading each hunk by its header's counts, and the file names that Git quotes or ends with a tab. It reads the LCOV report's DA and BRDA records, and writes a section before the module table: the share of the changed lines that the report instruments that the tests reach, then, by file, the lines that no test reaches and, when branches are measured, the changed lines with branches that no test takes.
  • scripts/test_nvx_rs_coverage.py: tests of the trigger, the draft condition, which matches ci.yml's, the checkout, and the Measure step, which a POSIX host runs with and without a base; of Git's diffs in fixture repositories, with renamed, deleted, added, quoted, and untracked files, deleted lines, a base that moved on, uncommitted changes, and a hostile Git configuration; of LCOV records; of the counting, with comments and files that the report lacks; of the summary; and of --base through measure() and main().
  • doc/ci.md: the trigger, a "Changed lines that no test reaches" subsection, and --base on a development host; nvx-rs/README.md (Testing) and doc/project-structure.md.

Changes to existing tests

check_test_changes.py --base origin/dev flags three tests of scripts/test_nvx_rs_coverage.py, each of which checked behavior that this changes:

  • WorkflowTests.test_pushes_to_dev_that_change_the_measurement_run_it asserted that the workflow's triggers are only push and workflow_dispatch ("Never for pull requests"). The set now includes pull_request, and the comment says that merge groups never run it. Its checks of the push trigger are unchanged, and the new test_ready_pull_requests_that_change_the_measurement_run_it checks the pull_request trigger.
  • WorkflowTests.test_the_workflow_measures_linux_and_windows asserted the Measure step's exact command, which is now a bash script that adds --base for a pull request. It now checks the script's output option and command, and the new test_pull_requests_measure_their_head_and_their_changes runs the step with and without a base.
  • CommandTests.test_the_output_defaults_to_the_build_directory asserted the call of measure(), which now passes changes=None when there is no --base.

Acceptance criteria of #1324

  • A pull request that adds a production line of nvx-rs that no test reaches finds it in its run's summary, and one that adds none finds none: on a Windows workstation, the script listed the lines of an uncommitted function that no test calls, and only them (Validation), and test_changes_find_the_lines_that_they_add_and_no_test_reaches shows both halves through real Git. This pull request changes no instrumented line of nvx-rs/, only its README, and its own run 42418117916 found none: both jobs measured its head, b611b51df, with the pinned rustc 1.97.1 and cargo-llvm-cov 0.9.1, and each summary says "The changes since 8394746fd864 add or change no instrumented line of production code".
  • No required check changes: dev's rules require only Required status check (gh api repos/microsoft/nvx/rules/branches/dev), a job of ci.yml, which this leaves unchanged. The new runs are the measure / ubuntu-latest and measure / windows-latest jobs of another workflow, which merge groups never run.

Problems found, not fixed here

  • llvm-cov counts the lines of a const fn that only the compiler evaluates as unreached, such as table() in src/gpt/crc.rs (lines 18-36 in dev's run 42398285564), so a pull request that changes such a function sees its lines listed.
  • On the Windows workstation, some subtests of test_host_loopback_allow_script_checks_publication_and_traffic in test_microvm_tests.py error, as their shell script exceeds its 10 s timeout under Git for Windows' sh, at 8394746fd (dev) too, as ci: report the coverage of the Python host tooling in scripts/ #1344 recorded.

Validation

Host Platform Host type Revision Run Result
Workstation, Python 3.14.10 windows not recorded 8394746fd (dev) nvx_rs_coverage.py --base origin/dev Exit 2, unrecognized arguments: --base origin/dev. The workflow has no pull_request trigger, and no pull-request run of it exists
nvx-kvm-test, Python 3.12.16, Git 2.45.4 linux-kvm virtual-machine 8394746fd (dev) The same Exit 2, the same
Workstation windows not recorded 8394746fd, with this branch's tests test_nvx_rs_coverage.py 38 of 55 fail: 3 failures, 35 errors
Workstation windows not recorded b611b51df test_nvx_rs_coverage.py 55 passed, 4 skipped, which run only on POSIX hosts
nvx-kvm-test linux-kvm virtual-machine b611b51df test_nvx_rs_coverage.py, test_tool_versions.py, and test_markdown_links.py 173 passed, 5 skipped, which need PowerShell; every coverage test ran
nvx-kvm-test linux-kvm virtual-machine e70a27eb2, before the review fix below validate-nvx's Linux test modules, without NVX_RS 1,912 passed, 40 skipped, in 170 s
Workstation windows not recorded e70a27eb2 validate-nvx's Windows test modules, without NVX_RS 1,912 run, 78 skipped, 3 errors: the loopback subtests above, which also error at 8394746fd (2 of them in a run of that test alone)
Workstation windows not recorded This branch, with an uncommitted function that no test calls added to src/gpt/crc.rs nvx_rs_coverage.py --base origin/dev, under nightly-2026-07-09 and its llvm-tools, which the workstation's 1.97.1 lacks Exit 0 in 160 s: "Tests reach 60.0% of 5 instrumented lines", listing src/gpt/crc.rs 55-56, the function. Its DA records hold 0, the changed lines of Crc32::new ran 559 times each, and the changed comment, blank, doc comment, and attribute lines have no record
Workstation windows not recorded The same, with an impossible bounds check added to Crc32::update The same, with RUSTFLAGS=-Zcoverage-options=branch Exit 0 in 254 s: 62.5% of 8, lines 55-56 and 64, and line 63's branch that no test takes, 1 of 2, from BRDA records; the same with the review fix, from the run's LCOV report

Also: ruff check, ruff format --check, and pyright --pythonplatform Linux and Windows are clean; check_markdown_links.py and check_test_layout.py pass; and the LCOV reports of dev's run 42398285564 parse into the counts that they hold: 262 files and 43,251 lines on Linux, 164 files and 26,807 lines on Windows.

A code review of e70a27eb2 found that the summary left out the branches of changed lines that no test reaches, which b611b51df lists, as the issue asks.

CI of b611b51df: run 42418117994 of ci.yml passed, with NVX CLI / Linux and NVX CLI / Windows, which run validate-nvx with NVX_RS, and Required status check; its change classification skipped the microVM, platform, and package jobs, which this changes no input of. Run 42418117916 of nvx-rs coverage, the first with the pinned release and --base, passed on ubuntu-latest in 4 min and windows-latest in 5 min, with no test run again and no stray profile.

…ches

A pull request that changes the nvx crate could not tell which of the
lines that it adds or changes no test reaches: nvx-rs-coverage.yml ran
only for pushes to dev and on dispatch, and its summary gave totals and
a row per module.

The workflow now also runs for ready pull requests to any branch that
change its inputs, the paths that start it for dev, in jobs that skip
drafts with the condition of ci.yml's jobs. No required check depends
on them: dev requires only Required status check, a job of ci.yml, and
merge groups never run the workflow. A pull request's jobs check out
its head, rather than its merge with its base, with the history that
their merge base needs, and pass the base's commit to the script with
--base.

With --base REVISION, scripts/nvx_rs_coverage.py:

- takes the lines of the crate that the working tree adds or changes
  since the merge base of REVISION and HEAD from git diff, with rename
  detection and no context, whatever Git's configuration says of
  colors, prefixes, renames, context, external diff drivers, text
  conversions, or relative paths; it reads each hunk by the line
  counts of its header, so that an added line that looks like a header
  counts as a line, and the file names that Git quotes or ends with a
  tab;
- reads the LCOV report of the production code, whose DA records give
  each instrumented line once, and whose BRDA records give the
  branches when the compiler measures them;
- counts only the changed lines that the report instruments: a renamed
  file's changed lines, but neither deleted lines, nor comments, blank
  lines, or declarations, nor the lines of test code, test doubles, or
  files that the host's OS doesn't compile;
- writes, before the summary's module table, the share of those lines
  that the tests reach, the lines that they don't, by file, and, when
  the compiler measures branches, the branches on the changed lines
  that no test takes.

At 8394746, the script refused --base and the workflow had no
pull_request trigger, on a Windows workstation and on nvx-kvm-test.
With this change, on the Windows workstation, under nightly-2026-07-09
and its llvm-tools, since its pinned 1.97.1 lacks them, with an
uncommitted function in src/gpt/crc.rs that no test calls:

- --base origin/dev exited 0 in 160 s, and the summary said that the
  tests reach 60.0% of 5 instrumented changed lines, and listed lines
  55-56 of src/gpt/crc.rs, the new function's, whose DA records hold 0.
  The three changed lines of Crc32::new ran 559 times each, and the
  changed comment, blank, doc comment, and attribute lines have no DA
  record.
- With RUSTFLAGS=-Zcoverage-options=branch and an impossible bounds
  check added to Crc32::update, it listed lines 55-56 and 64, and the
  branch that no test takes on line 63, 1 of its 2, from BRDA records.

The LCOV reports of dev's run 42398285564 parse into the counts that
they hold: 262 files and 43,251 lines on Linux, and 164 files and
26,807 lines on Windows.

scripts/test_nvx_rs_coverage.py tests the workflow's pull_request
trigger, its draft condition, which matches ci.yml's, its checkout, and
its Measure step, which a POSIX host runs with and without a base; the
lines of Git's diffs in fixture repositories, with renamed, deleted,
added, quoted, and untracked files, deleted lines, a base that moved
on, uncommitted changes, and a hostile Git configuration; the LCOV
records; the counting, with comments and files that the report lacks;
and the summary. At 8394746, 38 of its 55 tests fail; with this
change, all pass. Three existing tests change with the trigger, the
Measure step, and the call of measure(). doc/ci.md describes the pull
requests' report and --base on a development host.

Part of #1324.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings November 7, 2026 21:55
@github-actions github-actions Bot added the tests-modified Changes existing tests, test data, or test wiring label Nov 7, 2026
@github-actions

github-actions Bot commented Nov 7, 2026

Copy link
Copy Markdown
Contributor

This pull request changes existing tests

It modifies or removes 3 existing test asset(s), listed below. Review each with care: a change to a test can hide a regression that the test caught. See doc/contribute.md#changes-to-existing-tests.

Test code

Change What Before After
modified test def WorkflowTests.test_pushes_to_dev_that_change_the_measurement_run_it in scripts/test_nvx_rs_coverage.py scripts/test_nvx_rs_coverage.py:58 scripts/test_nvx_rs_coverage.py:60
modified test def WorkflowTests.test_the_workflow_measures_linux_and_windows in scripts/test_nvx_rs_coverage.py scripts/test_nvx_rs_coverage.py:81 scripts/test_nvx_rs_coverage.py:84
modified test def CommandTests.test_the_output_defaults_to_the_build_directory in scripts/test_nvx_rs_coverage.py scripts/test_nvx_rs_coverage.py:885 scripts/test_nvx_rs_coverage.py:1470

Relocated unchanged: 0; added: 35. Compared the merge base 8394746fd864 with b611b51df863.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The pull-request changed-line coverage update has no active review issues.

No open issues 🎉

What changed in this PR

Extends the existing nvx-rs coverage workflow to ready pull requests, reporting changed production lines that tests do not reach on Linux and Windows without changing required checks.

Changes:

  • Measures each pull request’s head and compares its changes against the merge base.
  • Adds --base support to combine Git diffs with LCOV data and summarize unreached lines and, when measured, untaken branches.
  • Adds tests for workflow wiring, diff parsing, coverage calculations, and summaries, and documents the behavior.
File Description
scripts/​test_nvx_rs_coverage.py Tests pull-request workflow wiring and changed-line coverage reporting.
scripts/​nvx_rs_coverage.py Computes changed-line coverage and renders it in the summary.
nvx-rs/​README.md Describes coverage reporting for ready pull requests.
doc/​project-structure.md Updates the coverage workflow’s purpose in the repository map.
doc/​ci.md Documents triggers, reporting semantics, and local --base usage.
.github/​workflows/​nvx-rs-coverage.yml Enables ready pull-request runs with head checkout and base comparison.

Review effort: Balanced

@ppenna
Pedro Henrique Penna (ppenna) added this pull request to the merge queue Nov 7, 2026
Merged via the queue into dev with commit 2ea5032 Nov 7, 2026
49 checks passed
@ppenna
Pedro Henrique Penna (ppenna) deleted the agents/nvx-issue-1324-fix branch November 7, 2026 22:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

tests-modified Changes existing tests, test data, or test wiring

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ci: show pull requests the nvx-rs lines that they add and no test reaches

2 participants