Fork coverage (Codecov) #198
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Uploads coverage/test results for PRs from forks to Codecov. | |
| # | |
| # PRs from forks do not have access to repository secrets, so the direct | |
| # Codecov steps in the main CI workflow are skipped for them. This workflow | |
| # runs on `workflow_run` (i.e. in the base-repo context, WITH secrets) after | |
| # the main CI completes, downloads ONLY the coverage data artifact that the CI | |
| # build produced, and uploads it to Codecov. It never checks out or executes | |
| # fork code, so there is no risk of leaking secrets to untrusted contributions. | |
| name: Fork coverage (Codecov) | |
| on: | |
| workflow_run: | |
| workflows: ["Java CI with Maven"] | |
| types: [completed] | |
| permissions: | |
| contents: read | |
| actions: read | |
| jobs: | |
| codecov: | |
| # Only for PRs that originate from a fork (same-repo PRs upload directly in | |
| # the main CI workflow, which has secrets). | |
| if: > | |
| github.event.workflow_run.event == 'pull_request' && | |
| github.event.workflow_run.head_repository.full_name != github.event.workflow_run.repository.full_name | |
| runs-on: ubuntu-latest | |
| env: | |
| CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} | |
| steps: | |
| - name: Download coverage payload from CI run | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| name: codecov-payload | |
| path: codecov-payload | |
| run-id: ${{ github.event.workflow_run.id }} | |
| github-token: ${{ github.token }} | |
| - name: Read PR metadata | |
| id: meta | |
| # The payload file is produced by the untrusted fork build, so extract | |
| # only the expected keys and validate their format before exposing them | |
| # as step outputs (prevents $GITHUB_OUTPUT injection). | |
| run: | | |
| env_file=codecov-payload/pr-event.env | |
| pr_number=$(grep -m1 '^pr_number=' "$env_file" | cut -d= -f2-) | |
| pr_head_sha=$(grep -m1 '^pr_head_sha=' "$env_file" | cut -d= -f2-) | |
| pr_head_ref=$(grep -m1 '^pr_head_ref=' "$env_file" | cut -d= -f2-) | |
| [[ "$pr_number" =~ ^[0-9]+$ ]] || { echo "invalid pr_number"; exit 1; } | |
| [[ "$pr_head_sha" =~ ^[0-9a-f]{40}$ ]] || { echo "invalid pr_head_sha"; exit 1; } | |
| [[ "$pr_head_ref" =~ ^[A-Za-z0-9._/-]+$ ]] || { echo "invalid pr_head_ref"; exit 1; } | |
| { | |
| echo "pr_number=$pr_number" | |
| echo "pr_head_sha=$pr_head_sha" | |
| echo "pr_head_ref=$pr_head_ref" | |
| } >> "$GITHUB_OUTPUT" | |
| - name: Publish fork PR test execution results to Codecov | |
| if: env.CODECOV_TOKEN != '' | |
| uses: codecov/test-results-action@0fa95f0e1eeaafde2c782583b36b28ad0d8c77d3 # v1.2.1 | |
| with: | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| files: codecov-payload/surefire/*.xml,codecov-payload/failsafe/*.xml | |
| override_commit: ${{ steps.meta.outputs.pr_head_sha }} | |
| override_pr: ${{ steps.meta.outputs.pr_number }} | |
| override_branch: ${{ steps.meta.outputs.pr_head_ref }} | |
| fail_ci_if_error: true | |
| verbose: false | |
| - name: Publish fork PR test coverage to Codecov | |
| if: env.CODECOV_TOKEN != '' && github.event.workflow_run.conclusion == 'success' | |
| uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 | |
| with: | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| files: codecov-payload/jacoco.xml,codecov-payload/jacoco-aggregate.xml | |
| flags: processor | |
| name: codecov-upload-fork | |
| override_commit: ${{ steps.meta.outputs.pr_head_sha }} | |
| override_pr: ${{ steps.meta.outputs.pr_number }} | |
| override_branch: ${{ steps.meta.outputs.pr_head_ref }} | |
| fail_ci_if_error: true | |
| verbose: false |