From a20bbbe401de94f0f110cef677dc47da3d62033d Mon Sep 17 00:00:00 2001 From: Marko Cupic <71461781+cupicmarko@users.noreply.github.com> Date: Mon, 11 Aug 2025 06:30:01 +0200 Subject: [PATCH 1/4] Update coverage.yml Update coverage job to run on push --- .github/workflows/coverage.yml | 38 ++++++++++++++-------------------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 1071253..b0d7bf1 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -1,34 +1,26 @@ -name: Coverage +name: Coverage (Push) on: push: - branches: [main] - pull_request: - types: [opened, synchronize, reopened] - + branches: ['**'] # all branches, including main + permissions: contents: read - pull-requests: write + actions: write jobs: - coverage: + coverage-push: runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Install cargo-llvm-cov - run: cargo install cargo-llvm-cov - - - name: Install llvm-tools - run: rustup component add llvm-tools-preview + - uses: actions/checkout@v4 - - name: Run code coverage - run: cargo llvm-cov --workspace --lcov --output-path lcov.info --ignore-filename-regex '^examples/' + - run: cargo install cargo-llvm-cov + - run: rustup component add llvm-tools-preview + - run: cargo llvm-cov --workspace --lcov --output-path lcov.info --ignore-filename-regex '^examples/' - - name: Comment PR with coverage - continue-on-error: true - uses: romeovs/lcov-reporter-action@v0.4.0 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - lcov-file: lcov.info + - name: Upload branch coverage artifact + uses: actions/upload-artifact@v4 + with: + name: coverage-lcov + path: lcov.info + retention-days: 21 From ca4d8d732e7116f38f57ba07c8fa40f1f39ac6f8 Mon Sep 17 00:00:00 2001 From: Marko Cupic <71461781+cupicmarko@users.noreply.github.com> Date: Mon, 11 Aug 2025 06:32:20 +0200 Subject: [PATCH 2/4] Create coverage-pr.yml Add job running coverage on PR --- .github/workflows/coverage-pr.yml | 148 ++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 .github/workflows/coverage-pr.yml diff --git a/.github/workflows/coverage-pr.yml b/.github/workflows/coverage-pr.yml new file mode 100644 index 0000000..c880154 --- /dev/null +++ b/.github/workflows/coverage-pr.yml @@ -0,0 +1,148 @@ +name: Coverage (PR) + +on: + pull_request: + types: [opened, synchronize, reopened] + +permissions: + contents: read + pull-requests: write + actions: read + +jobs: + cov-head: + runs-on: ubuntu-latest + container: + image: rust:1.88 + outputs: + pct: ${{ steps.cov.outputs.coverage }} + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + + - run: cargo install cargo-llvm-cov + - run: rustup component add llvm-tools-preview + - run: cargo llvm-cov --workspace --lcov --output-path lcov.info --ignore-filename-regex '^examples/' + + - name: Upload head coverage artifact (for stacked PRs) + uses: actions/upload-artifact@v4 + with: + name: coverage-lcov + path: lcov.info + retention-days: 21 + + - name: Extract total coverage % (head) + id: cov + shell: bash + run: | + pct=$(awk -F: ' + /^LH:/ {lh += $2} + /^LF:/ {lf += $2} + END { if (lf>0) printf "%.2f", (lh/lf)*100; else print "0.00" } + ' lcov.info) + echo "coverage=$pct" >> "$GITHUB_OUTPUT" + + compare-and-comment: + needs: cov-head + runs-on: ubuntu-latest + container: + image: rust:1.88 + steps: + # 1) Try to download base artifact from the base branch + - name: Download base branch artifact (if present) + id: dl + uses: dawidd6/action-download-artifact@v6 + with: + name: coverage-lcov + branch: ${{ github.event.pull_request.base.ref }} + if_no_artifact_found: ignore # don't fail if missing + + - name: Check if base artifact was found + id: base_art + shell: bash + run: | + if [ -f "coverage-lcov/lcov.info" ]; then + echo "found=true" >> "$GITHUB_OUTPUT" + else + echo "found=false" >> "$GITHUB_OUTPUT" + fi + + # 2) Fallback: if no artifact, checkout base commit and compute base coverage here + - name: Checkout base + if: ${{ steps.base_art.outputs.found == 'false' }} + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.base.sha }} + + - name: Install cargo-llvm-cov (fallback path) + if: ${{ steps.base_art.outputs.found == 'false' }} + run: cargo install cargo-llvm-cov + + - name: Install llvm-tools (fallback path) + if: ${{ steps.base_art.outputs.found == 'false' }} + run: rustup component add llvm-tools-preview + + - name: Run base coverage (fallback path) + if: ${{ steps.base_art.outputs.found == 'false' }} + run: cargo llvm-cov --workspace --lcov --output-path base.lcov.info --ignore-filename-regex '^examples/' + + # 3) Extract base coverage (from artifact or from freshly computed fallback) + - name: Extract total coverage % (base) + id: basecov + shell: bash + run: | + file="coverage-lcov/lcov.info" + if [ "${{ steps.base_art.outputs.found }}" != "true" ]; then + file="base.lcov.info" + fi + pct=$(awk -F: ' + /^LH:/ {lh += $2} + /^LF:/ {lf += $2} + END { if (lf>0) printf "%.2f", (lh/lf)*100; else print "0.00" } + ' "$file") + echo "coverage=$pct" >> "$GITHUB_OUTPUT" + + - name: Find existing coverage comment + id: find_comment + uses: peter-evans/find-comment@v3 + with: + issue-number: ${{ github.event.pull_request.number }} + comment-author: 'github-actions[bot]' + body-includes: '' + + - name: Comment only if head < base + uses: actions/github-script@v7 + with: + script: | + const base = parseFloat(`${{ steps.basecov.outputs.coverage }}`); + const head = parseFloat(`${{ needs.cov-head.outputs.pct }}`); + if (!(base >= 0) || !(head >= 0)) { + core.setFailed(`Bad coverage values. base=${base} head=${head}`); + return; + } + if (head >= base) { + core.info(`No drop (head ${head}% >= base ${base}%).`); + return; + } + const delta = (head - base).toFixed(2); + const body = ` + **Coverage (base → head):** \`${base}% → ${head}%\` ⬇️ ${Math.abs(delta)} pp + _Only posts when PR coverage is lower than the base branch's latest push (or freshly computed base)._ + `; + const commentId = `${{ steps.find_comment.outputs.comment-id }}`; + if (commentId) { + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: parseInt(commentId, 10), + body + }); + } else { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body + }); + } From 17623597785ebb1e51dbeb63de760755d1af9462 Mon Sep 17 00:00:00 2001 From: Marko Cupic Date: Mon, 25 Aug 2025 14:41:37 +0200 Subject: [PATCH 3/4] Remove the pinned rust version from coverage-pr.yml --- .github/workflows/coverage-pr.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/coverage-pr.yml b/.github/workflows/coverage-pr.yml index c880154..bdf3d0f 100644 --- a/.github/workflows/coverage-pr.yml +++ b/.github/workflows/coverage-pr.yml @@ -12,8 +12,6 @@ permissions: jobs: cov-head: runs-on: ubuntu-latest - container: - image: rust:1.88 outputs: pct: ${{ steps.cov.outputs.coverage }} steps: @@ -46,13 +44,11 @@ jobs: compare-and-comment: needs: cov-head runs-on: ubuntu-latest - container: - image: rust:1.88 steps: # 1) Try to download base artifact from the base branch - name: Download base branch artifact (if present) id: dl - uses: dawidd6/action-download-artifact@v6 + uses: dawidd6/action-download-artifact@ac66b43f0e6a346234dd65d4d0c8fbb31cb316e5 with: name: coverage-lcov branch: ${{ github.event.pull_request.base.ref }} From a5d56fd2c8f52f9f8fd0be7bd9b5d4c6072ffb6f Mon Sep 17 00:00:00 2001 From: Marko Cupic Date: Mon, 25 Aug 2025 14:51:48 +0200 Subject: [PATCH 4/4] Hardcode version for find-comment github-action --- .github/workflows/coverage-pr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/coverage-pr.yml b/.github/workflows/coverage-pr.yml index bdf3d0f..4a196aa 100644 --- a/.github/workflows/coverage-pr.yml +++ b/.github/workflows/coverage-pr.yml @@ -101,7 +101,7 @@ jobs: - name: Find existing coverage comment id: find_comment - uses: peter-evans/find-comment@v3 + uses: peter-evans/find-comment@3eae4d37986fb5a8592848f6a574fdf654e61f9e with: issue-number: ${{ github.event.pull_request.number }} comment-author: 'github-actions[bot]'