Repository navigation
Fork pull requests never run e2e — build image push is denied, and the skipped required check still lets the PR merge #3257
Description
Activity
- addedkind/bugCategorizes issue or PR as related to a bugCategorizes issue or PR as related to a bugpriority/important-soonMust be staffed and worked on either currently, or very soon, ideally in time for the next releaseMust be staffed and worked on either currently, or very soon, ideally in time for the next releasearea/ciIssues or PRs related to CI workflows, GitHub Actions, automationIssues or PRs related to CI workflows, GitHub Actions, automation
on Jul 9, 2026 - added 7 commits that reference this issue
on Jul 9, 2026 Implementing this as Option A (privileged
workflow_runsplit) in #3262.It restores e2e for fork PRs while never exposing the registry push credentials to untrusted fork code: the unprivileged
pull_requestbuild exports images as OCI archives, and a privilegedworkflow_runfrom the default branch pushes them by digest, runs e2e, and reports the requiredE2E Testscheck on the head SHA.Option B (
pull_request_target+ok-to-test) was rejected — it runs untrusted code with secrets in scope; Option C (build-without-push) restores neither e2e nor the merge gate. The skipped-required-check bypass is closed by makingE2E Testsan explicitly-concluded check-run instead of a skippable job (a skipped required job counts as passing).- added a commit that references this issue
on Jul 15, 2026 Recording the direction here, since this issue asked to settle it before implementing.
Decision: Option A — a privileged
workflow_runsplit. The fork's unprivilegedpull_requestrun builds every image to an OCI archive (no push); a privilegedworkflow_run(running from the default branch) then pushes those archives to the existing CI registry by digest and runs the e2e suite in an ephemeral, credential-less sandbox. Fork build and test code never receive registry credentials — a stronger posture thanpull_request_target, which would hand fork code the secrets directly.Alternatives considered and why not:
pull_request_target— exposes repo secrets to the fork's checked-out code. Rejected on security posture.- Skip e2e for forks / maintainer-run only — leaves the merge-gate hole this issue is about (a skipped required check counts as satisfied by branch protection) and shifts the burden onto maintainers every time.
Implemented in #3262. Flagging so the direction is on the record; happy to revisit if there's a preference before it leaves draft.
21 remaining items
- added 11 commits that reference this issue
on Jul 29, 2026 - added a commit that references this issue
on Aug 8, 2026 - added a commit that references this issue
on Sep 30, 2026 - added a commit that references this issue
on Oct 7, 2026
Fork pull requests never run e2e — build image push is denied, and the skipped required check still lets the PR merge
Summary
Pull requests opened from a fork cannot run the e2e pipeline, and — more importantly — an approved fork PR can still merge with e2e having never executed. External contributions therefore land without any e2e coverage.
Mechanism
.github/workflows/pull-requests.yamlguards every registry login withif: ${{ !github.event.pull_request.head.repo.fork }}, so on a fork PR theLogin to ... registrystep is skipped (correct —pull_requestruns from a fork receive no secrets). But the build itself pushes unconditionally:hack/common-envs.mksetsPUSH := 1andBUILDX_ARGS := ... --push=$(PUSH), somake imagestill runsdocker buildx build --push. With no login it pushes anonymously and dies in ~20s:That fails every
Build <pkg>andBuild Talosjob.finalizerequiresbuildto have succeeded or been skipped (not failed), so it is skipped;e2erequiresfinalizeto have succeeded, so it is skipped too. The wholebuild → finalize → e2echain collapses on any fork PR.Impact
Two distinct problems:
Build <pkg>❌. These are not required checks, so they do not block merge, but they read as "this PR is broken" to contributors and reviewers.E2E Testsis a required check, and on a fork PR it ends inskipping. Branch protection treats a skipped required check as satisfied, so an approved fork PR reachesMERGEABLEand can be merged with e2e never having run. For a project where e2e is the merge gate, external contributions bypass it entirely.Recently observed on a batch of fork PRs; the mechanism is documented with a job link in a comment on #2196.
Options
I am filing this to track the gap and settle direction before implementing — not proposing a specific fix yet.
workflow_runsplit. The unprivilegedpull_requestrun builds images without pushing (e.g.--output type=oci) and uploads them as artifacts; a privilegedworkflow_runworkflow from the default branch (which has secrets) pushes those pre-built images and runsfinalize+ e2e, reporting status back to the PR head SHA. Restores e2e for forks without handing registry credentials to the untrusted build. Most work.ok-to-testlabel +pull_request_target. A maintainer applies a label that triggers a privileged run over the fork's code with secrets (the Prow pattern). Less work, but it runs untrusted code with registry credentials, which is a weaker security posture and needs careful per-commit SHA pinning.Notes
maintoday arepre-commitandE2E Tests; theBuild <pkg>jobs are not required.Suggested labels:
kind/bug,area/ci,priority/important-soon.