fix(github): reject empty or repeated review-thread cursors - #169
Conversation
ListPullReviewThreads followed hasNextPage and assigned the next GraphQL cursor with no empty or repeat check. A GitHub or proxy page that kept hasNextPage true with a blank or stuck endCursor refetched forever during gitcrawl sync PR enrichment. Reject a missing endCursor when another page is claimed, and remember cursors already followed for both thread pages and nested comment pages. Sibling crawlers already fail closed on a non-advancing cursor. Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
|
🦞👀 Pull request received. I will update this pull request when review starts. |
|
Codex review: needs maintainer review before merge. Reviewed September 4, 2026, 4:03 AM ET / 08:03 UTC. ClawSweeper reviewWhat this changesGitcrawl rejects empty or repeated review-pagination cursors, adds regression coverage, and documents the resulting sync errors. Merge readiness✅ Ready for maintainer review This remains a useful, well-supported fix: main and v0.9.4 still lack the guards. No blocking correctness or security findings remain. Priority: P2 Review scores
Verification
How this fits togetherGitcrawl fetches GitHub review threads and their comments during pull-request synchronization. Complete responses become local SQLite evidence used by review and search workflows. flowchart TD
A[Sync with PR details] --> B[GitHub GraphQL client]
B --> C[Review threads and comments]
C --> D{Pagination complete?}
D -->|Yes| E[Store complete review evidence]
D -->|No| F{Cursor advances?}
F -->|Yes| B
F -->|No| G[Report error and retain prior evidence]
Before mergeNone. Agent review detailsSecurityNone. Review metrics
Technical reviewBest possible solution: Reject non-advancing pagination through the existing sync error path while retaining prior archive evidence and normal multi-page results. Do we have a high-confidence way to reproduce the issue? Yes. Returning hasNextPage=true with an empty or cycling cursor makes current main repeat GraphQL requests; source establishes the loop, and the supplied CLI run reports reproducing it. This review did not execute the scenario. Is this the best way to solve the issue? Yes. Per-fetch cursor tracking repairs the owning loops without changing pagination APIs, stored formats, or valid-response behavior. AGENTS.md: not found in the target repository. Codex review notes: model internal, reasoning high; reviewed against 488e87da8d37. LabelsLabel justifications:
EvidenceWhat I checked:
Likely related people:
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
HistoryReview history (8 earlier review cycles)
|
Merge main after #169 and preserve both the cursor-fix thanks and the integrated dependency notes. Keep the Go 1.27.1 candidate separate from main until managed CodeQL and the full build/runtime checks confirm compatibility.
Align source and Docker builds on Go 1.27.1 for CrawlKit 0.14.8, with the source-build minimum and macOS 13 minimum for newly built binaries documented in README, installation docs and the changelog. The documented platform transition is approved for this dependency update. Absorb the compatible updates from #171: SQLite 1.58.0, runewidth, pprof, golden, TruffleHog 3.97.4 and Dockerfile frontend 1.27. Keep SQLite's exact libc 1.75.6 requirement. Apply only the indentation required by the Go 1.27 formatter in application code. Preserve the review-cursor fix and contributor thanks from #169. Full checks pass at 85.6% coverage, including six snapshot targets. Real CLI proof reopens an old archive, syncs through HTTP, searches through FTS, checks SQLite integrity, and preserves existing review rows on malformed cursors. Docker build/runtime and managed CodeQL 2.26.4 with actual Go 1.27.1 pass on the reviewed head. Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
When GitHub or a proxy returns
hasNextPage: truewith a missing or repeatedendCursor,gitcrawl sync --with pr-detailscan refetch review-thread pages indefinitely. Nested comment pages already rejected missing cursors but could also loop on repeated cursors.This change validates cursors in the GitHub pagination client before following another page. Both loops reject previously followed cursors, and the thread loop also rejects empty cursors. Errors propagate through PR enrichment without saving incomplete review-thread evidence. Normal pagination remains unchanged. The sync guide documents the error and retry behavior.
Thanks @SebTardif for the fix, regression tests, and original reproduction. The original contributor commit is preserved, with a maintainer documentation follow-up.
Validation:
sync synthetic/cursor-proof --numbers 8 --include-comments --with pr-details --jsonagainst a local synthetic HTTP API and real temporary SQLite archive. Main exceeded a three-second deadline with thousands of GraphQL requests for empty, repeated, and nested repeated cursors. The fixed CLI exits after one or two requests, reports the cursor error, and preserves previously stored review rows.The synthetic fixture proves the production CLI/HTTP/storage path; no malformed response was induced on github.com.
Maintainer closeout for
0916d4f91dd2028632a1e25a9b671f518f308931:make checkpasses using Go 1.26.7 and its matching formatter: tidy, format, vet, govulncheck, deadcode, full suite (85.1% coverage), CLI smoke, release-script tests, and all six snapshot targets.