Fix branches API offset pagination returning empty pages

What does this MR do and why?

Fix branches API offset pagination returning empty pages

GET /projects/:id/repository/branches returns an empty array for every page beyond page 1 when per_page * page exceeds the default per-page maximum of 100. The pagination headers stay correct, so the count and data paths diverge. This regressed after enabling the use_new_branches_finder_api feature flag, which routes unfiltered branch listing through Gitlab::Git::Finders::BranchesFinder.

BranchesFinder implements offset pagination by over-fetching per_page * page refs and slicing the target page, but RefsFinder silently clamped the over-fetch to MAX_PER_PAGE, so the slice landed past the end of the returned refs.

  • Add a scoped max_per_page option to RefsFinder that overrides the default cap only when provided.
  • Pass max_per_page: effective_per_page from BranchesFinder so the over-fetch limit reaches Gitaly instead of being clamped.
  • Add regression coverage across the finders and the branches API.

References

How to set up and validate locally

  1. Ensure the use_new_branches_finder_api feature flag is enabled (default).
  2. Use a project with more branches than per_page (or lower the cap for testing).
  3. Request page 2:
    curl -H "PRIVATE-TOKEN: $TOKEN" \
      '<gitlab>/api/v4/projects/<id>/repository/branches?per_page=100&page=2'
  4. Confirm the body returns the second page of branches (previously []), with consistent X-Page / X-Total / X-Total-Pages headers.

Automated coverage:

bundle exec rspec spec/lib/gitlab/git/finders/refs_finder_spec.rb \
  spec/lib/gitlab/git/finders/branches_finder_spec.rb \
  spec/requests/api/branches_spec.rb

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

Merge request reports

Loading