Skip to content

Commit cbfc520

Browse files
authored
Merge pull request #23 from hzj-edu-nju/test/changed-line-coverage-gate
test: validate changed-line coverage gate
2 parents 2de63bb + 28f1819 commit cbfc520

1 file changed

Lines changed: 75 additions & 27 deletions

File tree

.github/workflows/pr-build.yml

Lines changed: 75 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,60 @@ jobs:
279279
echo "base_xmls=$BASE_XMLS" >> "$GITHUB_OUTPUT"
280280
echo "pr_xmls=$PR_XMLS" >> "$GITHUB_OUTPUT"
281281
282+
- name: Set up Python
283+
uses: actions/setup-python@v5
284+
with:
285+
python-version: '3.11'
286+
287+
- name: Changed-line coverage (diff-cover)
288+
id: diff-cover
289+
env:
290+
BASE_REF: ${{ github.event.pull_request.base.ref }}
291+
run: |
292+
set -euo pipefail
293+
pip install --quiet 'diff-cover==9.2.0'
294+
295+
# Ensure the base branch ref is available locally for diff-cover.
296+
git fetch --no-tags origin "+refs/heads/${BASE_REF}:refs/remotes/origin/${BASE_REF}"
297+
298+
PR_XMLS=$(find coverage/pr -name "jacocoTestReport.xml" | sort)
299+
if [ -z "$PR_XMLS" ]; then
300+
echo "No PR jacoco XML reports found, skipping diff-cover."
301+
exit 0
302+
fi
303+
304+
SRC_ROOTS=$(find . -type d -path '*/src/main/java' \
305+
-not -path './coverage/*' -not -path './.git/*' | sort)
306+
307+
set +e
308+
diff-cover $PR_XMLS \
309+
--compare-branch="origin/${BASE_REF}" \
310+
--src-roots $SRC_ROOTS \
311+
--fail-under=0 \
312+
--json-report=diff-cover.json \
313+
--markdown-report=diff-cover.md
314+
DIFF_RC=$?
315+
set -e
316+
317+
CHANGED_LINE_COVERAGE=$(jq -r '.total_percent_covered // empty' diff-cover.json)
318+
if [ -z "$CHANGED_LINE_COVERAGE" ]; then
319+
echo "Unable to parse changed-line coverage from diff-cover.json."
320+
exit 1
321+
fi
322+
echo "changed_line_coverage=${CHANGED_LINE_COVERAGE}" >> "$GITHUB_OUTPUT"
323+
324+
{
325+
echo "### Changed-line Coverage (diff-cover)"
326+
echo ""
327+
if [ -f diff-cover.md ] && [ -s diff-cover.md ]; then
328+
cat diff-cover.md
329+
else
330+
echo "_diff-cover produced no report._"
331+
fi
332+
} >> "$GITHUB_STEP_SUMMARY"
333+
334+
echo "diff-cover exit code: ${DIFF_RC}"
335+
282336
- name: Aggregate base coverage
283337
id: jacoco-base
284338
uses: madrapps/jacoco-report@v1.7.2
@@ -288,6 +342,7 @@ jobs:
288342
min-coverage-overall: 0
289343
min-coverage-changed-files: 0
290344
skip-if-no-changes: true
345+
comment-type: summary
291346
title: '## Base Coverage Snapshot'
292347
update-comment: false
293348

@@ -300,14 +355,15 @@ jobs:
300355
min-coverage-overall: 0
301356
min-coverage-changed-files: 0
302357
skip-if-no-changes: true
358+
comment-type: summary
303359
title: '## PR Code Coverage Report'
304360
update-comment: false
305361

