Skip to content
Merged
Show file tree
Hide file tree
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
39 changes: 39 additions & 0 deletions .github/workflows/coverage-comment.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Post Coverage Comment
on:
workflow_run:
workflows: ["Build and Deploy Snapshot"]
types: [completed]

permissions:
pull-requests: write

jobs:
comment:
runs-on: ubuntu-24.04
if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success'
steps:
- name: Download comment artifact
uses: dawidd6/action-download-artifact@v6
with:
name: pr-comment
path: pr-comment/
run_id: ${{ github.event.workflow_run.id }}
github_token: ${{ secrets.GITHUB_TOKEN }}

- name: Post coverage comment
run: |
PR_NUMBER=$(cat pr-comment/pr-number.txt)
COMMENT_BODY=$(cat pr-comment/comment-body.txt)

# Find and delete existing comment
COMMENT_ID=$(gh pr view $PR_NUMBER --json comments \
--jq '.comments[] | select(.body | contains("<!-- jacoco-coverage-comment -->")) | .id' | head -1)

if [ -n "$COMMENT_ID" ]; then
gh api -X DELETE "repos/${{ github.repository }}/issues/comments/$COMMENT_ID" || true
fi

# Post new comment
gh pr comment $PR_NUMBER --body "$COMMENT_BODY"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
120 changes: 90 additions & 30 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,22 @@ jobs:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./target/site/jacoco/jacoco.xml
flags: unittests
- name: Upload coverage report as artifact
if: ${{ matrix.release_build && github.event_name != 'pull_request' }}
uses: actions/upload-artifact@v4
with:
name: jacoco-report
path: target/site/jacoco/jacoco.csv
retention-days: 30
- name: Download base branch coverage
if: ${{ matrix.release_build && github.event_name == 'pull_request' }}
uses: dawidd6/action-download-artifact@v6
continue-on-error: true
with:
workflow: main.yml
branch: ${{ github.event.pull_request.base.ref }}
name: jacoco-report
path: base-coverage/
- name: Generate coverage summary
if: ${{ matrix.release_build && github.event_name == 'pull_request' }}
id: jacoco
Expand All @@ -80,51 +96,95 @@ jobs:
generate-coverage-badge: false
generate-branches-badge: false
generate-summary: true
- name: Add coverage comment to PR
- name: Generate coverage comment
if: ${{ matrix.release_build && github.event_name == 'pull_request' }}
continue-on-error: true
run: |
# Helper functions
parse_coverage() {
local csv_file=$1 col_missed=$2 col_covered=$3
awk -F',' -v m="$col_missed" -v c="$col_covered" \
'NR>1 && $1=="Jackson-databind" {
missed=$m; covered=$c;
if (missed + covered > 0) printf "%.1f", (covered * 100.0) / (missed + covered)
}' "$csv_file" | head -1
}

format_delta() {
local delta=$1
if awk -v d="$delta" 'BEGIN { exit (d >= 0) ? 0 : 1 }'; then
echo "+${delta}%|📈"
else
echo "${delta}%|📉"
fi
}

get_color() {
awk -v v="$1" 'BEGIN {
if (v >= 80) print "brightgreen"
else if (v >= 60) print "green"
else if (v >= 40) print "yellow"
else print "red"
}'
}

# Convert decimal to percentage and round to 1 decimal place
COVERAGE=$(awk -v cov="${{ steps.jacoco.outputs.coverage }}" 'BEGIN { printf "%.1f", cov * 100 }')
BRANCHES=$(awk -v br="${{ steps.jacoco.outputs.branches }}" 'BEGIN { printf "%.1f", br * 100 }')

# Determine color for coverage badge using awk (more portable than bc)
COV_COLOR=$(awk -v cov="$COVERAGE" 'BEGIN {
if (cov >= 80) print "brightgreen"
else if (cov >= 60) print "green"
else if (cov >= 40) print "yellow"
else print "red"
}')

