Improve GitHub branch listing pagination#102
Conversation
Greptile SummaryThis PR rewrites
Confidence Score: 5/5The PR is safe to merge; all adapters return the new structured shape consistently and the pagination logic is correct across providers. All adapters correctly implement the new signature, return type, and pagination contract. The GitHub GraphQL probe logic ensures items is never empty when hasNext is true. The Gogs branch-existence scan iterates through all virtual pages. The abstract contract, concrete implementations, and tests are all in sync. The only note is a minor efficiency opportunity in the GitHub adapter for $perPage less than 100. No files require special attention. Important Files Changed
Reviews (11): Last reviewed commit: "Document that Gitea has no server-side b..." | Re-trigger Greptile |
43e2053 to
e71e384
Compare
All providers now return array{items, hasNext, nextCursor} so callers
get a consistent shape regardless of provider. GitHub uses true GraphQL
cursor pagination; GitLab/Gitea/Gogs/Forgejo compute hasNext from the
client-side slice and always return nextCursor: null. Error-path early
returns and the Gogs internal branch-existence check are updated to match.
Tests updated and testListBranchesNonExistingRepository added for GitLab
and Gitea (inherited by Gogs and Forgejo).
3a84574 to
f85fa75
Compare
| 'name' => $repositoryName, | ||
| 'first' => $perPage, | ||
| 'after' => $currentCursor, | ||
| 'query' => $search !== '' ? $search : null, |
There was a problem hiding this comment.
Do I understand this query parameter is reasin to use GraphQL? Can we try same endpoint with HTTP to have proof query isnt accepted there?
There was a problem hiding this comment.
Tested this. REST branches API has no search support and only supports page-based pagination. We need GraphQL here for both branch search and cursor-based pagination (nextCursor). Added comments above the query documenting both limitations.
| $gql = <<<'GRAPHQL' | ||
| query ListBranches($owner: String!, $name: String!, $first: Int!, $after: String, $query: String) { | ||
| repository(owner: $owner, name: $name) { | ||
| refs(refPrefix: "refs/heads/", first: $first, after: $after, orderBy: {field: ALPHABETICAL, direction: ASC}, query: $query) { |
There was a problem hiding this comment.
Curious, does Gitea have refs endpoints too? I recall they try to be compatible with GitHub, I would expect we can urilize same thing there.
There was a problem hiding this comment.
Nope, Gitea does not support server-side branch filtering
Parameters like q or search are ignored server-side (verified against Codeberg/Forgejo). Since Gitea also lacks GraphQL support, fetching all branches and filtering client-side is currently unavoidable. Added a comment documenting this behavior.
The private helper was only called from one place; the logic is now directly inside listBranches with an explanatory comment block.
Two REST limitations make GraphQL necessary: 1. REST branches endpoint has no search/filter param (query is GraphQL-only) 2. REST only supports integer page offsets (per-edge cursors are GraphQL-only)
GitLab's branches API accepts search=^term to filter branches that begin with term, so we no longer need to fetch all pages before filtering. A single paginated request is made; hasNext is read from X-Next-Page.
The parameter was being reassigned and then used 10 lines later for client-side slicing, which looked like dead code. Renaming it and adding a comment makes the intent clear.
Live test on Codeberg (Forgejo/Gitea) confirmed the q param is silently ignored — fetch-all + client-side str_starts_with is the only option.
No description provided.