306362
- name: Enforce coverage gates
307363
env:
308364
BASE_OVERALL_RAW: ${{ steps.jacoco-base.outputs.coverage-overall }}
309365
PR_OVERALL_RAW: ${{ steps.jacoco-pr.outputs.coverage-overall }}
310-
PR_CHANGED_RAW: ${{ steps.jacoco-pr.outputs.coverage-changed-files }}
366+
CHANGED_LINE_RAW: ${{ steps.diff-cover.outputs.changed_line_coverage }}
311367
run: |
312368
set -euo pipefail
313369
@@ -329,7 +385,7 @@ jobs:
329385
# 1) Parse metrics from jacoco-report outputs
330386
BASE_OVERALL="$(sanitize "$BASE_OVERALL_RAW")"
331387
PR_OVERALL="$(sanitize "$PR_OVERALL_RAW")"
332-
PR_CHANGED="$(sanitize "$PR_CHANGED_RAW")"
388+
CHANGED_LINE="$(sanitize "$CHANGED_LINE_RAW")"
333389
334390
if ! is_number "$BASE_OVERALL" || ! is_number "$PR_OVERALL"; then
335391
echo "Failed to parse coverage values: base='${BASE_OVERALL}', pr='${PR_OVERALL}'."
@@ -340,19 +396,16 @@ jobs:
340396
DELTA=$(awk -v pr="$PR_OVERALL" -v base="$BASE_OVERALL" 'BEGIN { printf "%.4f", pr - base }')
341397
DELTA_OK=$(compare_float "${DELTA} >= ${MAX_DROP}")
342398
343-
CHANGED_STATUS="SKIPPED (no changed coverage value)"
344-
CHANGED_OK=1
345-
if [ -n "$PR_CHANGED" ] && [ "$PR_CHANGED" != "NaN" ]; then
346-
if ! is_number "$PR_CHANGED"; then
347-
echo "Failed to parse changed-files coverage: changed='${PR_CHANGED}'."
348-
exit 1
349-
fi
350-
CHANGED_OK=$(compare_float "${PR_CHANGED} > ${MIN_CHANGED}")
351-
if [ "$CHANGED_OK" -eq 1 ]; then
352-
CHANGED_STATUS="PASS (> ${MIN_CHANGED}%)"
353-
else
354-
CHANGED_STATUS="FAIL (<= ${MIN_CHANGED}%)"
355-
fi
399+
if [ -z "$CHANGED_LINE" ] || [ "$CHANGED_LINE" = "NaN" ] || ! is_number "$CHANGED_LINE"; then
400+
echo "Failed to parse changed-line coverage: changed-line='${CHANGED_LINE}'."
401+
exit 1
402+
fi
403+
404+
CHANGED_LINE_OK=$(compare_float "${CHANGED_LINE} > ${MIN_CHANGED}")
405+
if [ "$CHANGED_LINE_OK" -eq 1 ]; then
406+
CHANGED_LINE_STATUS="PASS (> ${MIN_CHANGED}%)"
407+
else
408+
CHANGED_LINE_STATUS="FAIL (<= ${MIN_CHANGED}%)"
356409
fi
357410
358411
# 3) Output base metrics (always visible in logs + step summary)
@@ -362,11 +415,11 @@ jobs:
362415
fi
363416
364417
METRICS_TEXT=$(cat <<EOF
365-
Changed Files Coverage: ${PR_CHANGED}%
418+
Changed-line Coverage: ${CHANGED_LINE}%
366419
PR Overall Coverage: ${PR_OVERALL}%
367420
Base Overall Coverage: ${BASE_OVERALL}%
368421
Delta (PR - Base): ${DELTA}%
369-
Changed Files Gate: ${CHANGED_STATUS}
422+
Changed-line Gate: ${CHANGED_LINE_STATUS}
370423
Overall Delta Gate: ${OVERALL_STATUS}
371424
EOF
372425
)
@@ -376,11 +429,11 @@ jobs:
376429
{
377430
echo "### Coverage Gate Metrics"
378431
echo ""
379-
echo "- Changed Files Coverage: ${PR_CHANGED}%"
432+
echo "- Changed-line Coverage: ${CHANGED_LINE}%"
380433
echo "- PR Overall Coverage: ${PR_OVERALL}%"
381434
echo "- Base Overall Coverage: ${BASE_OVERALL}%"
382435
echo "- Delta (PR - Base): ${DELTA}%"
383-
echo "- Changed Files Gate: ${CHANGED_STATUS}"
436+
echo "- Changed-line Gate: ${CHANGED_LINE_STATUS}"
384437
echo "- Overall Delta Gate: ${OVERALL_STATUS}"
385438
} >> "$GITHUB_STEP_SUMMARY"
386439
@@ -391,14 +444,9 @@ jobs:
391444
exit 1
392445
fi
393446
394-
if [ -z "$PR_CHANGED" ] || [ "$PR_CHANGED" = "NaN" ]; then
395-
echo "No changed-files coverage value detected, skip changed-files gate."
396-
exit 0
397-
fi
398-
399-
if [ "$CHANGED_OK" -ne 1 ]; then
400-
echo "Coverage gate failed: changed files coverage must be > 60%."
401-
echo "changed=${PR_CHANGED}%"
447+
if [ "$CHANGED_LINE_OK" -ne 1 ]; then
448+
echo "Coverage gate failed: changed-line coverage must be > 60%."
449+
echo "changed-line=${CHANGED_LINE}%"
402450
exit 1
403451
fi
404452

0 commit comments

Comments
 (0)