Skip to content

Commit dc29142

Browse files
committed
ci(coverage): single combined Codecov upload, exclude legacy/entrypoints from the number
Consolidate coverage uploads into one combined report with after_n_builds synchronisation; exclude legacy/entrypoint modules from the coverage metric.
1 parent 69ab76a commit dc29142

5 files changed

Lines changed: 53 additions & 9 deletions

File tree

.github/workflows/ci-tests.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,8 +319,26 @@ jobs:
319319
ls -la .coverage* 2>/dev/null || echo "no .coverage data files found"
320320
321321
- name: Combine coverage and enforce combined threshold
322+
id: coverage-gate
322323
run: make ci-tests-coverage-check
323324

325+
# Single deterministic Codecov upload: the combined report from ALL legs is
326+
# sent once here, instead of each leg uploading separately. Codecov then
327+
# shows one stable number (no mid-run partial-merge flapping) and this needs
328+
# no hardcoded leg count — it auto-scales to any number of provider legs.
329+
# if: always() so the report uploads even when the threshold gate fails
330+
# above (the job still fails on the gate; Codecov still gets the data).
331+
- name: Upload combined coverage to Codecov
332+
if: always()
333+
continue-on-error: true
334+
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v6
335+
with:
336+
token: ${{ secrets.CODECOV_TOKEN }}
337+
files: coverage-combined.xml
338+
name: combined
339+
# Overwrite any prior partial report for this commit with the full merge.
340+
override_commit: ${{ github.event.pull_request.head.sha || github.sha }}
341+
324342
# Single stable required status check for branch protection. Replaces listing
325343
# every individual job name (which drifts silently when jobs are renamed).
326344
# Register "CI Passed" as the sole required check in branch protection.

.github/workflows/reusable-test.yml

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -185,15 +185,12 @@ jobs:
185185
coverage-*.xml
186186
.coverage*
187187
188-
- name: Upload coverage to Codecov
189-
if: inputs.upload-coverage && always()
190-
continue-on-error: true
191-
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v6
192-
with:
193-
token: ${{ secrets.CODECOV_TOKEN }}
194-
files: coverage-${{ inputs.test-type }}${{ inputs.provider != '' && format('-{0}', inputs.provider) || '' }}.xml
195-
flags: ${{ inputs.test-type }}${{ inputs.provider != '' && format('-{0}', inputs.provider) || '' }}
196-
name: ${{ inputs.test-type }}${{ inputs.provider != '' && format('-{0}', inputs.provider) || '' }}-tests
188+
# NOTE: per-leg coverage is NOT uploaded to Codecov here. The .coverage
189+
# data files are uploaded as artifacts (above) and the coverage-combine
190+
# fan-in job in ci-tests.yml merges them and uploads ONE combined report
191+
# to Codecov. A single upload gives Codecov one deterministic number
192+
# (no mid-run partial-merge flapping) and auto-scales to any number of
193+
# provider legs without a hardcoded after_n_builds count.
197194

198195
- name: Upload test results to Codecov
199196
# Gated on upload-coverage: legs without pytest (e.g. ui-smoke) produce

codecov.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
# Coverage is uploaded to Codecov exactly ONCE, from the ci-tests
2+
# coverage-combine job, which merges every leg's .coverage data first. A single
3+
# upload gives Codecov one deterministic number (no mid-run partial-merge
4+
# flapping) and needs no hardcoded leg count — it auto-scales to any number of
5+
# provider legs.
16
coverage:
27
status:
38
project:
@@ -22,7 +27,14 @@ flags:
2227
- src/orb/
2328
carryforward: true
2429

30+
# Kept in sync with [tool.coverage.run] omit in pyproject.toml so Codecov's
31+
# view matches the combined report we upload.
2532
ignore:
2633
- "tests/"
2734
- "docs/"
2835
- "scripts/"
36+
- "src/orb/k8s_legacy/**" # own separate test suite; runs outside the main legs
37+
- "**/tests/**" # test files under src/ are not production source
38+
- "src/orb/__main__.py" # thin process entrypoints — not unit-tested
39+
- "src/orb/run.py"
40+
- "src/orb/interface/server_daemon.py"

makefiles/ci.mk

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,9 @@ ci-tests-infrastructure: ## Run infrastructure tests only (matches ci.yml infra
168168
ci-tests-coverage-check: ## Combined-coverage gate: merge per-leg data + enforce threshold
169169
@echo "Combining per-leg coverage data and checking combined threshold ($(COVERAGE_THRESHOLD)%)..."
170170
$(call run-tool,coverage,combine)
171+
# Emit the merged XML BEFORE the threshold check so it is always produced
172+
# for the single Codecov upload, even when the gate below fails.
173+
$(call run-tool,coverage,xml -o coverage-combined.xml)
171174
# `coverage report` uses --fail-under (the pytest-cov spelling
172175
# --cov-fail-under is not valid for the coverage CLI).
173176
$(call run-tool,coverage,report --fail-under=$(COVERAGE_THRESHOLD))

pyproject.toml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,20 @@ env = []
545545
[tool.coverage.run]
546546
source = ["src/orb"]
547547
branch = true
548+
omit = [
549+
# k8s_legacy is the legacy HostFactory plugin: it has its own test suite
550+
# under src/orb/k8s_legacy/tests (in pytest testpaths) that runs separately
551+
# from the main legs, so it always shows 0% here and unfairly drags the
552+
# combined number. Exclude it from the main coverage report.
553+
"src/orb/k8s_legacy/*",
554+
# Test files that live under src/ are not production source.
555+
"*/tests/*",
556+
# Thin process entrypoints / daemon lifecycle: not meaningfully unit-tested
557+
# (exercised via subprocess/integration, not the coverage-uploading legs).
558+
"src/orb/__main__.py",
559+
"src/orb/run.py",
560+
"src/orb/interface/server_daemon.py",
561+
]
548562

549563
[tool.coverage.report]
550564
precision = 2

0 commit comments

Comments
 (0)