Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 75 additions & 27 deletions .github/workflows/pr-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,60 @@ jobs:
echo "base_xmls=$BASE_XMLS" >> "$GITHUB_OUTPUT"
echo "pr_xmls=$PR_XMLS" >> "$GITHUB_OUTPUT"

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'

- name: Changed-line coverage (diff-cover)
id: diff-cover
env:
BASE_REF: ${{ github.event.pull_request.base.ref }}
run: |
set -euo pipefail
pip install --quiet 'diff-cover==9.2.0'

# Ensure the base branch ref is available locally for diff-cover.
git fetch --no-tags origin "+refs/heads/${BASE_REF}:refs/remotes/origin/${BASE_REF}"

PR_XMLS=$(find coverage/pr -name "jacocoTestReport.xml" | sort)
if [ -z "$PR_XMLS" ]; then
echo "No PR jacoco XML reports found, skipping diff-cover."
exit 0
fi

SRC_ROOTS=$(find . -type d -path '*/src/main/java' \
-not -path './coverage/*' -not -path './.git/*' | sort)

set +e
diff-cover $PR_XMLS \
--compare-branch="origin/${BASE_REF}" \
--src-roots $SRC_ROOTS \
--fail-under=0 \
--json-report=diff-cover.json \
--markdown-report=diff-cover.md
DIFF_RC=$?
set -e

CHANGED_LINE_COVERAGE=$(jq -r '.total_percent_covered // empty' diff-cover.json)
if [ -z "$CHANGED_LINE_COVERAGE" ]; then
echo "Unable to parse changed-line coverage from diff-cover.json."
exit 1
fi
Comment on lines +307 to +321
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Fail when diff-cover exits nonzero.

DIFF_RC is captured but only logged. With --fail-under=0, a nonzero exit should represent a tool/report-generation problem, so the gate should stop instead of parsing potentially stale or partial diff-cover.json.

Proposed fix
           DIFF_RC=$?
           set -e
+
+          if [ "$DIFF_RC" -ne 0 ]; then
+            echo "diff-cover failed with exit code: ${DIFF_RC}"
+            exit "$DIFF_RC"
+          fi
 
           CHANGED_LINE_COVERAGE=$(jq -r '.total_percent_covered // empty' diff-cover.json)

Also applies to: 334-334

🤖 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 307 - 321, The workflow captures
diff-cover's exit code into DIFF_RC but continues to parse diff-cover.json;
change the logic after running diff-cover (the diff-cover invocation that sets
DIFF_RC) to check if DIFF_RC is non-zero and immediately fail (exit with DIFF_RC
and an error message) before attempting to read
diff-cover.json/CHANGED_LINE_COVERAGE; apply the same fix to the other
diff-cover invocation block (the second diff-cover run that also sets DIFF_RC)
so the job stops on tool/report-generation failures instead of parsing
partial/stale JSON.

echo "changed_line_coverage=${CHANGED_LINE_COVERAGE}" >> "$GITHUB_OUTPUT"

{
echo "### Changed-line Coverage (diff-cover)"
echo ""
if [ -f diff-cover.md ] && [ -s diff-cover.md ]; then
cat diff-cover.md
else
echo "_diff-cover produced no report._"
fi
} >> "$GITHUB_STEP_SUMMARY"

echo "diff-cover exit code: ${DIFF_RC}"

- name: Aggregate base coverage
id: jacoco-base
uses: madrapps/jacoco-report@v1.7.2
Expand All @@ -288,6 +342,7 @@ jobs:
min-coverage-overall: 0
min-coverage-changed-files: 0
skip-if-no-changes: true
comment-type: summary
title: '## Base Coverage Snapshot'
update-comment: false

Expand All @@ -300,14 +355,15 @@ jobs:
min-coverage-overall: 0
min-coverage-changed-files: 0
skip-if-no-changes: true
comment-type: summary
title: '## PR Code Coverage Report'
update-comment: false

- name: Enforce coverage gates
env:
BASE_OVERALL_RAW: ${{ steps.jacoco-base.outputs.coverage-overall }}
PR_OVERALL_RAW: ${{ steps.jacoco-pr.outputs.coverage-overall }}
PR_CHANGED_RAW: ${{ steps.jacoco-pr.outputs.coverage-changed-files }}
CHANGED_LINE_RAW: ${{ steps.diff-cover.outputs.changed_line_coverage }}
run: |
set -euo pipefail

Expand All @@ -329,7 +385,7 @@ jobs:
# 1) Parse metrics from jacoco-report outputs
BASE_OVERALL="$(sanitize "$BASE_OVERALL_RAW")"
PR_OVERALL="$(sanitize "$PR_OVERALL_RAW")"
PR_CHANGED="$(sanitize "$PR_CHANGED_RAW")"
CHANGED_LINE="$(sanitize "$CHANGED_LINE_RAW")"

if ! is_number "$BASE_OVERALL" || ! is_number "$PR_OVERALL"; then
echo "Failed to parse coverage values: base='${BASE_OVERALL}', pr='${PR_OVERALL}'."
Expand All @@ -340,19 +396,16 @@ jobs:
DELTA=$(awk -v pr="$PR_OVERALL" -v base="$BASE_OVERALL" 'BEGIN { printf "%.4f", pr - base }')
DELTA_OK=$(compare_float "${DELTA} >= ${MAX_DROP}")

