Repository navigation
CI: run SonarCloud/Codecov for fork PRs via manual maintainer approval #198
Description
Problem
Pull requests from forked repositories cannot run the secret-gated quality checks (SonarCloud analysis, Codecov upload). For a pull_request event from a fork, GitHub withholds all repository secrets, so SONAR_TOKEN / CODECOV_TOKEN resolve to empty and the corresponding steps are (correctly) skipped. The result is that external contributions get no coverage reporting and no static analysis, which is a gap for a project that advertises these gates.
Simply exposing secrets to fork PRs is unsafe (the classic pull_request_target "pwn request": untrusted code would run with secrets in scope). We need a path that lets a maintainer manually approve an external PR, after which the analysis runs in the base-repo context on behalf of the approver — never automatically for the fork author.
Why it matters (high-security / high-reliability)
- External contributions must still be measured against the same coverage and static-analysis gates before merge.
- Secrets must never be handed to untrusted fork code without an explicit human approval step.
- Approval must be re-required on every new push so a contributor cannot "approve-then-push" malicious changes.
Affected files / paths
.github/workflows/maven.yml(produce a coverage payload artifact on fork PRs).github/workflows/fork-coverage.yml(new —workflow_runCodecov upload).github/workflows/fork-sonar.yml(new — env-gatedpull_request_targetSonarCloud analysis)docs/CONTRIBUTING.md(document thefork-cienvironment + approval flow)
Proposed remediation
Two complementary, safe patterns:
-
Codecov via
workflow_run(no untrusted execution). The normalpull_requestbuild (no secrets) uploads the JaCoCo XML + test-result XML + PR metadata as an artifact. A follow-up workflow triggered onworkflow_runruns in the base-repo context (secrets available), downloads only those data artifacts, and uploads to Codecov withoverride_commit/override_pr/override_branch. It never executes fork code, so there is no secret-exfiltration risk. Gated to fork PRs only (same-repo PRs keep uploading directly). -
SonarCloud via env-gated
pull_request_target(manual approval). A workflow triggered onpull_request_targetthat references a GitHub Environment (fork-ci) configured with Required reviewers. GitHub pauses the run until a maintainer approves; only then does it check out the PR head SHA, build, and runsonar:sonarwithSONAR_TOKENand thesonar.pullrequest.*parameters so the PR is decorated. Becausepull_request_targetre-runs on everysynchronize, approval is required per push. Gated to fork PRs only (same-repo PRs are analyzed by the normal CI workflow).
Maintainer setup: create an environment named fork-ci with required reviewers under Settings → Environments.
Maintainer TODOs (required before the fork checks work)
- Create the
fork-ciEnvironment (Settings → Environments → New environment →fork-ci) and add yourself (a maintainer) under Required reviewers.fork-sonar.ymlreferences this environment as its approval gate; without it the Sonar job would run untrusted fork code with secrets automatically, which is unsafe. - Confirm the SonarCloud decoration mechanism in the SonarCloud project settings: verify PR decoration uses a token configured in the project settings (not the GitHub App). This is the assumption behind dropping
pull-requests: write(Drop unnecessary pull-requests: write scope from the Maven CI job #187) and behind the fork-Sonar design. - Ensure the
SONAR_TOKENandCODECOV_TOKENrepository secrets exist (they are already used by the main CI); no new secrets are introduced by this PR.
Activity