diff --git a/app/finders/merge_requests_finder.rb b/app/finders/merge_requests_finder.rb index d0687d28c2188fb79dc693d822966c36a5dcd8f4..068ae7f8c897f366977be57a0bd10fcf72dbf7d6 100644 --- a/app/finders/merge_requests_finder.rb +++ b/app/finders/merge_requests_finder.rb @@ -17,14 +17,42 @@ # sort: string # non_archived: boolean # my_reaction_emoji: string +# source_branch: string +# target_branch: string # class MergeRequestsFinder < IssuableFinder def klass MergeRequest end + def filter_items(_items) + items = by_source_branch(super) + + by_target_branch(items) + end + private + def source_branch + @source_branch ||= params[:source_branch].presence + end + + def by_source_branch(items) + return items unless source_branch + + items.where(source_branch: source_branch) + end + + def target_branch + @target_branch ||= params[:target_branch].presence + end + + def by_target_branch(items) + return items unless target_branch + + items.where(target_branch: target_branch) + end + def item_project_ids(items) items&.reorder(nil)&.select(:target_project_id) end diff --git a/changelogs/unreleased/merge-requests-api-filter-by-branch.yml b/changelogs/unreleased/merge-requests-api-filter-by-branch.yml new file mode 100644 index 0000000000000000000000000000000000000000..03a7e4d0f715eee0e43c306c8243b6e0beafaaad --- /dev/null +++ b/changelogs/unreleased/merge-requests-api-filter-by-branch.yml @@ -0,0 +1,5 @@ +--- +title: Add support for filtering by source and target branch to merge requests API +merge_request: +author: +type: added diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md index 2957a0a5f487052194d28ef87d0f715492c6fdfd..6ce021cb4bfa64f682aaedb59e31a502c4381430 100644 --- a/doc/api/merge_requests.md +++ b/doc/api/merge_requests.md @@ -47,6 +47,8 @@ Parameters: | `author_id` | integer | no | Returns merge requests created by the given user `id`. Combine with `scope=all` or `scope=assigned-to-me` | | `assignee_id` | integer | no | Returns merge requests assigned to the given user `id` | | `my_reaction_emoji` | string | no | Return merge requests reacted by the authenticated user by the given `emoji` _([Introduced][ce-14016] in GitLab 10.0)_ | +| `source_branch` | string | no | Return merge requests with the given source branch | +| `target_branch` | string | no | Return merge requests with the given target branch | | `search` | string | no | Search merge requests against their `title` and `description` | ```json @@ -162,6 +164,8 @@ Parameters: | `author_id` | integer | no | Returns merge requests created by the given user `id` _([Introduced][ce-13060] in GitLab 9.5)_ | | `assignee_id` | integer | no | Returns merge requests assigned to the given user `id` _([Introduced][ce-13060] in GitLab 9.5)_ | | `my_reaction_emoji` | string | no | Return merge requests reacted by the authenticated user by the given `emoji` _([Introduced][ce-14016] in GitLab 10.0)_ | +| `source_branch` | string | no | Return merge requests with the given source branch | +| `target_branch` | string | no | Return merge requests with the given target branch | | `search` | string | no | Search merge requests against their `title` and `description` | ```json diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb index 719afa0929578b553d004c3c0453b39bec6fcba8..4ffd4895c7e33420dd734ccc2b5784395409fa85 100644 --- a/lib/api/merge_requests.rb +++ b/lib/api/merge_requests.rb @@ -48,6 +48,8 @@ module API optional :scope, type: String, values: %w[created-by-me assigned-to-me all], desc: 'Return merge requests for the given scope: `created-by-me`, `assigned-to-me` or `all`' optional :my_reaction_emoji, type: String, desc: 'Return issues reacted by the authenticated user by the given emoji' + optional :source_branch, type: String, desc: 'Return merge requests with the given source branch' + optional :target_branch, type: String, desc: 'Return merge requests with the given target branch' optional :search, type: String, desc: 'Search merge requests for text present in the title or description' use :pagination end diff --git a/spec/finders/merge_requests_finder_spec.rb b/spec/finders/merge_requests_finder_spec.rb index 9385c892c9ec6d4d179a1a1974479ac5116bbb48..7917a00fc50e7f13822083b221296a4d6170aa9a 100644 --- a/spec/finders/merge_requests_finder_spec.rb +++ b/spec/finders/merge_requests_finder_spec.rb @@ -18,7 +18,7 @@ describe MergeRequestsFinder do let(:project4) { create(:project, :public, group: subgroup) } let!(:merge_request1) { create(:merge_request, :simple, author: user, source_project: project2, target_project: project1) } - let!(:merge_request2) { create(:merge_request, :simple, author: user, source_project: project2, target_project: project1, state: 'closed') } + let!(:merge_request2) { create(:merge_request, :conflict, author: user, source_project: project2, target_project: project1, state: 'closed') } let!(:merge_request3) { create(:merge_request, :simple, author: user, source_project: project2, target_project: project2) } let!(:merge_request4) { create(:merge_request, :simple, author: user, source_project: project3, target_project: project3) } let!(:merge_request5) { create(:merge_request, :simple, author: user, source_project: project4, target_project: project4) } @@ -74,6 +74,22 @@ describe MergeRequestsFinder do expect(merge_requests).to contain_exactly(merge_request1) end + it 'filters by source branch' do + params = { source_branch: merge_request2.source_branch } + + merge_requests = described_class.new(user, params).execute + + expect(merge_requests).to contain_exactly(merge_request2) + end + + it 'filters by target branch' do + params = { target_branch: merge_request2.target_branch } + + merge_requests = described_class.new(user, params).execute + + expect(merge_requests).to contain_exactly(merge_request2) + end + context 'filtering by group milestone' do let!(:group) { create(:group, :public) } let(:group_milestone) { create(:milestone, group: group) } diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb index 14dd9da119d76f8a9a51ad377d6a7bd81a9c6b5e..658cedd6b5f3ac02e3c8bf48591ab942a8280142 100644 --- a/spec/requests/api/merge_requests_spec.rb +++ b/spec/requests/api/merge_requests_spec.rb @@ -151,6 +151,26 @@ describe API::MergeRequests do expect(json_response.first['id']).to eq(merge_request3.id) end + context 'source_branch param' do + it 'returns merge requests with the given source branch' do + get api('/merge_requests', user), source_branch: merge_request_closed.source_branch, state: 'all' + + expect(json_response.length).to eq(2) + expect(json_response.map { |mr| mr['id'] }) + .to contain_exactly(merge_request_closed.id, merge_request_merged.id) + end + end + + context 'target_branch param' do + it 'returns merge requests with the given target branch' do + get api('/merge_requests', user), target_branch: merge_request_closed.target_branch, state: 'all' + + expect(json_response.length).to eq(2) + expect(json_response.map { |mr| mr['id'] }) + .to contain_exactly(merge_request_closed.id, merge_request_merged.id) + end + end + context 'search params' do before do merge_request.update(title: 'Search title', description: 'Search description') @@ -426,6 +446,26 @@ describe API::MergeRequests do expect(response_dates).to eq(response_dates.sort) end end + + context 'source_branch param' do + it 'returns merge requests with the given source branch' do + get api('/merge_requests', user), source_branch: merge_request_closed.source_branch, state: 'all' + + expect(json_response.length).to eq(2) + expect(json_response.map { |mr| mr['id'] }) + .to contain_exactly(merge_request_closed.id, merge_request_merged.id) + end + end + + context 'target_branch param' do + it 'returns merge requests with the given target branch' do + get api('/merge_requests', user), target_branch: merge_request_closed.target_branch, state: 'all' + + expect(json_response.length).to eq(2) + expect(json_response.map { |mr| mr['id'] }) + .to contain_exactly(merge_request_closed.id, merge_request_merged.id) + end + end end end