Skip to content

Commit 4bc071b

Browse files
committed
ci: code coverage report
1 parent ba87eac commit 4bc071b

File tree

3 files changed

+215
-0
lines changed

3 files changed

+215
-0
lines changed

.github/actions-rs/grcov.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
output-type: lcov
2+
output-path: ./lcov.info
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
name: Generate Coverage Report (PR)
2+
3+
on:
4+
push:
5+
branches:
6+
- develop
7+
pull_request:
8+
branches:
9+
- develop
10+
11+
env:
12+
CARGO_TERM_COLOR: always
13+
14+
jobs:
15+
coverage:
16+
name: Generate Coverage Report
17+
environment: coverage
18+
runs-on: ubuntu-latest
19+
env:
20+
CARGO_INCREMENTAL: "0"
21+
RUSTFLAGS: "-Cinstrument-coverage"
22+
23+
steps:
24+
- name: Checkout repository
25+
uses: actions/checkout@v4
26+
27+
- name: Install LLVM tools
28+
run: sudo apt-get update && sudo apt-get install -y llvm
29+
30+
- id: setup
31+
name: Setup Toolchain
32+
uses: dtolnay/rust-toolchain@nightly
33+
with:
34+
toolchain: nightly
35+
components: llvm-tools-preview
36+
37+
- id: cache
38+
name: Enable Workflow Cache
39+
uses: Swatinem/rust-cache@v2
40+
41+
- id: tools
42+
name: Install Tools
43+
uses: taiki-e/install-action@v2
44+
with:
45+
tool: grcov,cargo-llvm-cov
46+
47+
- id: build_and_test
48+
name: Build and test
49+
run: |
50+
echo "${{ secrets.CODECOV_TOKEN }}"
51+
cargo clean
52+
cargo build
53+
cargo test -- --nocapture
54+
55+
- id: coverage
56+
name: Generate Coverage Report
57+
run: |
58+
cargo llvm-cov --lcov --output-path=./lcov.info
59+
60+
- name: Store PR number and commit SHA
61+
run: |
62+
echo "Storing PR number ${{ github.event.number }}"
63+
echo "${{ github.event.number }}" > pr_number.txt
64+
65+
echo "Storing commit SHA ${{ github.event.pull_request.head.sha }}"
66+
echo "${{ github.event.pull_request.head.sha }}" > commit_sha.txt
67+
68+
# Workaround for https://github.com/orgs/community/discussions/25220
69+
# Triggered sub-workflow is not able to detect the original commit/PR which is available
70+
# in this workflow.
71+
- name: Store PR number
72+
uses: actions/upload-artifact@v4
73+
with:
74+
name: pr_number
75+
path: pr_number.txt
76+
77+
- name: Store commit SHA
78+
uses: actions/upload-artifact@v4
79+
with:
80+
name: commit_sha
81+
path: commit_sha.txt
82+
83+
# This stores the coverage report in artifacts. The actual upload to Codecov
84+
# is executed by a different workflow `coverage-report.yml`. The reason for this
85+
# split is because `on.pull_request` workflows don't have access to secrets.
86+
- name: Store coverage report in artifacts
87+
uses: actions/upload-artifact@v4
88+
with:
89+
name: codecov_report
90+
path: ./lcov.info
91+
92+
- run: |
93+
echo "The coverage report was stored in Github artifacts."
94+
echo "It will be uploaded to Codecov using [coverage-report.yml] workflow shortly."
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
name: Upload Coverage Report (PR)
2+
3+
on:
4+
# This workflow is triggered after every successfull execution
5+
# of `Generate Coverage Report` workflow.
6+
workflow_run:
7+
workflows: ["Generate Coverage Report (PR)"]
8+
types:
9+
- completed
10+
11+
permissions:
12+
actions: write
13+
contents: write
14+
issues: write
15+
pull-requests: write
16+
17+
jobs:
18+
coverage:
19+
name: Upload Coverage Report
20+
environment: coverage
21+
runs-on: ubuntu-latest
22+
steps:
23+
- name: "Download existing coverage report"
24+
id: prepare_report
25+
uses: actions/github-script@v7
26+
with:
27+
script: |
28+
var fs = require('fs');
29+
30+
// List artifacts of the workflow run that triggered this workflow
31+
var artifacts = await github.rest.actions.listWorkflowRunArtifacts({
32+
owner: context.repo.owner,
33+
repo: context.repo.repo,
34+
run_id: context.payload.workflow_run.id,
35+
});
36+
37+
let codecovReport = artifacts.data.artifacts.filter((artifact) => {
38+
return artifact.name == "codecov_report";
39+
});
40+
41+
if (codecovReport.length != 1) {
42+
throw new Error("Unexpected number of {codecov_report} artifacts: " + codecovReport.length);
43+
}
44+
45+
var download = await github.rest.actions.downloadArtifact({
46+
owner: context.repo.owner,
47+
repo: context.repo.repo,
48+
artifact_id: codecovReport[0].id,
49+
archive_format: 'zip',
50+
});
51+
fs.writeFileSync('codecov_report.zip', Buffer.from(download.data));
52+
53+
let prNumber = artifacts.data.artifacts.filter((artifact) => {
54+
return artifact.name == "pr_number";
55+
});
56+
57+
if (prNumber.length != 1) {
58+
throw new Error("Unexpected number of {pr_number} artifacts: " + prNumber.length);
59+
}
60+
61+
var download = await github.rest.actions.downloadArtifact({
62+
owner: context.repo.owner,
63+
repo: context.repo.repo,
64+
artifact_id: prNumber[0].id,
65+
archive_format: 'zip',
66+
});
67+
fs.writeFileSync('pr_number.zip', Buffer.from(download.data));
68+
69+
let commitSha = artifacts.data.artifacts.filter((artifact) => {
70+
return artifact.name == "commit_sha";
71+
});
72+
73+
if (commitSha.length != 1) {
74+
throw new Error("Unexpected number of {commit_sha} artifacts: " + commitSha.length);
75+
}
76+
77+
var download = await github.rest.actions.downloadArtifact({
78+
owner: context.repo.owner,
79+
repo: context.repo.repo,
80+
artifact_id: commitSha[0].id,
81+
archive_format: 'zip',
82+
});
83+
fs.writeFileSync('commit_sha.zip', Buffer.from(download.data));
84+
85+
- id: parse_previous_artifacts
86+
run: |
87+
unzip codecov_report.zip
88+
unzip pr_number.zip
89+
unzip commit_sha.zip
90+
91+
echo "Detected PR is: $(<pr_number.txt)"
92+
echo "Detected commit_sha is: $(<commit_sha.txt)"
93+
94+
# Make the params available as step output
95+
echo "override_pr=$(<pr_number.txt)" >> "$GITHUB_OUTPUT"
96+
echo "override_commit=$(<commit_sha.txt)" >> "$GITHUB_OUTPUT"
97+
98+
- name: Checkout repository
99+
uses: actions/checkout@v4
100+
with:
101+
ref: ${{ steps.parse_previous_artifacts.outputs.override_commit || '' }}
102+
path: repo_root
103+
104+
- name: Upload coverage to Codecov
105+
uses: codecov/codecov-action@v4
106+
with:
107+
verbose: true
108+
token: ${{ secrets.CODECOV_TOKEN }}
109+
files: ${{ github.workspace }}/lcov.info
110+
fail_ci_if_error: true
111+
# Manual overrides for these parameters are needed because automatic detection
112+
# in codecov-action does not work for non-`pull_request` workflows.
113+
# In `main` branch push, these default to empty strings since we want to run
114+
# the analysis on HEAD.
115+
override_commit: ${{ steps.parse_previous_artifacts.outputs.override_commit || '' }}
116+
override_pr: ${{ steps.parse_previous_artifacts.outputs.override_pr || '' }}
117+
working-directory: ${{ github.workspace }}/repo_root
118+
# Location where coverage report files are searched for
119+
directory: ${{ github.workspace }}

0 commit comments

Comments
 (0)