ci(coverage): exclude generated EF migrations to stop coverage OOM (exit 137)
Build ErsatzTV Image / Docs update reminder (pull_request) Successful in 7s
Build ErsatzTV Image / decisions.md append-only (pull_request) Successful in 8s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 4m26s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 16s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 17s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 6m5s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Build ErsatzTV Image / Functional E2E (curl contracts) (pull_request) Successful in 3m46s

The shared Build & test job OOM-killed (exit 137) with coverage enabled: the
whole-solution Architecture.Tests process instruments both EF migration folders
(~2.59M generated lines vs ~200k authored), ballooning coverlet's in-memory
hit-count arrays past the runner's limit.

Add coverlet.runsettings excluding **/Migrations/*.cs (+ generated/compiler
attributes) and pass it via --settings on the Test step. This cuts the
instrumented surface ~126x (2,510,185 -> 19,963 coverable lines in the
Architecture.Tests process, verified locally) and makes the reported percentage
reflect authored code. Documented in docs/ci-cd.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-16 19:03:54 +02:00
co-authored by Claude Opus 4.8
parent a886fd2824
commit e78aa01c05
3 changed files with 36 additions and 6 deletions
+1 -1
View File
@@ -103,7 +103,7 @@ jobs:
- name: Test
run: >-
dotnet test --configuration Release --no-build --blame-hang-timeout "2m" --verbosity normal
--collect:"XPlat Code Coverage" --results-directory ./coverage
--collect:"XPlat Code Coverage" --settings coverlet.runsettings --results-directory ./coverage
# Coverage reporting (ersatztv#15 scope item 4): coverlet.collector emits a Cobertura report
# per test project (via --collect above); ReportGenerator merges them into a human-readable
+24
View File
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Coverage collector config (ersatztv#15). Passed to dotnet test via
"settings coverlet.runsettings" alongside collect:"XPlat Code Coverage".
The two EF Core migration folders are ~2.59M lines of generated snapshot code
(vs ~200k lines of authored code); instrumenting them balloons coverlet memory
and OOM killed the shared Build and test job (exit 137). Excluding generated
migration code bounds memory and makes the reported percentage reflect authored
code. Keep this comment free of double hyphens (invalid in XML comments).
-->
<RunSettings>
<DataCollectionRunSettings>
<DataCollectors>
<DataCollector friendlyName="XPlat Code Coverage">
<Configuration>
<ExcludeByFile>**/Migrations/*.cs</ExcludeByFile>
<ExcludeByAttribute>GeneratedCodeAttribute,CompilerGeneratedAttribute,ExcludeFromCodeCoverageAttribute</ExcludeByAttribute>
<Exclude>[*]*.Migrations.*</Exclude>
<SkipAutoProps>true</SkipAutoProps>
</Configuration>
</DataCollector>
</DataCollectors>
</DataCollectionRunSettings>
</RunSettings>
+11 -5
View File
@@ -96,11 +96,17 @@ Docker build) → `dotnet build -c Release` → `dotnet test -c Release --no-bui
the image build.
- **Code coverage** (ersatztv#15): `dotnet test` runs with `--collect:"XPlat Code Coverage"
--results-directory ./coverage`, so `coverlet.collector` (referenced by every `*.Tests`
project) emits a Cobertura report per project. A follow-up **Coverage summary** step merges
them with ReportGenerator (`TextSummary` to the log, `MarkdownSummaryGithub` to the job step
summary). No floor is enforced yet ("decide on a floor later" — #15); the step is
`continue-on-error: true`, so a missing report or a transient tool install never blocks a build.
--settings coverlet.runsettings --results-directory ./coverage`, so `coverlet.collector`
(referenced by every `*.Tests` project) emits a Cobertura report per project. A follow-up
**Coverage summary** step merges them with ReportGenerator (`TextSummary` to the log,
`MarkdownSummaryGithub` to the job step summary). No floor is enforced yet ("decide on a
floor later" — #15); the step is `continue-on-error: true`, so a missing report or a
transient tool install never blocks a build.
- **`coverlet.runsettings` excludes generated EF migration code** (`**/Migrations/*.cs`,
~2.59M generated lines vs ~200k authored). Instrumenting it OOM-killed the shared `test`
job (exit 137); excluding it cuts the instrumented surface ~126× (2.5M→20k coverable
lines in the whole-solution `Architecture.Tests` process) and makes the percentage reflect
authored code.
- **Shallow checkout**: `fetch-depth: 1` (ersatztv#190) — this job never runs `git
describe`/`git log`, only `build` needs full history/tags for version computation, so
`test` and `migrations` both check out shallow. `build`'s checkout stays `fetch-depth: 0`.