Skip to content

Commit a75bc8c

Browse files
authored
Merge pull request csala#13 from pythiac/fix-codecov-tokenless-upload
Fix codecov tokenless upload on external PRs
2 parents ca41b9b + d9a308d commit a75bc8c

File tree

3 files changed

+154
-9
lines changed

3 files changed

+154
-9
lines changed

.github/workflows/tests.yml renamed to .github/workflows/ci.yml

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,48 @@ jobs:
4848
run: |
4949
pytest --cov=mdformat_pyproject --cov-report=xml --cov-report=term-missing
5050
51-
- name: Upload to Codecov
51+
- name: Store PR number and commit SHA
5252
if: matrix.os == 'ubuntu-latest' && matrix.python-version == 3.11
53-
uses: codecov/codecov-action@v5
53+
run: |
54+
echo "Storing PR number ${{ github.event.number }}"
55+
echo "${{ github.event.number }}" > pr_number.txt
56+
57+
echo "Storing commit SHA ${{ github.event.pull_request.head.sha }}"
58+
echo "${{ github.event.pull_request.head.sha }}" > commit_sha.txt
59+
60+
# Workaround for codecov tokenless upload errors on external PRs
61+
# Copied and ajusted from the workarounds suggested in the link below:
62+
# https://github.com/codecov/feedback/issues/301#issuecomment-2009355183
63+
# Triggered sub-workflow is not able to detect the original commit/PR which is available
64+
# in this workflow.
65+
- name: Store PR number
66+
if: matrix.os == 'ubuntu-latest' && matrix.python-version == 3.11
67+
uses: actions/upload-artifact@v4
68+
with:
69+
name: pr_number
70+
path: pr_number.txt
71+
72+
- name: Store commit SHA
73+
if: matrix.os == 'ubuntu-latest' && matrix.python-version == 3.11
74+
uses: actions/upload-artifact@v4
75+
with:
76+
name: commit_sha
77+
path: commit_sha.txt
78+
79+
# This stores the coverage report in artifacts. The actual upload to Codecov
80+
# is executed by a different workflow `coverage-report.yml`. The reason for this
81+
# split is because `on.pull_request` workflows don't have access to secrets.
82+
- name: Store coverage report in artifacts
83+
if: matrix.os == 'ubuntu-latest' && matrix.python-version == 3.11
84+
uses: actions/upload-artifact@v4
5485
with:
55-
fail_ci_if_error: true
56-
files: ./coverage.xml
57-
flags: pytests
58-
name: pytests-py3.11
59-
token: ${{ secrets.CODECOV_TOKEN }}
86+
name: codecov_report
87+
path: ./coverage.xml
88+
89+
- run: |
90+
echo "The coverage report was stored in Github artifacts."
91+
echo "It will be uploaded to Codecov using [codecov.yml] workflow shortly."
92+
if: matrix.os == 'ubuntu-latest' && matrix.python-version == 3.11
6093
6194
pre-commit-hook:
6295
runs-on: ubuntu-latest

