From 7a1cbe0b215c40b1fe9aaaf6121438f3fb645c1b Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Fri, 15 Nov 2024 08:22:22 +0000 Subject: [PATCH] ci: [#1075] fix coverage report --- .github/workflows/generate_coverage.yaml | 87 +++++++++++++++++ .github/workflows/upload_coverage.yaml | 119 +++++++++++++++++++++++ .gitignore | 5 +- 3 files changed, 209 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/generate_coverage.yaml create mode 100644 .github/workflows/upload_coverage.yaml diff --git a/.github/workflows/generate_coverage.yaml b/.github/workflows/generate_coverage.yaml new file mode 100644 index 000000000..eb2471b69 --- /dev/null +++ b/.github/workflows/generate_coverage.yaml @@ -0,0 +1,87 @@ +name: Generate Coverage Report + +on: + push: + branches: + - develop + pull_request: + branches: + - develop + +env: + CARGO_TERM_COLOR: always + +jobs: + coverage: + name: Generate Coverage Report + environment: coverage + runs-on: ubuntu-latest + env: + CARGO_INCREMENTAL: "0" + RUSTFLAGS: "-Cinstrument-coverage" + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install LLVM tools + run: sudo apt-get update && sudo apt-get install -y llvm + + - id: setup + name: Setup Toolchain + uses: dtolnay/rust-toolchain@nightly + with: + toolchain: nightly + components: llvm-tools-preview + + - id: cache + name: Enable Workflow Cache + uses: Swatinem/rust-cache@v2 + + - id: tools + name: Install Tools + uses: taiki-e/install-action@v2 + with: + tool: grcov,cargo-llvm-cov + + - id: coverage + name: Generate Coverage Report + run: | + cargo clean + cargo llvm-cov --lcov --output-path=./lcov.info + + - name: Store PR number and commit SHA + run: | + echo "Storing PR number ${{ github.event.number }}" + echo "${{ github.event.number }}" > pr_number.txt + + echo "Storing commit SHA ${{ github.event.pull_request.head.sha }}" + echo "${{ github.event.pull_request.head.sha }}" > commit_sha.txt + + # Workaround for https://github.com/orgs/community/discussions/25220 + # Triggered sub-workflow is not able to detect the original commit/PR which is available + # in this workflow. + - name: Store PR number + uses: actions/upload-artifact@v4 + with: + name: pr_number + path: pr_number.txt + + - name: Store commit SHA + uses: actions/upload-artifact@v4 + with: + name: commit_sha + path: commit_sha.txt + + # This stores the coverage report in artifacts. The actual upload to Codecov + # is executed by a different workflow `upload_coverage.yml`. The reason for this + # split is because `on.pull_request` workflows don't have access to secrets. + - name: Store coverage report in artifacts + uses: actions/upload-artifact@v4 + with: + name: codecov_report + path: ./lcov.info + + - run: | + echo "The coverage report was stored in Github artifacts." + echo "It will be uploaded to Codecov using [upload_coverage.yml] workflow shortly." diff --git a/.github/workflows/upload_coverage.yaml b/.github/workflows/upload_coverage.yaml new file mode 100644 index 000000000..4644ed6f1 --- /dev/null +++ b/.github/workflows/upload_coverage.yaml @@ -0,0 +1,119 @@ +name: Upload Coverage Report + +on: + # This workflow is triggered after every successfull execution + # of `Generate Coverage Report` workflow. + workflow_run: + workflows: ["Generate Coverage Report"] + types: + - completed + +permissions: + actions: write + contents: write + issues: write + pull-requests: write + +jobs: + coverage: + name: Upload Coverage Report + environment: coverage + runs-on: ubuntu-latest + steps: + - name: "Download existing coverage report" + id: prepare_report + uses: actions/github-script@v7 + with: + script: | + var fs = require('fs'); + + // List artifacts of the workflow run that triggered this workflow + var artifacts = await github.rest.actions.listWorkflowRunArtifacts({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: context.payload.workflow_run.id, + }); + + let codecovReport = artifacts.data.artifacts.filter((artifact) => { + return artifact.name == "codecov_report"; + }); + + if (codecovReport.length != 1) { + throw new Error("Unexpected number of {codecov_report} artifacts: " + codecovReport.length); + } + + var download = await github.rest.actions.downloadArtifact({ + owner: context.repo.owner, + repo: context.repo.repo, + artifact_id: codecovReport[0].id, + archive_format: 'zip', + }); + fs.writeFileSync('codecov_report.zip', Buffer.from(download.data)); + + let prNumber = artifacts.data.artifacts.filter((artifact) => { + return artifact.name == "pr_number"; + }); + + if (prNumber.length != 1) { + throw new Error("Unexpected number of {pr_number} artifacts: " + prNumber.length); + } + + var download = await github.rest.actions.downloadArtifact({ + owner: context.repo.owner, + repo: context.repo.repo, + artifact_id: prNumber[0].id, + archive_format: 'zip', + }); + fs.writeFileSync('pr_number.zip', Buffer.from(download.data)); + + let commitSha = artifacts.data.artifacts.filter((artifact) => { + return artifact.name == "commit_sha"; + }); + + if (commitSha.length != 1) { + throw new Error("Unexpected number of {commit_sha} artifacts: " + commitSha.length); + } + + var download = await github.rest.actions.downloadArtifact({ + owner: context.repo.owner, + repo: context.repo.repo, + artifact_id: commitSha[0].id, + archive_format: 'zip', + }); + fs.writeFileSync('commit_sha.zip', Buffer.from(download.data)); + + - id: parse_previous_artifacts + run: | + unzip codecov_report.zip + unzip pr_number.zip + unzip commit_sha.zip + + echo "Detected PR is: $(> "$GITHUB_OUTPUT" + echo "override_commit=$(> "$GITHUB_OUTPUT" + + - name: Checkout repository + uses: actions/checkout@v4 + with: + ref: ${{ steps.parse_previous_artifacts.outputs.override_commit || '' }} + path: repo_root + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v5 + with: + verbose: true + token: ${{ secrets.CODECOV_TOKEN }} + files: ${{ github.workspace }}/lcov.info + fail_ci_if_error: true + # Manual overrides for these parameters are needed because automatic detection + # in codecov-action does not work for non-`pull_request` workflows. + # In `main` branch push, these default to empty strings since we want to run + # the analysis on HEAD. + override_commit: ${{ steps.parse_previous_artifacts.outputs.override_commit || '' }} + override_pr: ${{ steps.parse_previous_artifacts.outputs.override_pr || '' }} + working-directory: ${{ github.workspace }}/repo_root + # Location where coverage report files are searched for + directory: ${{ github.workspace }} diff --git a/.gitignore b/.gitignore index b60b28991..b492857b1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .env +*.code-workspace **/*.rs.bk /.coverage/ /.idea/ @@ -12,5 +13,5 @@ /tracker.* /tracker.toml callgrind.out -perf.data* -*.code-workspace \ No newline at end of file +lcov.info +perf.data* \ No newline at end of file