Skip to content

Commit 200a08e

Browse files
jiridanekclaude
andauthored
ci: add GitHub Code Quality coverage (Python + Go) alongside Codecov (#4308)
Add actions/upload-code-coverage steps next to the existing Codecov uploads in code-quality.yaml so coverage also lands in GitHub's native Code Quality view on PRs. Python reuses the pytest-cov coverage.xml; Go converts coverage-go.out to Cobertura via gocover-cobertura (GitHub's documented recipe). Both are non-blocking (fail-on-error: false) and the action self-skips fork PRs and merge_group runs. Adds code-quality:write to the pytest-tests and go-tests jobs. * ci: harden GitHub Code Quality coverage steps (review feedback) - Guard both upload-code-coverage steps against a script injection in the action's push path (it interpolates github.ref_name/github.ref into a shell run:); skip the upload when the branch name contains $ ` " \ . - Make the Go Cobertura conversion non-blocking (continue-on-error) and gate the Go upload on its success, so optional coverage tooling can't fail the go-tests job. - Check out the PR head (head.sha) in both coverage jobs so reports map to the commit the action attributes them to (matches the action's README example). * ci: drop ref_name metachar guard; track upstream injection instead The guard was security theater: the injection in actions/upload-code-coverage is only reachable via push/workflow_dispatch to trusted branches, which already require write access (= arbitrary CI execution). Replace the denylist with a note linking the upstream report (actions/upload-code-coverage#26); the real fix (inject via env:) belongs there. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * ci(code-quality): set persist-credentials:false on the go-tests checkout Matches every other checkout in this workflow; the go-tests job now has code-quality:write, so don't leave the token in .git/config for PR code to reuse. The job only fetches public Go modules, so it needs no persisted creds. --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 5b6777f commit 200a08e

1 file changed

Lines changed: 56 additions & 0 deletions

File tree

.github/workflows/code-quality.yaml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,18 @@ jobs:
7878
permissions:
7979
contents: read
8080
packages: read
81+
code-quality: write # upload coverage to GitHub Code Quality
8182
runs-on: ubuntu-26.04
8283
steps:
8384
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
8485
with:
8586
persist-credentials: false # https://github.com/actions/checkout/issues/2312
8687
# Full history so tests/test_pylock_downgrade.py can `git show origin/main:…/pylock.toml`.
8788
fetch-depth: 0
89+
# Check out the PR head (not the merge commit) so coverage maps to head.sha, which is
90+
# what upload-code-coverage attributes the report to (matches the action's README
91+
# example). On push, head.sha is empty -> falls back to github.sha (unchanged).
92+
ref: ${{ github.event.pull_request.head.sha || github.sha }}
8893

8994
- name: Login to GitHub Container Registry
9095
if: ${{ github.repository != 'opendatahub-io/notebooks' }}
@@ -142,6 +147,28 @@ jobs:
142147
flags: python
143148
fail_ci_if_error: false
144149

150+
# --- GitHub Code Quality: native code coverage on PRs (complements Codecov) ---
151+
# One-time repo setup: Settings > Security > Code quality > Enable code quality.
152+
# Needs (1) a Cobertura XML report -- coverage.xml, produced above by pytest-cov
153+
# via PYTEST_ADDOPTS -- and (2) code-quality:write, granted on this job's perms.
154+
# Fork PRs and merge_group runs are skipped by the action itself (read-only token).
155+
# Feature docs: https://docs.github.com/en/code-security/code-quality
156+
# Setup guide: https://docs.github.com/en/code-security/how-tos/maintain-quality-code/set-up-code-coverage
157+
# Enable feature: https://docs.github.com/en/code-security/how-tos/maintain-quality-code/enable-code-quality
158+
# Upload action: https://github.com/actions/upload-code-coverage
159+
# NOTE: on push/workflow_dispatch this action interpolates github.ref_name/github.ref into a
160+
# shell run: (upstream script injection: https://github.com/actions/upload-code-coverage/issues/26).
161+
# Only reachable with write access (which already grants CI code execution), so no marginal
162+
# risk here; the fix belongs upstream (pass those values via env:).
163+
- name: Upload Python coverage to GitHub Code Quality
164+
if: ${{ !cancelled() && steps.install-deps.conclusion == 'success' }}
165+
uses: actions/upload-code-coverage@1c15be36fc3733ba839b1dd643bd9556e4426dc1 # v1.4.1
166+
with:
167+
file: coverage.xml
168+
language: Python
169+
label: code-coverage/python
170+
fail-on-error: false # non-blocking, matching the Codecov steps
171+
145172
- name: Upload test results to Codecov
146173
if: ${{ !cancelled() && steps.install-deps.conclusion == 'success' }}
147174
uses: codecov/test-results-action@0fa95f0e1eeaafde2c782583b36b28ad0d8c77d3 # v1.2.1
@@ -153,8 +180,13 @@ jobs:
153180
runs-on: ubuntu-26.04
154181
permissions:
155182
contents: read
183+
code-quality: write # upload coverage to GitHub Code Quality
156184
steps:
157185
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
186+
with:
187+
persist-credentials: false # don't leave the (code-quality:write) token in .git/config for PR code
188+
# PR head (not the merge commit) so Go coverage maps to head.sha (see pytest-tests note).
189+
ref: ${{ github.event.pull_request.head.sha || github.sha }}
158190

159191
- name: Set up Go
160192
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
@@ -174,6 +206,20 @@ jobs:
174206
run: gotestsum --junitfile=junit-go.xml -- -coverprofile=coverage-go.out -covermode=atomic ./...
175207
working-directory: scripts/buildinputs
176208

209+
- name: Convert Go coverage to Cobertura XML
210+
id: go-cobertura
211+
if: ${{ !cancelled() }}
212+
continue-on-error: true # optional coverage tooling must not fail the go-tests job
213+
# upload-code-coverage only accepts Cobertura; Codecov reads the native .out directly.
214+
# GitHub's documented Go recipe (see the "set-up-code-coverage" guide, language table):
215+
# go test -coverprofile=cover.out && gocover-cobertura < cover.out > coverage.xml
216+
# https://docs.github.com/en/code-security/how-tos/maintain-quality-code/set-up-code-coverage
217+
# https://github.com/boumenot/gocover-cobertura
218+
run: |
219+
go install github.com/boumenot/gocover-cobertura@v1.5.0
220+
"$(go env GOPATH)/bin/gocover-cobertura" < coverage-go.out > coverage-go.xml
221+
working-directory: scripts/buildinputs
222+
177223
- name: Upload Go coverage to Codecov
178224
if: ${{ !cancelled() }}
179225
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
@@ -184,6 +230,16 @@ jobs:
184230
flags: go
185231
fail_ci_if_error: false
186232

233+
# See the upstream-injection note on the Python upload above (github.com/actions/upload-code-coverage/issues/26).
234+
- name: Upload Go coverage to GitHub Code Quality
235+
if: ${{ !cancelled() && steps.go-cobertura.outcome == 'success' }}
236+
uses: actions/upload-code-coverage@1c15be36fc3733ba839b1dd643bd9556e4426dc1 # v1.4.1
237+
with:
238+
file: scripts/buildinputs/coverage-go.xml
239+
language: Go
240+
label: code-coverage/go
241+
fail-on-error: false # non-blocking, matching the Codecov steps
242+
187243
- name: Upload Go test results to Codecov
188244
if: ${{ !cancelled() }}
189245
uses: codecov/test-results-action@0fa95f0e1eeaafde2c782583b36b28ad0d8c77d3 # v1.2.1

0 commit comments

Comments
 (0)