Skip to content

fix(ci): gate changed-line coverage with diff-cover#26

Merged
bladehan1 merged 1 commit intodevelopfrom
fix/ci_coverage_line_gate
Apr 24, 2026
Merged

fix(ci): gate changed-line coverage with diff-cover#26
bladehan1 merged 1 commit intodevelopfrom
fix/ci_coverage_line_gate

Conversation

@bladehan1
Copy link
Copy Markdown
Owner

@bladehan1 bladehan1 commented Apr 24, 2026

Summary

Replace the upstream coverage-changed-files gate (whole-file INSTRUCTION coverage) with a true changed-line LINE coverage gate powered by diff-cover, plus several robustness fixes uncovered during self-review.

Commits included

SHA Subject Purpose
28f1819cf9 ci(coverage): gate changed-line coverage Introduce diff-cover as the changed-code gate, switch jacoco-report to summary-only to eliminate 403s on fork PRs
ece6e0930f ci(coverage): harden diff-cover step and handle non-Java PRs Drop an unreachable branch, add NA sentinel for PRs with no src/main/java changes so the gate does not wrongly fail
37248f0bc3 ci(coverage): polish diff-cover step and clarify metric semantics Guard empty SRC_ROOTS, verify diff-cover produced its JSON, drop a no-signal log line, add a footnote clarifying the LINE vs INSTRUCTION mix

Net change: 1 file, +90 / -27.

Why

  1. Patch coverage semantics. The previous gate used madrapps/jacoco-report's coverage-changed-files output, which is the whole-file INSTRUCTION coverage of each changed file — not the coverage of the lines the PR actually changed. diff-cover provides the industry-standard "changed-line" measurement.
  2. Drop the 403 noise. jacoco-report's default PR comment needs pull-requests: write, which fork PRs do not get. The log kept filling up with 403 errors. comment-type: summary sidesteps that.
  3. Stop wrongly failing non-Java PRs. With just diff-cover, a PR that only touches workflows / docs / proto / test code produces total_num_lines=0 and the original jq call exited with 1. The NA sentinel now maps that state to SKIPPED in the enforce step.