.github/workflows/codecov.yml

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
name: CodeCov Report Upload
2+
3+
on:
4+
# This workflow is triggered after every successfull execution
5+
# of `ci` workflow.
6+
workflow_run:
7+
workflows: ["CI"]
8+
types:
9+
- completed
10+
11+
jobs:
12+
coverage:
13+
name: CodeCov Report Upload
14+
runs-on: ubuntu-latest
15+
steps:
16+
17+
- name: 'Download existing coverage report'
18+
id: prepare_report
19+
uses: actions/github-script@v7
20+
with:
21+
script: |
22+
var fs = require('fs');
23+
24+
// List artifacts of the workflow run that triggered this workflow
25+
var artifacts = await github.rest.actions.listWorkflowRunArtifacts({
26+
owner: context.repo.owner,
27+
repo: context.repo.repo,
28+
run_id: context.payload.workflow_run.id,
29+
});
30+
31+
let codecovReport = artifacts.data.artifacts.filter((artifact) => {
32+
return artifact.name == "codecov_report";
33+
});
34+
35+
if (codecovReport.length != 1) {
36+
throw new Error("Unexpected number of {codecov_report} artifacts: " + codecovReport.length);
37+
}
38+
39+
var download = await github.rest.actions.downloadArtifact({
40+
owner: context.repo.owner,
41+
repo: context.repo.repo,
42+
artifact_id: codecovReport[0].id,
43+
archive_format: 'zip',
44+
});
45+
fs.writeFileSync('codecov_report.zip', Buffer.from(download.data));
46+
47+
let prNumber = artifacts.data.artifacts.filter((artifact) => {
48+
return artifact.name == "pr_number";
49+
});
50+
51+
if (prNumber.length != 1) {
52+
throw new Error("Unexpected number of {pr_number} artifacts: " + prNumber.length);
53+
}
54+
55+
var download = await github.rest.actions.downloadArtifact({
56+
owner: context.repo.owner,
57+
repo: context.repo.repo,
58+
artifact_id: prNumber[0].id,
59+
archive_format: 'zip',
60+
});
61+
fs.writeFileSync('pr_number.zip', Buffer.from(download.data));
62+
63+
let commitSha = artifacts.data.artifacts.filter((artifact) => {
64+
return artifact.name == "commit_sha";
65+
});
66+
67+
if (commitSha.length != 1) {
68+
throw new Error("Unexpected number of {commit_sha} artifacts: " + commitSha.length);
69+
}
70+
71+
var download = await github.rest.actions.downloadArtifact({
72+
owner: context.repo.owner,
73+
repo: context.repo.repo,
74+
artifact_id: commitSha[0].id,
75+
archive_format: 'zip',
76+
});
77+
fs.writeFileSync('commit_sha.zip', Buffer.from(download.data));
78+
79+
- id: parse_previous_artifacts
80+
run: |
81+
unzip codecov_report.zip
82+
unzip pr_number.zip
83+
unzip commit_sha.zip
84+
85+
echo "Detected PR is: $(<pr_number.txt)"
86+
echo "Detected commit_sha is: $(<commit_sha.txt)"
87+
88+
# Make the params available as step output
89+
echo "override_pr=$(<pr_number.txt)" >> "$GITHUB_OUTPUT"
90+
echo "override_commit=$(<commit_sha.txt)" >> "$GITHUB_OUTPUT"
91+
92+
- name: Checkout repository
93+
uses: actions/checkout@v4
94+
with:
95+
ref: ${{ steps.parse_previous_artifacts.outputs.override_commit || '' }}
96+
path: repo_root
97+
98+
- name: Upload coverage to Codecov
99+
uses: codecov/codecov-action@v5
100+
with:
101+
token: ${{ secrets.CODECOV_TOKEN }}
102+
files: ${{ github.workspace }}/coverage.xml
103+
fail_ci_if_error: true
104+
# Manual overrides for these parameters are needed because automatic detection
105+
# in codecov-action does not work for non-`pull_request` workflows.
106+
# In `main` branch push, these default to empty strings since we want to run
107+
# the analysis on HEAD.
108+
override_commit: ${{ steps.parse_previous_artifacts.outputs.override_commit || '' }}
109+
override_pr: ${{ steps.parse_previous_artifacts.outputs.override_pr || '' }}
110+
working-directory: ${{ github.workspace }}/repo_root
111+
# Location where coverage report files are searched for
112+
directory: ${{ github.workspace }}

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ Add the following to your `.pre-commit-config.yaml`:
4343
- mdformat-pyproject
4444
```
4545
46-
[ci-badge]: https://github.com/csala/mdformat-pyproject/actions/workflows/tests.yml/badge.svg
47-
[ci-link]: https://github.com/csala/mdformat-pyproject/actions/workflows/tests.yml
46+
[ci-badge]: https://github.com/csala/mdformat-pyproject/actions/workflows/ci.yml/badge.svg
47+
[ci-link]: https://github.com/csala/mdformat-pyproject/actions/workflows/ci.yml
4848
[cov-badge]: https://codecov.io/gh/csala/mdformat-pyproject/branch/master/graph/badge.svg
4949
[cov-link]: https://codecov.io/gh/csala/mdformat-pyproject
5050
[mdformat]: https://github.com/executablebooks/mdformat

0 commit comments

Comments
 (0)