feat: deployment plan dry runs comment back to associated version creation pull request#999
Conversation
…ation pull request
📝 WalkthroughWalkthroughThe changes add GitHub PR commenting functionality to the deployment plan result controller. When a deployment plan is processed, the controller now calls Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
Adds GitHub PR commenting for deployment plan (dry-run) results by locating the PR associated with the deployment version’s commit SHA and then creating/updating an issue comment with plan status and diffs.
Changes:
- Introduces a GitHub commenting helper that formats plan results (including unified diffs) and upserts a PR comment keyed by a marker.
- Hooks PR commenting into the deployment plan result controller for unsupported/errored/completed outcomes.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| apps/workspace-engine/svc/controllers/deploymentplanresult/github_comment.go | New GitHub PR comment upsert + diff formatting logic driven by version metadata (owner/repo/sha). |
| apps/workspace-engine/svc/controllers/deploymentplanresult/controller.go | Calls the PR commenting helper after persisting plan-result terminal states. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| comments, _, err := client.Issues.ListComments( | ||
| ctx, owner, repo, prNumber, &github.IssueListCommentsOptions{ | ||
| ListOptions: github.ListOptions{PerPage: 100}, | ||
| }, | ||
| ) | ||
| if err != nil { | ||
| return fmt.Errorf("list comments: %w", err) | ||
| } | ||
|
|
||
| for _, c := range comments { | ||
| body := c.GetBody() | ||
| if !strings.Contains(body, marker) { | ||
| continue | ||
| } | ||
|
|
||
| updated := appendSection(body, newSection) | ||
| _, _, err := client.Issues.EditComment( | ||
| ctx, owner, repo, c.GetID(), | ||
| &github.IssueComment{Body: &updated}, | ||
| ) | ||
| if err != nil { | ||
| return fmt.Errorf("edit comment: %w", err) | ||
| } | ||
| return nil | ||
| } | ||
|
|
||
| body := buildComment(marker, dispatchCtx, []string{newSection}) | ||
| _, _, err = client.Issues.CreateComment( |
There was a problem hiding this comment.
upsertComment only fetches the first page of PR comments (PerPage: 100) and never paginates, so it may fail to find/update an existing marker comment on PRs with lots of discussion. Consider paging through results until the marker is found or there are no more pages.
| comments, _, err := client.Issues.ListComments( | |
| ctx, owner, repo, prNumber, &github.IssueListCommentsOptions{ | |
| ListOptions: github.ListOptions{PerPage: 100}, | |
| }, | |
| ) | |
| if err != nil { | |
| return fmt.Errorf("list comments: %w", err) | |
| } | |
| for _, c := range comments { | |
| body := c.GetBody() | |
| if !strings.Contains(body, marker) { | |
| continue | |
| } | |
| updated := appendSection(body, newSection) | |
| _, _, err := client.Issues.EditComment( | |
| ctx, owner, repo, c.GetID(), | |
| &github.IssueComment{Body: &updated}, | |
| ) | |
| if err != nil { | |
| return fmt.Errorf("edit comment: %w", err) | |
| } | |
| return nil | |
| } | |
| body := buildComment(marker, dispatchCtx, []string{newSection}) | |
| _, _, err = client.Issues.CreateComment( | |
| opts := &github.IssueListCommentsOptions{ | |
| ListOptions: github.ListOptions{PerPage: 100}, | |
| } | |
| for { | |
| comments, resp, err := client.Issues.ListComments(ctx, owner, repo, prNumber, opts) | |
| if err != nil { | |
| return fmt.Errorf("list comments: %w", err) | |
| } | |
| for _, c := range comments { | |
| body := c.GetBody() | |
| if !strings.Contains(body, marker) { | |
| continue | |
| } | |
| updated := appendSection(body, newSection) | |
| _, _, err := client.Issues.EditComment( | |
| ctx, owner, repo, c.GetID(), | |
| &github.IssueComment{Body: &updated}, | |
| ) | |
| if err != nil { | |
| return fmt.Errorf("edit comment: %w", err) | |
| } | |
| return nil | |
| } | |
| if resp == nil || resp.NextPage == 0 { | |
| break | |
| } | |
| opts.Page = resp.NextPage | |
| } | |
| body := buildComment(marker, dispatchCtx, []string{newSection}) | |
| _, _, err := client.Issues.CreateComment( |
| updated := appendSection(body, newSection) | ||
| _, _, err := client.Issues.EditComment( | ||
| ctx, owner, repo, c.GetID(), | ||
| &github.IssueComment{Body: &updated}, | ||
| ) | ||
| if err != nil { | ||
| return fmt.Errorf("edit comment: %w", err) | ||
| } | ||
| return nil | ||
| } | ||
|
|
||
| body := buildComment(marker, dispatchCtx, []string{newSection}) | ||
| _, _, err = client.Issues.CreateComment( | ||
| ctx, owner, repo, prNumber, | ||
| &github.IssueComment{Body: &body}, | ||
| ) | ||
| if err != nil { | ||
| return fmt.Errorf("create comment: %w", err) | ||
| } | ||
| return nil | ||
| } | ||
|
|
||
| func appendSection(existingBody, newSection string) string { | ||
| return existingBody + "\n" + newSection | ||
| } |
There was a problem hiding this comment.
When an existing marker comment is found, the code appends newSection to the end of the comment body. This makes the operation non-idempotent (retries/re-runs keep growing the comment) and can also cause lost updates if multiple reconciles edit the same comment concurrently. Prefer rebuilding the full comment body deterministically (e.g., replace the previous section for this target) rather than blindly appending.
| diff, err := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{ | ||
| A: difflib.SplitLines(r.Current), | ||
| B: difflib.SplitLines(r.Proposed), | ||
| FromFile: "current", | ||
| ToFile: "proposed", | ||
| Context: 3, | ||
| }) | ||
| if err != nil { | ||
| diff = "Failed to compute diff" | ||
| } | ||
|
|
||
| sb.WriteString("<details>\n<summary>Changes detected</summary>\n\n") | ||
| sb.WriteString("```diff\n") | ||
| sb.WriteString(diff) | ||
| sb.WriteString("```\n") | ||
| sb.WriteString("</details>\n") |
There was a problem hiding this comment.
The generated unified diff is written into a PR comment without any size guard. GitHub comments have a hard size limit; large Current/Proposed payloads will cause CreateComment/EditComment to fail (422) and the worker will keep recording errors. Consider truncating the diff/inputs to a safe limit and/or posting a summary with a link to stored artifacts.
| // MaybeCommentOnPR posts or updates a PR comment with plan results for a | ||
| // resource. Returns nil if the version metadata lacks GitHub info, the bot | ||
| // is not configured, or no PR is found for the SHA. | ||
| func MaybeCommentOnPR( | ||
| ctx context.Context, | ||
| dispatchCtx *oapi.DispatchContext, | ||
| targetID string, | ||
| result prCommentResult, | ||
| ) error { | ||
| if dispatchCtx.Version == nil { | ||
| return nil | ||
| } | ||
| meta := dispatchCtx.Version.Metadata | ||
| owner := meta[metaGitHubOwner] | ||
| repo := meta[metaGitHubRepo] | ||
| sha := meta[metaGitSHA] | ||
| if owner == "" || repo == "" || sha == "" { | ||
| return nil | ||
| } |
There was a problem hiding this comment.
MaybeCommentOnPR depends on specific DeploymentVersion.Metadata keys (github/owner, github/repo, git/sha) but the function comment only mentions “GitHub info” generically. Please document the exact required keys (and expected formats) so callers/workflows know what must be set for PR commenting to work.
| prs, _, err := client.PullRequests.ListPullRequestsWithCommit( | ||
| ctx, owner, repo, sha, &github.ListOptions{PerPage: 1}, | ||
| ) | ||
| if err != nil { | ||
| return 0, fmt.Errorf("list PRs for commit %s: %w", sha, err) | ||
| } | ||
| for _, pr := range prs { | ||
| if pr.GetState() == "open" { | ||
| return pr.GetNumber(), nil | ||
| } | ||
| } | ||
| if len(prs) > 0 { | ||
| return prs[0].GetNumber(), nil | ||
| } | ||
| return 0, nil |
There was a problem hiding this comment.
findPRForSHA requests only 1 PR (PerPage: 1), which makes the subsequent loop that prefers an open PR ineffective and can easily select the wrong PR (or none) if the first returned PR isn’t the desired open one. Increase PerPage and/or paginate until an open PR is found (falling back only after exhausting results).
| prs, _, err := client.PullRequests.ListPullRequestsWithCommit( | |
| ctx, owner, repo, sha, &github.ListOptions{PerPage: 1}, | |
| ) | |
| if err != nil { | |
| return 0, fmt.Errorf("list PRs for commit %s: %w", sha, err) | |
| } | |
| for _, pr := range prs { | |
| if pr.GetState() == "open" { | |
| return pr.GetNumber(), nil | |
| } | |
| } | |
| if len(prs) > 0 { | |
| return prs[0].GetNumber(), nil | |
| } | |
| return 0, nil | |
| opts := &github.ListOptions{PerPage: 100, Page: 1} | |
| fallbackPRNumber := 0 | |
| for { | |
| prs, resp, err := client.PullRequests.ListPullRequestsWithCommit( | |
| ctx, owner, repo, sha, opts, | |
| ) | |
| if err != nil { | |
| return 0, fmt.Errorf("list PRs for commit %s: %w", sha, err) | |
| } | |
| for _, pr := range prs { | |
| if fallbackPRNumber == 0 { | |
| fallbackPRNumber = pr.GetNumber() | |
| } | |
| if pr.GetState() == "open" { | |
| return pr.GetNumber(), nil | |
| } | |
| } | |
| if resp == nil || resp.NextPage == 0 { | |
| break | |
| } | |
| opts.Page = resp.NextPage | |
| } | |
| return fallbackPRNumber, nil |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@apps/workspace-engine/svc/controllers/deploymentplanresult/github_comment.go`:
- Around line 184-186: The current call to
client.PullRequests.ListPullRequestsWithCommit uses github.ListOptions{PerPage:
1}, which can return a closed PR first and cause wrong selection; change the
logic in github_comment.go to fetch a larger page size (e.g., PerPage: 100) and
paginate through results from ListPullRequestsWithCommit, iterating all returned
PRs (the prs slice) to prefer a PR with State == "open" before falling back to
the first result; ensure you loop over pages (incrementing ListOptions.Page)
until you find an open PR or exhaust results, then use that chosen PR.
- Around line 89-93: formatResultSection currently writes the full unified diff
into the GitHub comment body which can exceed the API 65,536-character limit;
before writing the diff (sb.WriteString(diff)) truncate it to a safe threshold
(e.g., 50,000 characters) and append a clear marker such as "\n...[truncated]"
so the comment remains valid. Update the same truncation logic where you call
EditComment (the EditComment invocation referenced in the review) so both
CreateComment and EditComment use the same truncatedDiff variable; implement the
truncation as a small helper (e.g., truncateDiff(diff string, max int) string)
and replace direct uses of diff with truncateDiff(diff, 50000) in
formatResultSection and the EditComment call.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 5b27cde2-44d4-47d9-bc1d-2affdd378524
📒 Files selected for processing (2)
apps/workspace-engine/svc/controllers/deploymentplanresult/controller.goapps/workspace-engine/svc/controllers/deploymentplanresult/github_comment.go
| if commentErr := MaybeCommentOnPR( | ||
| ctx, | ||
| &dispatchCtx, | ||
| result.TargetID.String(), | ||
| prCommentResult{ | ||
| AgentID: dispatchCtx.JobAgent.Id, | ||
| AgentName: dispatchCtx.JobAgent.Name, | ||
| AgentType: agentType, | ||
| Status: "unsupported", | ||
| }, | ||
| ); commentErr != nil { | ||
| span.RecordError(commentErr) | ||
| } |
There was a problem hiding this comment.
Comment posting failures are non-recoverable right now.
If MaybeCommentOnPR fails (rate limit, transient GitHub outage), the job still completes and no retry path exists, so PR diff visibility can be permanently lost for that run.
Also applies to: 136-149, 201-212
| sb.WriteString("<details>\n<summary>Changes detected</summary>\n\n") | ||
| sb.WriteString("```diff\n") | ||
| sb.WriteString(diff) | ||
| sb.WriteString("```\n") | ||
| sb.WriteString("</details>\n") |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
What is the maximum GitHub issue comment body size for CreateComment/EditComment API calls, and what failure status/code is returned when exceeded?
💡 Result:
The maximum GitHub issue comment body size for CreateComment (POST /repos/{owner}/{repo}/issues/{issue_number}/comments) and EditComment (PATCH /repos/{owner}/{repo}/issues/comments/{comment_id}) REST API calls is 65536 characters. When exceeded, the API returns HTTP status 422 Unprocessable Entity with a JSON error body like: {"resource":"IssueComment","code":"unprocessable" or "custom","field":"data" or "body","message":"Body is too long (maximum is 65536 characters)"}. This limit is consistently reported across multiple sources from 2020 to 2026, including GitHub Community discussions and GitHub Actions issues encountering the exact error. Official REST API docs do not explicitly state the limit but document 422 for validation failures. Recent docs (apiVersion=2026-03-10) confirm 422 usage. No evidence of change post-2026-04-15.
Citations:
- 1: error: body is too long (maximum is 65536 characters) mshick/add-pr-comment#93
- 2: https://github.community/t/maximum-length-for-the-comment-body-in-issues-and-pr/148867
- 3: Body is too long (maximum is 65536 characters) telia-oss/github-pr-resource#259
- 4: https://docs.github.com/en/rest/issues/comments?apiVersion=2026-03-10
🏁 Script executed:
wc -l apps/workspace-engine/svc/controllers/deploymentplanresult/github_comment.goRepository: ctrlplanedev/ctrlplane
Length of output: 146
🏁 Script executed:
cat -n apps/workspace-engine/svc/controllers/deploymentplanresult/github_comment.go | sed -n '70,110p'Repository: ctrlplanedev/ctrlplane
Length of output: 1310
🏁 Script executed:
cat -n apps/workspace-engine/svc/controllers/deploymentplanresult/github_comment.go | sed -n '240,280p'Repository: ctrlplanedev/ctrlplane
Length of output: 995
🏁 Script executed:
cat -n apps/workspace-engine/svc/controllers/deploymentplanresult/github_comment.go | sed -n '98,135p'Repository: ctrlplanedev/ctrlplane
Length of output: 1494
🏁 Script executed:
cat -n apps/workspace-engine/svc/controllers/deploymentplanresult/github_comment.go | sed -n '1,50p'Repository: ctrlplanedev/ctrlplane
Length of output: 1537
🏁 Script executed:
rg -n "wrapAgentSection|replaceOrAppendAgentSection" apps/workspace-engine/svc/controllers/deploymentplanresult/github_comment.go -A 10Repository: ctrlplanedev/ctrlplane
Length of output: 1648
🏁 Script executed:
rg -n "diff.*size|maxDiff|truncat" apps/workspace-engine/svc/controllers/deploymentplanresult/ -iRepository: ctrlplanedev/ctrlplane
Length of output: 48
🏁 Script executed:
rg -n "TODO|FIXME" apps/workspace-engine/svc/controllers/deploymentplanresult/github_comment.goRepository: ctrlplanedev/ctrlplane
Length of output: 48
Truncate large diffs to prevent comment body size failures.
formatResultSection writes the full unified diff without size validation. GitHub's REST API enforces a 65,536 character limit on issue comments; diffs exceeding this cause CreateComment/EditComment to fail with HTTP 422, which silently drops PR visibility for the deployment result.
Truncate the diff to a safe threshold (e.g., 50,000 characters) before writing it:
Suggested fix
+const maxDiffChars = 50000
+
func formatResultSection(r prCommentResult) string {
var sb strings.Builder
fmt.Fprintf(&sb, "**%s** · `%s`\n", r.AgentName, r.AgentType)
@@
if err != nil {
diff = "Failed to compute diff"
}
+ if len(diff) > maxDiffChars {
+ diff = diff[:maxDiffChars] + "\n...diff truncated..."
+ }
sb.WriteString("<details>\n<summary>Changes detected</summary>\n\n")Also applies to the EditComment call at lines 247-250.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| sb.WriteString("<details>\n<summary>Changes detected</summary>\n\n") | |
| sb.WriteString("```diff\n") | |
| sb.WriteString(diff) | |
| sb.WriteString("```\n") | |
| sb.WriteString("</details>\n") | |
| const maxDiffChars = 50000 | |
| func formatResultSection(r prCommentResult) string { | |
| var sb strings.Builder | |
| fmt.Fprintf(&sb, "**%s** · `%s`\n", r.AgentName, r.AgentType) | |
| if err != nil { | |
| diff = "Failed to compute diff" | |
| } | |
| if len(diff) > maxDiffChars { | |
| diff = diff[:maxDiffChars] + "\n...diff truncated..." | |
| } | |
| sb.WriteString("<details>\n<summary>Changes detected</summary>\n\n") | |
| sb.WriteString(" |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/workspace-engine/svc/controllers/deploymentplanresult/github_comment.go`
around lines 89 - 93, formatResultSection currently writes the full unified diff
into the GitHub comment body which can exceed the API 65,536-character limit;
before writing the diff (sb.WriteString(diff)) truncate it to a safe threshold
(e.g., 50,000 characters) and append a clear marker such as "\n...[truncated]"
so the comment remains valid. Update the same truncation logic where you call
EditComment (the EditComment invocation referenced in the review) so both
CreateComment and EditComment use the same truncatedDiff variable; implement the
truncation as a small helper (e.g., truncateDiff(diff string, max int) string)
and replace direct uses of diff with truncateDiff(diff, 50000) in
formatResultSection and the EditComment call.
| prs, _, err := client.PullRequests.ListPullRequestsWithCommit( | ||
| ctx, owner, repo, sha, &github.ListOptions{PerPage: 1}, | ||
| ) |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
For the GitHub REST endpoint "List pull requests associated with a commit" (and go-github v66 PullRequests.ListPullRequestsWithCommit), what ordering guarantees exist? Can per_page=1 miss an open PR when multiple PRs reference the same commit SHA?
💡 Result:
No explicit ordering guarantees are documented for the GitHub REST API endpoint GET /repos/{owner}/{repo}/commits/{commit_sha}/pulls or the go-github v66 PullRequests.ListPullRequestsWithCommit method. The official documentation does not specify sort order, direction, or stability of results. It supports standard pagination with per_page (default 30, max 100) and page parameters. The endpoint returns merged PRs that introduced the commit if present in the default branch, or both merged and open PRs otherwise. Multiple PRs can reference the same commit SHA (e.g., cherry-picked commits), so lists can exceed length 1. With per_page=1, only the first page (1 result) is returned. Since ordering is unspecified, yes, it can miss an open PR if >1 PRs exist and the open PR is not first in the undocumented order. To detect all PRs including open ones reliably, fetch all pages (check Link headers or iterate until empty response).
Citations:
- 1: https://github.com/google/go-github/blob/master/github/pulls.go
- 2: https://docs.github.com/en/rest/commits/commits
- 3: https://docs.github.com/v3/repos/commits
- 4: https://docs.github.com/rest/commits/commits
🏁 Script executed:
cd apps/workspace-engine && find . -name "github_comment.go" -type fRepository: ctrlplanedev/ctrlplane
Length of output: 122
🏁 Script executed:
head -220 apps/workspace-engine/svc/controllers/deploymentplanresult/github_comment.go | tail -50Repository: ctrlplanedev/ctrlplane
Length of output: 1200
PR lookup can select the wrong PR because only one result is fetched.
Using PerPage: 1 risks missing an open PR associated with the commit and then selecting a closed PR fallback. GitHub's REST API does not document ordering guarantees for the list pull requests endpoint, so an open PR may not be the first result returned. Fetch a larger page size and iterate through all results to find an open PR before falling back to the first result.
Suggested fix
func findPRForSHA(
ctx context.Context,
client *github.Client,
owner, repo, sha string,
) (int, error) {
- prs, _, err := client.PullRequests.ListPullRequestsWithCommit(
- ctx, owner, repo, sha, &github.ListOptions{PerPage: 1},
- )
- if err != nil {
- return 0, fmt.Errorf("list PRs for commit %s: %w", sha, err)
- }
- for _, pr := range prs {
- if pr.GetState() == "open" {
- return pr.GetNumber(), nil
- }
- }
- if len(prs) > 0 {
- return prs[0].GetNumber(), nil
- }
- return 0, nil
+ opts := &github.ListOptions{PerPage: 100}
+ firstPR := 0
+ for {
+ prs, resp, err := client.PullRequests.ListPullRequestsWithCommit(
+ ctx, owner, repo, sha, opts,
+ )
+ if err != nil {
+ return 0, fmt.Errorf("list PRs for commit %s: %w", sha, err)
+ }
+ for _, pr := range prs {
+ if firstPR == 0 {
+ firstPR = pr.GetNumber()
+ }
+ if pr.GetState() == "open" {
+ return pr.GetNumber(), nil
+ }
+ }
+ if resp.NextPage == 0 {
+ break
+ }
+ opts.Page = resp.NextPage
+ }
+ return firstPR, nil
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| prs, _, err := client.PullRequests.ListPullRequestsWithCommit( | |
| ctx, owner, repo, sha, &github.ListOptions{PerPage: 1}, | |
| ) | |
| func findPRForSHA( | |
| ctx context.Context, | |
| client *github.Client, | |
| owner, repo, sha string, | |
| ) (int, error) { | |
| opts := &github.ListOptions{PerPage: 100} | |
| firstPR := 0 | |
| for { | |
| prs, resp, err := client.PullRequests.ListPullRequestsWithCommit( | |
| ctx, owner, repo, sha, opts, | |
| ) | |
| if err != nil { | |
| return 0, fmt.Errorf("list PRs for commit %s: %w", sha, err) | |
| } | |
| for _, pr := range prs { | |
| if firstPR == 0 { | |
| firstPR = pr.GetNumber() | |
| } | |
| if pr.GetState() == "open" { | |
| return pr.GetNumber(), nil | |
| } | |
| } | |
| if resp.NextPage == 0 { | |
| break | |
| } | |
| opts.Page = resp.NextPage | |
| } | |
| return firstPR, nil | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/workspace-engine/svc/controllers/deploymentplanresult/github_comment.go`
around lines 184 - 186, The current call to
client.PullRequests.ListPullRequestsWithCommit uses github.ListOptions{PerPage:
1}, which can return a closed PR first and cause wrong selection; change the
logic in github_comment.go to fetch a larger page size (e.g., PerPage: 100) and
paginate through results from ListPullRequestsWithCommit, iterating all returned
PRs (the prs slice) to prefer a PR with State == "open" before falling back to
the first result; ensure you loop over pages (incrementing ListOptions.Page)
until you find an open PR or exhaust results, then use that chosen PR.
fixes #979
Summary by CodeRabbit