Repository navigation
ci: collect coverage in-process so it cannot fail a green test run - #704
Conversation
coverlet.msbuild's GenerateCoverageResult target runs after the test run and could fail the whole job on an intermittent truncated read of its own hit file (#689) - a red build with every test passed, and on a merge-queue run a dequeued PR. Coverage is reporting-only and deliberately has no build-failing threshold (#641), so it moves to coverlet.collector, which runs inside the test host and has no post-test step to fail. The collector puts no framework in the report name, so the test project sets VSTestResultsDirectory to .../coverage/$(TargetFramework): that expands once per inner build, which keeps the run a single solution-wide `dotnet test` with both frameworks in parallel while still telling the two reports apart. CI's coverage step flattens <tfm>/<guid>/coverage.cobertura.xml back to the framework-labelled names the summary script and the uploaded artifact already use, so neither changes. coverlet.runsettings restates the format and ExcludeByAttribute the old properties set; without it the collector's defaults move the reported line rate from 88.86% to 86.91%. closes #689 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
/agentic_review |
PR Summary by QodoCollect coverage in-process to prevent false CI failures
AI Description
Diagram
High-Level Assessment
Files changed (4)
|
Code Review by Qodo
1.
|
Review found the new flatten step could reintroduce the very failure mode this PR removes: the step runs under `set -e`, so a failed `mv` would abort it and take the leg down after a fully green test run. A move failure now degrades to a ::warning:: and a report missing from the summary. It also only warned when coverage was lost for *both* frameworks; losing one rendered a table a row short and said nothing. The expected framework list is read out of Daqifi.Core.Tests.csproj rather than repeated in the workflow, so it cannot drift, and a test guards that the single-line read still finds it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
/agentic_review |
|
Code review by qodo was updated up to the latest commit 5f7f649 |
Review pointed out that the guard reimplemented CI's extraction in C# and only checked that the workflow still mentioned the project path, so editing the sed expression could break the warning while the test stayed green. It now lifts the expression out of ci.yml, translates the one BRE construct it uses, and runs it over the real project file - and refuses to guess if the expression grows a construct the translation cannot reproduce. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
/agentic_review |
|
Code review by qodo was updated up to the latest commit e0b70a3 |
|
Qodo-clean, CI green — ready for review. Verified on head |
CI went red on a run where nothing was wrong. Every test passed — 4,060 on each framework, plus the MCP suite — and then the Windows leg failed anyway, in coverlet's post-test MSBuild step, on
Unable to read beyond the end of the streamwhile it read back its own hit file. The net9.0 coverage report was lost and the non-zero exit failed the job and thebuildgate with it. Coverage is reporting-only here and deliberately has no threshold that can fail a build, so this failure mode is all cost: a re-run fixes it, and on a merge-queue run it dequeues whatever PR was merging.Coverage now comes from
coverlet.collectorinstead, which runs inside the test host and has no post-test step that can fail.dotnet testis still a single solution-wide invocation with both frameworks in parallel, and the job summary and the uploaded artifact look exactly as they did.What a reviewer might push back on. The collector puts no framework in the report name — it always writes
coverage.cobertura.xmlunder a per-run GUID directory — so the framework has to survive in the path instead. The test project setsVSTestResultsDirectoryto../coverage/$(TargetFramework), which expands once per inner build; CI then flattens<tfm>/<guid>/coverage.cobertura.xmlback to thecoverage.<tfm>.cobertura.xmlnames thatcoverage-summary.pyand the artifact already expect, so neither of those changed. Doing it this way (a project property, not--results-directoryon the command line) is what avoids splitting the run into-f net9.0and-f net10.0steps, which would have serialized the two frameworks and cost about 35s a leg.coverlet.runsettingsis load-bearing rather than decorative: without it the collector's own default exclusions move the reported line rate from 88.86% to 86.91%.One real behaviour change for local development:
dotnet testno longer prints coverlet's console coverage table. It writes cobertura undersrc/coverage/<tfm>/instead.Verification
coverage-summary.py) locally; the rendered table has the same shape and the samenet9.0/net10.0rows.CoverageReportingTestsguards the one relationship that is now split across two files — where the project writes reports vs. where the workflow looks for them — since a mismatch would degrade silently to "No coverage reports were produced by this run." Confirmed it fails when the workflow glob's depth is changed.closes #689
Not merging — for review.