Fix silent failure on large PRs (406 diff too large) - #82
MaxwellCalkin wants to merge 1 commit into
Conversation
When the GitHub API returns HTTP 406 for diffs exceeding the 20,000-line limit, the action previously swallowed the error and reported 0 findings, giving a false sense of security. This fix: - Detects the 406 response in get_pr_diff() and falls back to local git diff (origin/base...HEAD, then HEAD~1) - If local diff also fails, raises DiffTooLargeError with a structured JSON output including scan_status: "incomplete" and skip_reason - Updates action.yml to detect incomplete scans and surface them as ::error:: annotations instead of silently passing Fixes anthropics#80 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Nice approach to the 406 — falling back to a local The fallback recovers the same large diff, so on a PR big enough to hit the 406 the prompt still exceeds the model's context and the API returns #133 is just that one line changed to a prefix match, plus tests. Entirely yours to fold in if it's easier as part of this PR — I raised it separately only because it's an independent defect from the 406 and your diff doesn't touch it. |
Summary
Fixes #80 — When a PR's unified diff exceeds GitHub's 20,000-line API limit, the action silently reports 0 findings instead of surfacing the error. This gives a false sense of security since the PR appears clean when no analysis actually occurred.
Changes
get_pr_diff()— Instead of lettingraise_for_status()throw a generic error that gets swallowed, we now explicitly check for status 406 and fall back gracefullygit diff— When the API returns 406, we rungit diff origin/<base_ref>...HEADlocally (the action already checks out code), falling back togit diff HEAD~1if neededDiffTooLargeErrorexception — Raised only when both the API and all local diff fallbacks failscan_status: "incomplete"andskip_reason: "diff_too_large"instead of an empty findings listaction.yml— The shell wrapper now detectsscan_status == "incomplete"and emits::error::annotations so the failure is visible in the GitHub Actions UI (instead of silently passing with 0 findings)How it works
get_pr_diff()requests the diff from GitHub API_get_local_diff(base_ref)which tries:git diff origin/main...HEAD(using PR's actual base branch)git diff HEAD~1(fallback)DiffTooLargeError,main()outputs structured error JSON,action.ymlsurfaces it as an error annotationTests
Added 9 new tests (176 total pass):
origin/base...HEADbeforeHEAD~1HEAD~1when base ref failsHEAD~1)DiffTooLargeErrorwhen all fallbacks failmain()produces structured incomplete scan output forDiffTooLargeErrorTest plan