CHANGED_STATUS="SKIPPED (no changed coverage value)"
CHANGED_OK=1
if [ -n "$PR_CHANGED" ] && [ "$PR_CHANGED" != "NaN" ]; then
if ! is_number "$PR_CHANGED"; then
echo "Failed to parse changed-files coverage: changed='${PR_CHANGED}'."
exit 1
fi
CHANGED_OK=$(compare_float "${PR_CHANGED} > ${MIN_CHANGED}")
if [ "$CHANGED_OK" -eq 1 ]; then
CHANGED_STATUS="PASS (> ${MIN_CHANGED}%)"
else
CHANGED_STATUS="FAIL (<= ${MIN_CHANGED}%)"
fi
if [ -z "$CHANGED_LINE" ] || [ "$CHANGED_LINE" = "NaN" ] || ! is_number "$CHANGED_LINE"; then
echo "Failed to parse changed-line coverage: changed-line='${CHANGED_LINE}'."
exit 1
fi

CHANGED_LINE_OK=$(compare_float "${CHANGED_LINE} > ${MIN_CHANGED}")
if [ "$CHANGED_LINE_OK" -eq 1 ]; then
CHANGED_LINE_STATUS="PASS (> ${MIN_CHANGED}%)"
else
CHANGED_LINE_STATUS="FAIL (<= ${MIN_CHANGED}%)"
Comment on lines +404 to +408
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Use inclusive comparison for the minimum changed-line threshold.

MIN_CHANGED=60 reads as “at least 60%,” but > makes exactly 60.0% fail. Use >= unless the strict boundary is intentional.

Proposed fix
-          CHANGED_LINE_OK=$(compare_float "${CHANGED_LINE} > ${MIN_CHANGED}")
+          CHANGED_LINE_OK=$(compare_float "${CHANGED_LINE} >= ${MIN_CHANGED}")
           if [ "$CHANGED_LINE_OK" -eq 1 ]; then
-            CHANGED_LINE_STATUS="PASS (> ${MIN_CHANGED}%)"
+            CHANGED_LINE_STATUS="PASS (>= ${MIN_CHANGED}%)"
           else
-            CHANGED_LINE_STATUS="FAIL (<= ${MIN_CHANGED}%)"
+            CHANGED_LINE_STATUS="FAIL (< ${MIN_CHANGED}%)"
           fi
           if [ "$CHANGED_LINE_OK" -ne 1 ]; then
-            echo "Coverage gate failed: changed-line coverage must be > 60%."
+            echo "Coverage gate failed: changed-line coverage must be >= 60%."
             echo "changed-line=${CHANGED_LINE}%"
             exit 1
           fi

Also applies to: 447-449

🤖 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 404 - 408, The comparison
currently uses a strict greater-than, causing values exactly equal to
MIN_CHANGED to fail; change the compare_float invocation(s) to use ">=" instead
of ">" where CHANGED_LINE_OK is computed (and similarly at the other occurrence
around CHANGED_LINE_STATUS) so that CHANGED_LINE == MIN_CHANGED yields PASS;
update the calls that produce CHANGED_LINE_OK (the compare_float expression
involving CHANGED_LINE and MIN_CHANGED) in both places mentioned and keep the
CHANGED_LINE_STATUS logic unchanged.

fi

# 3) Output base metrics (always visible in logs + step summary)
Expand All @@ -362,11 +415,11 @@ jobs:
fi

METRICS_TEXT=$(cat <<EOF
Changed Files Coverage: ${PR_CHANGED}%
Changed-line Coverage: ${CHANGED_LINE}%
PR Overall Coverage: ${PR_OVERALL}%
Base Overall Coverage: ${BASE_OVERALL}%
Delta (PR - Base): ${DELTA}%
Changed Files Gate: ${CHANGED_STATUS}
Changed-line Gate: ${CHANGED_LINE_STATUS}
Overall Delta Gate: ${OVERALL_STATUS}
EOF
)
Expand All @@ -376,11 +429,11 @@ jobs:
{
echo "### Coverage Gate Metrics"
echo ""
echo "- Changed Files Coverage: ${PR_CHANGED}%"
echo "- Changed-line Coverage: ${CHANGED_LINE}%"
echo "- PR Overall Coverage: ${PR_OVERALL}%"
echo "- Base Overall Coverage: ${BASE_OVERALL}%"
echo "- Delta (PR - Base): ${DELTA}%"
echo "- Changed Files Gate: ${CHANGED_STATUS}"
echo "- Changed-line Gate: ${CHANGED_LINE_STATUS}"
echo "- Overall Delta Gate: ${OVERALL_STATUS}"
} >> "$GITHUB_STEP_SUMMARY"

Expand All @@ -391,14 +444,9 @@ jobs:
exit 1
fi

if [ -z "$PR_CHANGED" ] || [ "$PR_CHANGED" = "NaN" ]; then
echo "No changed-files coverage value detected, skip changed-files gate."
exit 0
fi

if [ "$CHANGED_OK" -ne 1 ]; then
echo "Coverage gate failed: changed files coverage must be > 60%."
echo "changed=${PR_CHANGED}%"
if [ "$CHANGED_LINE_OK" -ne 1 ]; then
echo "Coverage gate failed: changed-line coverage must be > 60%."
echo "changed-line=${CHANGED_LINE}%"
exit 1
fi

Expand Down
Loading