Refactor Commits API to use CommitsFinder + GitalyKeysetPager
## Summary Refactor the Commits API endpoint to use `CommitsFinder` and `GitalyKeysetPager`, replacing the inline pagination logic with the standard thin-controller pattern. ## Parent Issue This is part of #595504 (Epic: Refactor Commits API to use standard keyset pagination patterns) ## Background This is the final implementation MR that brings everything together. After `CommitsFinder` is created and integrated with `GitalyKeysetPager`, we can simplify the API endpoint significantly. ## Current State (lib/api/commits.rb) ~90 lines of inline conditional logic: ```ruby get ':id/repository/commits' do if params[:pagination] == 'keyset' # ~40 lines of keyset pagination logic else # ~40 lines of offset pagination logic end end ``` ## Proposed State ~15 lines using finder + pager: ```ruby get ':id/repository/commits' do not_found! 'Repository' unless user_project.repository_exists? finder = CommitsFinder.new( user_project, current_user, declared_params(include_missing: false) ) serializer = params[:with_stats] ? Entities::CommitWithStats : Entities::Commit commits = Gitlab::Pagination::GitalyKeysetPager.new(self, user_project).paginate(finder) present commits, with: serializer rescue ArgumentError => e render_api_error!(e.message, 400) end ``` ## Acceptance Criteria - [ ] Replace inline pagination logic with `CommitsFinder` + `GitalyKeysetPager` - [ ] Remove ~70 lines of code from API endpoint - [ ] All existing tests continue to pass - [ ] Add new API tests for keyset pagination edge cases: - [ ] `with_stats: true` with keyset pagination - [ ] `since/until` filters with keyset pagination - [ ] `author` filter with keyset pagination - [ ] `ref_name` (non-all mode) with keyset pagination - [ ] Feature flag controls keyset pagination availability - [ ] Backward compatible - existing offset pagination unchanged ## API Parameters New parameters added: - `pagination=keyset` - Opt-in to cursor-based pagination - `page_token=<sha>` - Cursor for next page Unsupported with keyset (return 400): - `path` - `first_parent` - `order` (non-default) - `trailers` - `follow` ## References - Parent epic: #595504 - Depends on: CommitsFinder issue, GitalyKeysetPager integration issue - Original MR: !229705 - Original bug: #586997
issue