Skip to content

Commit 75971fa

Browse files
committed
fix(ci): collect correct changed lines coverage
Signed-off-by: imeoer <yansong.ys@antgroup.com>
1 parent ac56eba commit 75971fa

File tree

2 files changed

+83
-20
lines changed

2 files changed

+83
-20
lines changed

.github/workflows/coverage-comment.yml

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,22 +26,41 @@ jobs:
2626
github.event.workflow_run.conclusion == 'failure')
2727
steps:
2828
- name: Download coverage artifacts
29+
id: download
30+
continue-on-error: true
2931
uses: actions/download-artifact@v4
3032
with:
3133
name: coverage-report
34+
path: coverage-artifact
3235
github-token: ${{ secrets.GITHUB_TOKEN }}
3336
# Download from the triggering workflow run, not the current one.
3437
run-id: ${{ github.event.workflow_run.id }}
3538

3639
- name: Read PR number
3740
id: pr
3841
run: |
39-
if [ -f pr-number.txt ]; then
40-
echo "number=$(cat pr-number.txt)" >> "$GITHUB_OUTPUT"
42+
if [ -f coverage-artifact/pr-number.txt ]; then
43+
echo "number=$(cat coverage-artifact/pr-number.txt)" >> "$GITHUB_OUTPUT"
44+
elif [ -n "${{ github.event.workflow_run.pull_requests[0].number }}" ]; then
45+
echo "number=${{ github.event.workflow_run.pull_requests[0].number }}" >> "$GITHUB_OUTPUT"
4146
else
4247
echo "number=" >> "$GITHUB_OUTPUT"
4348
fi
4449
50+
- name: Prepare coverage comment body
51+
run: |
52+
if [ -f coverage-artifact/coverage-report.md ]; then
53+
cp coverage-artifact/coverage-report.md coverage-report.md
54+
else
55+
cat > coverage-report.md <<EOF
56+
## 📊 Code Coverage Report
57+
58+
Coverage workflow concluded with **${{ github.event.workflow_run.conclusion }}**, but no coverage report artifact was available.
59+
60+
Triggering workflow run: ${{ github.event.workflow_run.html_url }}
61+
EOF
62+
fi
63+
4564
- name: Post coverage comment on PR
4665
if: steps.pr.outputs.number != ''
4766
uses: marocchino/sticky-pull-request-comment@v2

.github/workflows/coverage.yml

Lines changed: 62 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -84,74 +84,118 @@ jobs:
8484
BASE=origin/${{ github.base_ref }}
8585
DIFF_OUTPUT=$(diff-cover coverage.xml \
8686
--compare-branch="${BASE}" \
87+
--format json:diff-cover.json \
8788
--fail-under=${{ env.THRESHOLD_DIFF }} \
8889
2>&1) && DIFF_EXIT=0 || DIFF_EXIT=$?
8990
90-
DIFF_PCT=$(echo "$DIFF_OUTPUT" | grep -oP 'Diff coverage is \K[0-9.]+' || echo "N/A")
91+
if [ -f diff-cover.json ]; then
92+
DIFF_PCT=$(python3 - <<'PY'
93+
import json
94+
95+
with open('diff-cover.json', encoding='utf-8') as f:
96+
report = json.load(f)
97+
98+
num_changed_lines = report.get('num_changed_lines', 0)
99+
total_num_lines = report.get('total_num_lines', 0)
100+
total_percent_covered = report.get('total_percent_covered', 'N/A')
101+
102+
if num_changed_lines > 0 and total_num_lines == 0:
103+
print('N/A')
104+
else:
105+
print(total_percent_covered)
106+
PY
107+
)
108+
else
109+
DIFF_PCT="N/A"
110+
fi
111+
112+
if [ "$DIFF_PCT" = "N/A" ]; then
113+
DIFF_DISPLAY="N/A"
114+
else
115+
DIFF_DISPLAY="${DIFF_PCT}%"
116+
fi
117+
91118
echo "diff_pct=${DIFF_PCT}" >> "$GITHUB_OUTPUT"
119+
echo "diff_display=${DIFF_DISPLAY}" >> "$GITHUB_OUTPUT"
92120
echo "$DIFF_OUTPUT"
93121

94-
if [ "$DIFF_EXIT" -ne 0 ]; then
122+
if [ "$DIFF_EXIT" -ne 0 ] || [ "$DIFF_PCT" = "N/A" ]; then
95123
echo "diff_status=fail" >> "$GITHUB_OUTPUT"
124+
125+
if [ "$DIFF_PCT" = "N/A" ]; then
126+
echo "❌ Changed-line coverage could not be computed because diff-cover found changed lines without matching coverage information."
127+
fi
96128
else
97129
echo "diff_status=pass" >> "$GITHUB_OUTPUT"
98130
fi
99131

