fix(#2093): retry empty PR file list before refusing to approve - #1196
Conversation
Functional tests are runningAuthorization passed for this commit. See the Functional Tests workflow for results. |
PR Summary by QodoRetry transient empty PR file lists before blocking approval
AI Description
Diagram
High-Level Assessment
Files changed (5)
|
Code Review by Qodo
1. Protected scripts need human review
|
waynesun09
left a comment
There was a problem hiding this comment.
Review-only findings from an automated PR sweep.
|
/fs-review |
|
🤖 Finished Review · ✅ Success · Started 8:37 PM UTC · Completed 8:54 PM UTC Commit: Runtime: claude · Model: opus → claude-opus-4-6 · Effort: high · Cost: $5.43 |
|
Risk Assessment: moderate (2/5) DetailsTargeted edge-case bug fix in high-churn, multi-author core review scripts (5 protected paths, heavy regression history on post-review.sh) offset by narrow, well-tested scope with no security, dependency, or CI concerns and strong issue-to-implementation alignment. |
ReviewFindingsMedium
Low
Next steps:
|
post-review.sh refuses to approve a PR when it cannot establish what
changed, guarding against blind approvals. But the file list can come
back empty transiently: right after a merge-commit update GitHub has
not finished computing the diff, so the review agent fails a genuinely
non-empty PR.
Two changes:
- forge_get_pr_files (GitHub) now reads the paginated
/pulls/{n}/files REST endpoint instead of the async-populated
`gh pr view --json files` summary field, which reflects the computed
diff more directly.
- The call site retries once (notice + short sleep + re-fetch) before
the empty-result guard. The retry recovers from a transient race; a
genuinely empty result still refuses to approve. This applies to all
forges since the guard is forge-agnostic.
Adds integration tests for retry-recovers and retry-still-fails, and
regenerates the post-review.sh / pre-review.sh bundles.
Fixes fullsend-ai/fullsend#2093
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Shai Revivo <srevivo@redhat.com>
The empty-PR-files retry branch calls `sleep 10` before re-fetching. The integration tests prepend only MOCK_BIN to PATH and provided no `sleep` mock, so the real sleep ran in all three empty-list cases (retry-recovers, retry-still-fails, and the pre-existing safety-net-independent test), adding ~30s to every serial suite run. Add a no-op `sleep` mock to MOCK_BIN. The retry logic doesn't depend on real elapsed time, so stubbing it keeps the tests deterministic and fast without changing what they assert. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: Shai Revivo <srevivo@redhat.com>
Treat non-zero forge file-list fetches like empty results so the retry and fail-closed guard run for GitHub and GitLab. Add regression coverage for both adapters and describe the async-diff explanation as a hypothesis rather than an API guarantee. Co-authored-by: Codex <noreply@openai.com> Signed-off-by: Shai Revivo <srevivo@redhat.com>
6eedeef to
d24faf2
Compare
Preserve fetch status separately from captured filenames so a paginated forge error cannot be mistaken for a complete file list. Retry failed fetches once, discard partial output, and keep the approval guard fail-closed across GitHub and GitLab.\n\nCo-authored-by: Codex <noreply@openai.com> Signed-off-by: Shai Revivo <srevivo@redhat.com>
|
🤖 Finished Retro · ✅ Success · Started 7:23 PM UTC · Completed 7:37 PM UTC Commit: Runtime: claude · Model: opus → claude-opus-4-6 · Effort: high · Cost: $5.77 |
Retro: PR #1196 — retry empty PR file list before refusing to approveTimeline
Review QualityStrengths:
Key gap:
Existing Issue CoverageAll improvement opportunities identified in this retro are already covered by open issues:
Housekeepingfullsend-ai/fullsend#2093 remains open. Since the fix landed in a different repo ( |
What
Fixes the review agent failing genuinely non-empty PRs when the forge returns an empty changed-files list.
post-review.shrefuses to approve a PR when it cannot establish what changed (a safety net against blind approvals). But the file list can come back empty transiently: right after a merge-commit update, GitHub has not finished computing the diff, soforge_get_pr_filesreturns nothing and the agent aborts on a PR that actually has changes.Changes
scripts/lib/github-review-ops.lib.sh—forge_get_pr_filesnow reads the paginated/pulls/{n}/filesREST endpoint instead of the asynchronously-populatedgh pr view --json filessummary field. The files endpoint reflects the computed diff more directly.scripts/post-review.src.sh— the empty-result guard now retries once (::notice::+ shortsleep+ re-fetch) before refusing to approve. The retry recovers from the transient race; a genuinely empty result still refuses to approve. This lives at the call site, so it protects every forge (GitHub + GitLab) regardless of whichforge_get_pr_filesimplementation runs.scripts/post-review-test.sh— mockghupdated for the new endpoint; addedempty-pr-files-retry-recoversandempty-pr-files-retry-still-failsintegration tests.post-review.shandpre-review.shbundles (make script-build).Verification
make script-build+make check-bundle— bundles in syncbash scripts/post-review-test.sh— 106 pass, incl. both new testsmake lint(skillsaw) — Grade A, 0 errors/warningspre-commit runon changed files — shellcheck + secret scan passThe remaining
harness-jira-test.shfailures undermake script-testare pre-existing and env-dependent (unsetJIRA_*vars); they reproduce on a cleanmainand are unrelated to this change.Note: the tracking issue lives in
fullsend-ai/fullsend#2093, but the bug and fix are in this repo (the review scripts).🤖 Generated with Claude Code