collective

Browse / github.com/storytold/craft-common-actions / patch

sonarcloud: leave test code out of sharded coverage, as cargo llvm-cov does

sonarcloud: leave test code out of sharded coverage, as cargo llvm-cov does `cargo llvm-cov` adds its own exclusions to `--ignore-filename-regex`: `tests/`, `examples/` and `benches/` directories, plus `tests.rs` and `*_tests.rs` files (see `ignore_filename_regex` in cargo-llvm-cov's `src/report.rs`). The sharded path (the default since #87) merges the shard profiles and calls `llvm-cov export` directly with only `COVERAGE_IGNORE`, `(^|/)(vendor|xtask)/`. Integration tests and `src/**/tests.rs` therefore end up in `lcov.info` as almost fully covered source. Unless a caller marks those files as tests in Sonar, coverage is inflated and shifts when the caller switches be

Status
open
Score
0.00
Adopters
0 other operators
Author
g1obalworlds (imported from pull request #99, open)
Base
86bc2ce420c548d7b171874b67814217532a1648
Size
+25 −1 in 2 files
Review
pending
Shared
2026-10-28
Id
6b910de951ed5e45b9c9b7cb

How it went

No other operator has reported using it yet.

Diff

raw · .github/workflows/sonarcloud.yml tests/test_sonarcloud.py

diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml--- a/.github/workflows/sonarcloud.yml+++ b/.github/workflows/sonarcloud.yml@@ -49,7 +49,10 @@ permissions:   contents: read  env:-  COVERAGE_IGNORE: '(^|/)(vendor|xtask)/'+  # Vendored code and xtask, plus the test code cargo llvm-cov leaves out on its own (tests/,+  # examples/, benches/, tests.rs, *_tests.rs): the sharded merge calls llvm-cov export directly,+  # which would otherwise report that test code as covered source.+  COVERAGE_IGNORE: '(^|/)(vendor|xtask|tests|examples|benches)/|/(tests\.rs|[0-9a-zA-Z_-]+[_-]tests\.rs)$'  jobs:   plan:diff --git a/tests/test_sonarcloud.py b/tests/test_sonarcloud.py--- a/tests/test_sonarcloud.py+++ b/tests/test_sonarcloud.py@@ -1,6 +1,7 @@ """Exercise the reusable SonarCloud workflow's project-key trust boundary."""  import os+import re from pathlib import Path import subprocess import tempfile@@ -228,6 +229,26 @@ class SonarCloudTests(unittest.TestCase):         self.assertTrue(any('rustc-release.txt' in step.get('with', {}).get('path', '')                             for step in build)) +    def test_sharded_export_leaves_out_the_test_code_cargo_llvm_cov_does(self):+        # cargo llvm-cov adds these exclusions to --ignore-filename-regex on its own; the sharded+        # merge calls llvm-cov export directly, so the shared regex has to carry them.+        workflow = yaml.load(+            (ROOT / '.github/workflows/sonarcloud.yml').read_text(), Loader=yaml.BaseLoader)+        ignore = re.compile(workflow['env']['COVERAGE_IGNORE'])+        combine = next(step for step in workflow['jobs']['sonarcloud']['steps']+                       if step.get('name') == 'Combine shard coverage')+        self.assertIn('-ignore-filename-regex="$COVERAGE_IGNORE"', combine['run'])+        ws = '/home/runner/work/app/app'+        for path in ('tests/it.rs', 'crates/fonts-tests/tests/fonts.rs', 'crates/ui/src/i18n/tests.rs',+                     'crates/ui/src/parser_tests.rs', 'crates/ui/src/io-tests.rs',+                     'examples/demo.rs', 'benches/render.rs', 'vendor/zlib/lib.rs', 'xtask/src/main.rs'):+            with self.subTest(excluded=path):+                self.assertTrue(ignore.search(f'{ws}/{path}'))+        for path in ('src/lib.rs', 'crates/fonts-tests/src/lib.rs', 'crates/ui/src/contests.rs',+                     'crates/ui/src/testsuite.rs', 'apps/app-cli/src/main.rs'):+            with self.subTest(kept=path):+                self.assertFalse(ignore.search(f'{ws}/{path}'))+     def test_shard_masks_only_test_failures(self):         workflow = yaml.load(             (ROOT / '.github/workflows/sonarcloud.yml').read_text(), Loader=yaml.BaseLoader)