100132
# ── Generate per-package coverage table ──────────────────────────────
101133
- name: Generate coverage report markdown
134+
if: always()
102135
run: |
103136
{
104137
echo "## 📊 Code Coverage Report"
105138
echo ""
106139
107140
TOTAL="${{ steps.total_coverage.outputs.total }}"
108141
STATUS="${{ steps.total_coverage.outputs.status }}"
142+
[ -n "$TOTAL" ] || TOTAL="N/A"
109143
[ "$STATUS" = "pass" ] && ICON="✅" || ICON="❌"
110144
111145
echo "| Metric | Coverage | Threshold | Status |"
112146
echo "|--------|----------|-----------|--------|"
113147
echo "| Overall | **${TOTAL}%** | ${{ env.THRESHOLD_TOTAL }}% | ${ICON} |"
114148
115149
if [ "${{ github.event_name }}" = "pull_request" ]; then
116-
DIFF_PCT="${{ steps.diff_coverage.outputs.diff_pct }}"
150+
DIFF_DISPLAY="${{ steps.diff_coverage.outputs.diff_display }}"
117151
DIFF_STATUS="${{ steps.diff_coverage.outputs.diff_status }}"
152+
[ -n "$DIFF_DISPLAY" ] || DIFF_DISPLAY="N/A"
118153
[ "$DIFF_STATUS" = "pass" ] && DIFF_ICON="✅" || DIFF_ICON="❌"
119-
echo "| Changed lines | **${DIFF_PCT}%** | ${{ env.THRESHOLD_DIFF }}% | ${DIFF_ICON} |"
154+
echo "| Changed lines | **${DIFF_DISPLAY}** | ${{ env.THRESHOLD_DIFF }}% | ${DIFF_ICON} |"
120155
fi
121156
122-
echo ""
123-
echo "<details>"
124-
echo "<summary>📦 Per-package breakdown</summary>"
125-
echo ""
126-
echo '```'
127-
go tool cover -func=coverage.out | grep -v "^total:" | \
128-
awk '{printf "%-80s %s\n", $1, $3}' | sort
129-
echo ""
130-
go tool cover -func=coverage.out | grep "^total:"
131-
echo '```'
132-
echo ""
133-
echo "</details>"
157+
if [ -f coverage.out ]; then
158+
echo ""
159+
echo "<details>"
160+
echo "<summary>📦 Per-package breakdown</summary>"
161+
echo ""
162+
echo '```'
163+
go tool cover -func=coverage.out | grep -v "^total:" | \
164+
awk '{printf "%-80s %s\n", $1, $3}' | sort
165+
echo ""
166+
go tool cover -func=coverage.out | grep "^total:"
167+
echo '```'
168+
echo ""
169+
echo "</details>"
170+
else
171+
echo ""
172+
echo "Coverage artifacts were not generated because the workflow failed before coverage collection completed."
173+
fi
134174
} > coverage-report.md
135175
136176
# ── Write step summary ────────────────────────────────────────────────
137177
- name: Write job summary
178+
if: always()
138179
run: cat coverage-report.md >> "$GITHUB_STEP_SUMMARY"
139180

140181
# ── Save PR number so the comment workflow can find the right PR ──────
141182
- name: Save PR number
142-
if: github.event_name == 'pull_request'
183+
if: always() && github.event_name == 'pull_request'
143184
run: echo "${{ github.event.pull_request.number }}" > pr-number.txt
144185

145186
# ── Upload artifacts (report + pr-number for comment workflow) ────────
146187
- name: Upload coverage artifacts
188+
if: always()
147189
uses: actions/upload-artifact@v4
148190
with:
149191
name: coverage-report
150192
path: |
151193
coverage.out
152194
coverage.xml
195+
diff-cover.json
153196
coverage-report.md
154197
pr-number.txt
198+
if-no-files-found: warn
155199
retention-days: 14
156200

157201
- name: Upload coverage to Codecov
@@ -176,6 +220,6 @@ jobs:
176220
github.event_name == 'pull_request' &&
177221
steps.diff_coverage.outputs.diff_status == 'fail'
178222
run: |
179-
echo "❌ Changed-line coverage ${{ steps.diff_coverage.outputs.diff_pct }}% is below the required ${{ env.THRESHOLD_DIFF }}%"
223+
echo "❌ Changed-line coverage ${{ steps.diff_coverage.outputs.diff_display }} is below the required ${{ env.THRESHOLD_DIFF }}%"
180224
exit 1
181225

0 commit comments

Comments
 (0)