Design notes for reviewers

  • CI wall-clock impact is ~0. The new coverage-base job runs independently of docker-build-debian11 (they share no needs:). Since docker-build-debian11 was already the slowest build (~16 min with testWithRocksDb), adding a parallel 16-min coverage-base does not extend the critical path. The gate job waits for both, so total PR wall-clock is unchanged.
  • Metric mix is intentional and footnoted. Changed-line Coverage uses LINE coverage (diff-cover), while PR Overall Coverage / Base Overall Coverage / Delta use INSTRUCTION coverage (jacoco-report v1.7.2 hard-codes this; there is no coverage-type input yet — see the open madrapps/jacoco-report#82 on milestone 1.8). The METRICS panel and step summary now print an explicit note so reviewers do not accidentally compare the two counters.
  • SKIPPED scope. diff-cover --src-roots is limited to */src/main/java. PRs touching only src/test/java, build/generated (proto output), docs, or CI will be reported as SKIPPED. Proto-only PRs that cause non-trivial generated-code changes are rare in this repo; we accept the gap.
  • No unit tests for the CI script itself. The bash in pr-build.yml is exercised end-to-end by every PR's own CI run rather than via a shell unit-test framework. This PR itself relies on the NA / SKIPPED path being observed on its own Coverage Gate run (proven previously on PR ci(coverage): harden diff-cover step and handle non-Java PRs #25 of the forked repo). Adding bats or similar as a follow-up is possible if the team wants it, but it is out of scope here.
  • Gate thresholds preserved. MIN_CHANGED=60 (for Changed-line LINE) and MAX_DROP=-0.1% (for Overall INSTRUCTION delta) are kept as in the previous workflow.

Follow-ups(not in this PR)

  • Migrate Overall to LINE once madrapps/jacoco-report 1.8 ships coverage-type, or switch to self-parsing the JaCoCo XML. That unifies the metrics panel on one counter.
  • Add proper shell unit tests (e.g. via bats) for the enforce step, so the three-state logic (NA / numeric / error) is covered without needing a real CI run.
  • Revisit comment-type: summary if upstream prefers on-PR comment visibility; restoring it requires granting pull-requests: write on the coverage-gate job.

Test plan

  • Workflow-only / non-Java PR → Changed-line Coverage: NA, Changed-line Gate: SKIPPED, gate passes. Verified on PR ci(coverage): harden diff-cover step and handle non-Java PRs #25 of the forked repo (same ece6e0930f commit): see Coverage Gate job summary.
  • Java PR with changed lines → Changed-line Coverage: X%, Changed-line Gate: PASS at X > 60. Verified on PR test: PR12 unit-test coverage on external account #24 of the forked repo (25 lines @ 100%, both files under test).
  • Java PR with changed lines at X <= 60FAIL. Logic reviewed; path not forced in CI yet.
  • First natural Java PR after merge → regress PASS / FAIL / mixed-change paths.

Summary by CodeRabbit

  • Chores
    • Improved CI/CD pipeline reliability with explicit validation for Java source discovery.
    • Enhanced failure detection when coverage reports are not properly generated.
    • Clarified coverage metrics documentation in build summaries to explain the distinction between different coverage measurement types.

Summary by cubic

Switch the PR coverage gate to changed-line LINE coverage using diff-cover. Adds guardrails and clearer metrics, skips non-Java PRs, and avoids fork PR permission noise.

  • New Features

    • Gate changed-line coverage with diff-cover (LINE coverage).
    • Keep overall/Delta via madrapps/jacoco-report (INSTRUCTION) and add a note to avoid mixing metrics.
    • Use comment-type: summary to avoid 403s on fork PRs.
  • Bug Fixes

    • Skip gate for PRs without src/main/java changes; report NA and mark as SKIPPED.
    • Guard empty SRC_ROOTS before running diff-cover.
    • Verify diff-cover.json exists; fail early with a clear message.
    • Remove the noisy “diff-cover exit code” log.

Written for commit 37248f0. Summary will update on new commits.

- Guard against empty SRC_ROOTS before invoking diff-cover; exits with a
  readable error instead of letting --fail-under be consumed as a
  src-root value.
- Verify that diff-cover actually wrote diff-cover.json; surface the
  exit code in the failure message so a runner/binary crash is
  diagnosable without hunting through logs.
- Drop the trailing "diff-cover exit code" log; --fail-under=0 means
  DIFF_RC is always 0 in the happy path, so the line carries no signal.
- Clarify the metrics panel: Changed-line is LINE coverage (diff-cover)
  while Overall / Delta are INSTRUCTION coverage (jacoco-report). Add a
  footnote to both the console output and the step summary so readers
  do not silently compare the two counters.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 24, 2026

📝 Walkthrough

Walkthrough

The PR-build workflow is hardened to fail early if Java sources are absent and to validate that diff-cover.json is successfully produced. The GitHub step summary is enhanced to clarify that line coverage metrics (from diff-cover) and instruction coverage metrics (from jacoco-report) are not directly comparable, reducing potential confusion in coverage reporting.

Changes

Cohort / File(s) Summary
GitHub Actions Workflow
.github/workflows/pr-build.yml
Added explicit failure conditions for missing Java source roots and missing diff-cover.json output; removed standalone diff-cover exit-code log; enhanced step summary with note distinguishing between LINE and INSTRUCTION coverage metrics from different tools.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Possibly related PRs

Suggested reviewers

  • 317787106
  • halibobo1205

Poem

🐰 A workflow grows robust and wise,
With guards to catch when Java dies,
And metrics clear—no more confused—
Which coverage tool left clues amused!
The gates stand firm, the flow runs clean,

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'fix(ci): gate changed-line coverage with diff-cover' directly summarizes the main change: implementing a changed-line coverage gate using diff-cover in the CI workflow.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/ci_coverage_line_gate

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@bladehan1 bladehan1 changed the title ci(coverage): gate changed-line coverage with diff-cover fix(ci): gate changed-line coverage with diff-cover Apr 24, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/workflows/pr-build.yml (1)

306-320: ⚠️ Potential issue | 🟡 Minor

Consider also failing on non-zero DIFF_RC, not just missing JSON.

With --fail-under=0 (line 310), diff-cover will not exit non-zero on low coverage, so a non-zero DIFF_RC indicates a real tool error (bad args, git/ref issue, etc.). Today, if diff-cover errors but still writes a (possibly partial) diff-cover.json, the step continues past line 319 and downstream jq parses whatever landed on disk — masking the failure. The captured DIFF_RC is only surfaced in the "missing JSON" branch.

Suggest gating on both conditions so tool errors are never silently absorbed:

🛠️ Proposed fix
-          if [ ! -f diff-cover.json ]; then
-            echo "diff-cover did not produce JSON report (exit=${DIFF_RC})." >&2
-            exit 1
-          fi
+          if [ "${DIFF_RC}" -ne 0 ] || [ ! -f diff-cover.json ]; then
+            echo "diff-cover failed (exit=${DIFF_RC}, json_present=$( [ -f diff-cover.json ] && echo yes || echo no ))." >&2
+            exit 1
+          fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/pr-build.yml around lines 306 - 320, The script currently
only fails when diff-cover.json is missing but ignores a non-zero DIFF_RC from
running diff-cover; update the post-run check to also fail when DIFF_RC is
non-zero. After running the diff-cover command (the block that sets DIFF_RC from
diff-cover $PR_XMLS ...), test if DIFF_RC != 0 OR if diff-cover.json is missing
and exit with an error message that includes the DIFF_RC value; reference the
existing DIFF_RC variable, the diff-cover invocation, and the diff-cover.json
filename when making this change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In @.github/workflows/pr-build.yml:
- Around line 306-320: The script currently only fails when diff-cover.json is
missing but ignores a non-zero DIFF_RC from running diff-cover; update the
post-run check to also fail when DIFF_RC is non-zero. After running the
diff-cover command (the block that sets DIFF_RC from diff-cover $PR_XMLS ...),
test if DIFF_RC != 0 OR if diff-cover.json is missing and exit with an error
message that includes the DIFF_RC value; reference the existing DIFF_RC
variable, the diff-cover invocation, and the diff-cover.json filename when
making this change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4b0dce10-777c-4619-9bbd-a2131bbd213d

📥 Commits

Reviewing files that changed from the base of the PR and between 8a330e2 and 37248f0.

📒 Files selected for processing (1)
  • .github/workflows/pr-build.yml

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

No issues found across 1 file

@bladehan1 bladehan1 merged commit b511d1e into develop Apr 24, 2026
20 of 24 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant