fix(#2432): retry merge on 409 after updating PR branch - #2434
Conversation
PR Summary by QodoRetry PR merge after updating branch on 409 “out of date” conflicts Description
Diagram
High-Level Assessment
Files changed (2)
|
Site previewPreview: https://67ea9b9e-site.fullsend-ai.workers.dev Commit: |
Code Review by Qodo
1.
|
|
🤖 Finished Review · ✅ Success · Started 4:34 PM UTC · Completed 4:56 PM UTC |
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
ReviewFindingsLow
Previous runReviewThe change correctly adds 409 retry logic to The four new unit tests cover the key paths: happy path, 409→update→retry→success, non-409 immediate failure, and retry exhaustion. Test assertions are precise (exact counts, not weak inequalities). No security, intent, documentation, or cross-repo contract concerns. FindingsLow
Previous run (2)ReviewFindingsLow
Previous run (3)ReviewFindingsLow
Previous run (4)ReviewFindingsMedium
Previous run (5)ReviewFindingsMedium
Low
Previous run (6)ReviewFindingsMedium
Low
Labels: PR modifies the GitHub forge client to fix an e2e test flake. Previous run (7)ReviewFindingsMedium
Low
Labels: PR fixes a bug in the GitHub forge client that caused flaky e2e test failures |
fd6cbd9 to
c140351
Compare
|
🤖 Finished Review · ✅ Success · Started 2:47 PM UTC · Completed 3:13 PM UTC |
ralphbean
left a comment
There was a problem hiding this comment.
Pushed fc5c076. Qodo's first item (range over int) is a false positive — for i := range n has been valid since Go 1.22 and we use it in do() already. The second item about ignoring update-branch errors is legit though, and the fullsend review flagged the same thing plus a few more.
Changes:
- update-branch response now goes through
checkStatus(), same pattern asUpdatePullRequestBranch - skips the update-branch call on the final iteration where no retry follows
- wraps the last merge error with
%win the exhaustion message - tightened the retry test to assert exactly 3 attempts
- added a test for update-branch failure
|
🤖 Finished Review · ✅ Success · Started 4:55 PM UTC · Completed 5:08 PM UTC |
When MergeChangeProposal gets a 409 "Head branch is out of date", call GitHub's update-branch endpoint to sync the PR branch with the base, wait briefly, then retry the merge. Up to 3 attempts before giving up. Non-409 errors are still returned immediately. Closes #2432 Assisted-by: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Ralph Bean <rbean@redhat.com>
Check the update-branch response status code with checkStatus (matching the pattern in UpdatePullRequestBranch) and return updateErr if the request itself fails. Skip the update-branch call on the final attempt since no retry will follow. Wrap the last merge error with %w so callers can inspect the underlying APIError. Tighten the test assertion from > 1 to exactly 3 attempts. Signed-off-by: Ralph Bean <rbean@redhat.com> Assisted-by: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Ralph Bean <rbean@redhat.com>
fc5c076 to
ddb9b37
Compare
waynesun09
left a comment
There was a problem hiding this comment.
[medium] redundant-retry — e2e/admin/admin_test.go
Both mergeEnrollmentPR (lines 296-316) and mergeScaffoldPR (lines 370-389) have their own 3-attempt retry loops that catch 409 errors, call UpdatePullRequestBranch, and sleep 5 seconds. With MergeChangeProposal now retrying internally (3 attempts, 3s delays), these layers compound to 3×3 = 9 merge attempts with up to ~24s of cumulative delay. The outer retry still matches the 409 via errors.As because the final error wraps the *APIError with %w.
Suggested fix: Remove the outer retry loops from both helpers — a single MergeChangeProposal call now handles the full retry sequence. Can be a tracked follow-up if preferred.
Assisted-by: Claude (review), Gemini (review), Codex (review)
Replace inline update-branch logic with a call to the existing UpdatePullRequestBranch method, eliminating inconsistencies between the two call sites. Signed-off-by: Ralph Bean <rbean@redhat.com> Assisted-by: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Ralph Bean <rbean@redhat.com>
|
🤖 Finished Review · ✅ Success · Started 9:11 PM UTC · Completed 9:23 PM UTC |
waynesun09
left a comment
There was a problem hiding this comment.
Review squad (5 agents: Claude, Gemini, Codex) findings, deduplicated against existing PR comments. Most MEDIUM+ items from this pass were already raised and resolved in earlier commits (ddb9b37, d5e1f4c) or already open in the prior review (the redundant e2e retry-loop finding at #4666709137 — not re-posted here). Three new unposted findings below.
Assisted-by: Claude (review), Gemini (review), Codex (review)
Replace the flat 3-second sleep after update-branch with SHA polling that confirms the async branch update actually landed before retrying the merge. Extract retry timing into package vars so tests don't pay real wall-clock delays. Add tests for update-branch failure mid-retry and context cancellation during the poll loop. Assisted-by: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Ralph Bean <rbean@redhat.com>
|
🤖 Finished Review · ✅ Success · Started 6:26 PM UTC · Completed 6:40 PM UTC |
waynesun09
left a comment
There was a problem hiding this comment.
All prior review-squad findings (async update-branch race, hardcoded retry delay, missing test coverage) were fixed correctly in d069686 — verified by reading the fix and running go test ./internal/forge/github/... -race -run TestMergeChangeProposal -v (6/6 pass, race-clean, ~1s).
Non-blocking: the PR description is stale — it still says "waits 3s, then retries" but that was replaced by SHA polling, and the test plan doesn't list the two new tests (TestMergeChangeProposal_UpdateBranchFailsMidRetry, TestMergeChangeProposal_ContextCancelledDuringPoll). Worth a quick update before merge for anyone reading the PR later.
Assisted-by: Claude (review)
|
Is this still needed, given that #2432 is closed? |
|
#2435 was a tactical fix — it added retry logic at the e2e test call site so the test stops flaking. This one moves the retry into So yeah, the bug that motivated it is fixed at the test level, but the underlying library call still can't handle a 409 on its own. If any other caller hits the same race, they'd get the same failure. |
|
Merging as Ralph is on PTO |
|
🤖 Finished Retro · ✅ Success · Started 11:49 AM UTC · Completed 12:00 PM UTC |
Retro: PR #2434 — Retry merge on 409 after updating PR branchTimeline: Issue #2432 filed Jun 18 (flaky 409 on enrollment PR merge). Triage agent ran (run 27773271387), diagnosed correctly, recommended fixing at the PR #2434 went through 6 review agent runs over 33 days (Jun 18 – Jul 21). The review agent consistently found legitimate low/medium findings (error handling gaps, edge cases, test assertion weakness) with zero false positives. However, three important findings were caught only by human reviewer waynesun09 (using a multi-model review squad): (1) [high] race condition — What went well: The review agent produced zero false positives across 6 runs (vs Qodo's 50% false-positive rate). Its error-handling and test-adequacy findings were all actionable and drove real fixes. The triage agent's root-cause diagnosis was accurate. What could go better: Two key gaps emerged — the triage agent's fix-location recommendation (call-site vs implementation level) and the review agent's inability to detect inline reimplementation of existing methods. Existing issue evidence:
Proposals filed
|
Summary
MergeChangeProposalgets a 409 "Head branch is out of date", it now calls GitHub'sPUT .../pulls/{n}/update-branchto sync the PR with the base, waits 3s, then retries the merge (up to 3 attempts).TestAdminInstallUninstallfailure at the enrollment PR merge step.Closes #2432
Test plan
TestMergeChangeProposal_Success— happy path unchangedTestMergeChangeProposal_409UpdatesBranchAndRetries— 409 triggers update-branch then successful retryTestMergeChangeProposal_NonConflictErrorNotRetried— 422 not retriedTestMergeChangeProposal_409PersistsAfterRetries— gives up after max attempts with clear error🤖 Generated with Claude Code