feat(foreman): open the pull request on review GO#956
Conversation
The pipeline ended one hop short of its artifact: a coder-GO, gate-PASS, review-GO branch sat on the remote, reviewed and unopened, until a human found it. New githubpr package (mirrors githubissue): EnsurePR is idempotent — an existing PR for the head branch (any state) is reused, and losing a create race to a concurrent reviewer resolves 422 to the winner's PR. Title comes from the branch head's commit subject (fallback 'Fix #<n>'), base from payload.baseBranch, body links the issue. Workload.spec.openPullRequest (*bool) gates it: nil defaults to TRUE in issue-batch mode — a Workload built from Issues exists to produce a PR — and *false opts out. Stamped onto review-step payloads; explicit pipelines set payload.openPullRequest per step. The reviewer executor opens the PR after its enforcement passes settle a GO, best-effort (approval stands if GitHub is down; error surfaces in result extra as pullRequestError, success as pullRequestURL), using the same token the coder pushed with. Fixes defilantech#937 Signed-off-by: Jory Irving <jory.irving@stackadapt.com>
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
ReviewRequest changes — architecturally sound and safe (degrades to a logged error, never loses a branch), but as written it does not open a PR in our fork workflow, which is the mode the fleet actually runs. Fork-head bug (blocking): Test gaps: Nice-to-haves: up to 3 sequential GitHub calls (~30s worst case) run synchronously in the verdict path; |
What
A reviewer GO now opens the Workload's pull request — idempotently — instead of leaving a reviewed branch unopened on the remote. New
githubprpackage (mirrorsgithubissue);Workload.spec.openPullRequestgates it (nil = true in issue-batch mode,falseopts out; explicit pipelines setpayload.openPullRequestper step).Why
Fixes #937
The pipeline ended one hop short of its artifact: coder GO → gate PASS → review GO → …a branch sitting on the remote until a human noticed. We have hand-opened 12 PRs for completed Workloads in production since filing #937.
How
githubpr.EnsurePR: list-by-head first (any state → reuse), then create; a 422 create race (two reviewer tasks GOing concurrently) resolves to the winner's PR. Title = branch head's commit subject (fallbackFix #<n>), base =payload.baseBranch(default main), body =Fixes #<n>+ workload provenance.maybeOpenPullRequestruns best-effort with the same token the coder pushed with — the approval stands if GitHub is down;pullRequestURL/pullRequestErrorsurface in result extra.synthesizeIssueBatchstampspayload.openPullRequeston review steps from the spec field (three-valued*bool, default true — an issue-batch Workload exists to produce a PR). CRDs + chart CRDs regenerated.PREnsureris injected (likeIssueFetcher); nil disables the feature entirely.Follow-up candidates kept out of scope: draft PR on NO-GO carrying review findings (noted in #937), GHES base-URL config.
AI assistance: authored by Claude (Opus 4.8) operating under my direction; I reviewed the change and test output before submitting.
Checklist
make testpasses locally (agent + controller suites green)make lintpasses locally (golangci-lint run0 issues)git commit -s) per DCO