BR_COLOR=$(awk -v br="$BRANCHES" 'BEGIN {
if (br >= 80) print "brightgreen"
else if (br >= 60) print "green"
else if (br >= 40) print "yellow"
else print "red"
}')
# Check if base coverage artifact was downloaded and calculate deltas
HAS_DELTA=false
if [ -f "base-coverage/jacoco.csv" ]; then
echo "Found base branch coverage from artifact"
BASE_COVERAGE=$(parse_coverage "base-coverage/jacoco.csv" 4 5)
BASE_BRANCHES=$(parse_coverage "base-coverage/jacoco.csv" 6 7)

COMMENT_BODY="## :test_tube: Code Coverage Report
if [ -n "$BASE_COVERAGE" ] && [ -n "$BASE_BRANCHES" ]; then
COV_DELTA=$(awk -v curr="$COVERAGE" -v base="$BASE_COVERAGE" 'BEGIN { printf "%.1f", curr - base }')
BR_DELTA=$(awk -v curr="$BRANCHES" -v base="$BASE_BRANCHES" 'BEGIN { printf "%.1f", curr - base }')

IFS='|' read -r COV_DELTA_STR COV_DELTA_EMOJI <<< "$(format_delta "$COV_DELTA")"
IFS='|' read -r BR_DELTA_STR BR_DELTA_EMOJI <<< "$(format_delta "$BR_DELTA")"

HAS_DELTA=true
fi
fi

# Determine badge colors
COV_COLOR=$(get_color "$COVERAGE")
BR_COLOR=$(get_color "$BRANCHES")

| Metric | Coverage |
# Build coverage table with or without deltas
if [ "$HAS_DELTA" = "true" ]; then
COVERAGE_TABLE="| Metric | Coverage | Change |
|--------|----------|--------|
| **Instructions** | ![coverage](https://img.shields.io/badge/coverage-${COVERAGE}%25-${COV_COLOR}) **${COVERAGE}%** | ${COV_DELTA_EMOJI} **${COV_DELTA_STR}** |
| **Branches** | ![branches](https://img.shields.io/badge/branches-${BRANCHES}%25-${BR_COLOR}) **${BRANCHES}%** | ${BR_DELTA_EMOJI} **${BR_DELTA_STR}** |"
else
COVERAGE_TABLE="| Metric | Coverage |
|--------|----------|
| **Instructions** | ![coverage](https://img.shields.io/badge/coverage-${COVERAGE}%25-${COV_COLOR}) **${COVERAGE}%** |
| **Branches** | ![branches](https://img.shields.io/badge/branches-${BRANCHES}%25-${BR_COLOR}) **${BRANCHES}%** |
| **Branches** | ![branches](https://img.shields.io/badge/branches-${BRANCHES}%25-${BR_COLOR}) **${BRANCHES}%** |"
fi

> Coverage data generated from JaCoCo test results
COMMENT_BODY="## :test_tube: Code Coverage Report

<!-- jacoco-coverage-comment -->"
$COVERAGE_TABLE

# Find and delete existing coverage comment
COMMENT_ID=$(gh pr view ${{ github.event.pull_request.number }} --json comments --jq '.comments[] | select(.body | contains("<!-- jacoco-coverage-comment -->")) | .id' | head -1)
> Coverage data generated from JaCoCo test results

if [ -n "$COMMENT_ID" ]; then
gh api -X DELETE "repos/${{ github.repository }}/issues/comments/$COMMENT_ID" || true
fi
<!-- jacoco-coverage-comment -->"

# Post new comment (may fail for PRs from forks due to permissions)
gh pr comment ${{ github.event.pull_request.number }} --body "$COMMENT_BODY"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Save comment for the workflow_run
mkdir -p pr-comment
echo "${{ github.event.pull_request.number }}" > pr-comment/pr-number.txt
echo "$COMMENT_BODY" > pr-comment/comment-body.txt
- name: Upload PR comment
if: ${{ matrix.release_build && github.event_name == 'pull_request' }}
uses: actions/upload-artifact@v4
with:
name: pr-comment
path: pr-comment/
retention-days: 1

trigger-dep-build-v2:
name: Trigger v2 dep builds
Expand Down