From 327e344417888abbbc0811a8068c96c1af6fd326 Mon Sep 17 00:00:00 2001 From: mhasbini Date: Wed, 12 Apr 2017 14:38:00 +0300 Subject: Add issues/:iid/closed_by api endpoint --- changelogs/unreleased/26437-closed-by.yml | 4 ++ doc/api/issues.md | 61 +++++++++++++++++++++++++ lib/api/issues.rb | 15 ++++++ spec/factories/merge_requests_closing_issues.rb | 6 +++ spec/features/issuables/issuable_list_spec.rb | 2 +- spec/requests/api/issues_spec.rb | 35 ++++++++++++++ 6 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 changelogs/unreleased/26437-closed-by.yml create mode 100644 spec/factories/merge_requests_closing_issues.rb diff --git a/changelogs/unreleased/26437-closed-by.yml b/changelogs/unreleased/26437-closed-by.yml new file mode 100644 index 00000000000..6325d3576bc --- /dev/null +++ b/changelogs/unreleased/26437-closed-by.yml @@ -0,0 +1,4 @@ +--- +title: Add issues/:iid/closed_by api endpoint +merge_request: +author: mhasbini diff --git a/doc/api/issues.md b/doc/api/issues.md index 5f01fcdd396..6c10b5ab0e7 100644 --- a/doc/api/issues.md +++ b/doc/api/issues.md @@ -823,6 +823,67 @@ Example response: } ``` +## List merge requests that will close issue on merge + +Get all the merge requests that will close issue when merged. + +``` +GET /projects/:id/issues/:issue_iid/closed_by +``` + +| Attribute | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `id` | integer | yes | The ID of a project | +| `issue_iid` | integer | yes | The internal ID of a project issue | + +```bash +curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/1/issues/11/closed_by +``` + +Example response: + +```json +[ + { + "id": 6471, + "iid": 6432, + "project_id": 1, + "title": "add a test for cgi lexer options", + "description": "closes #11", + "state": "opened", + "created_at": "2017-04-06T18:33:34.168Z", + "updated_at": "2017-04-09T20:10:24.983Z", + "target_branch": "master", + "source_branch": "feature.custom-highlighting", + "upvotes": 0, + "downvotes": 0, + "author": { + "name": "Administrator", + "username": "root", + "id": 1, + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", + "web_url": "https://gitlab.example.com/root" + }, + "assignee": null, + "source_project_id": 1, + "target_project_id": 1, + "labels": [], + "work_in_progress": false, + "milestone": null, + "merge_when_pipeline_succeeds": false, + "merge_status": "unchecked", + "sha": "5a62481d563af92b8e32d735f2fa63b94e806835", + "merge_commit_sha": null, + "user_notes_count": 1, + "should_remove_source_branch": null, + "force_remove_source_branch": false, + "web_url": "https://gitlab.example.com/gitlab-org/gitlab-test/merge_requests/6432" + } +] +``` + + ## Comments on issues Comments are done via the [notes](notes.md) resource. diff --git a/lib/api/issues.rb b/lib/api/issues.rb index 09053e615cb..60b9a89d6a2 100644 --- a/lib/api/issues.rb +++ b/lib/api/issues.rb @@ -215,6 +215,21 @@ module API authorize!(:destroy_issue, issue) issue.destroy end + + desc 'List merge requests closing issue' do + success Entities::MergeRequestBasic + end + params do + requires :issue_iid, type: Integer, desc: 'The internal ID of a project issue' + end + get ':id/issues/:issue_iid/closed_by' do + issue = find_project_issue(params[:issue_iid]) + + merge_request_ids = MergeRequestsClosingIssues.where(issue_id: issue).select(:merge_request_id) + merge_requests = MergeRequestsFinder.new(current_user, project_id: user_project.id).execute.where(id: merge_request_ids) + + present paginate(merge_requests), with: Entities::MergeRequestBasic, current_user: current_user, project: user_project + end end end end diff --git a/spec/factories/merge_requests_closing_issues.rb b/spec/factories/merge_requests_closing_issues.rb new file mode 100644 index 00000000000..fdbdc00cad7 --- /dev/null +++ b/spec/factories/merge_requests_closing_issues.rb @@ -0,0 +1,6 @@ +FactoryGirl.define do + factory :merge_requests_closing_issues do + issue + merge_request + end +end diff --git a/spec/features/issuables/issuable_list_spec.rb b/spec/features/issuables/issuable_list_spec.rb index 3dc872ae520..f3ec80bb149 100644 --- a/spec/features/issuables/issuable_list_spec.rb +++ b/spec/features/issuables/issuable_list_spec.rb @@ -68,7 +68,7 @@ describe 'issuable list', feature: true do source_project: project, source_branch: generate(:branch)) - MergeRequestsClosingIssues.create!(issue: issue, merge_request: merge_request) + create(:merge_requests_closing_issues, issue: issue, merge_request: merge_request) end end end diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb index 551aae7d701..e8d9f7f0f0c 100644 --- a/spec/requests/api/issues_spec.rb +++ b/spec/requests/api/issues_spec.rb @@ -1345,6 +1345,41 @@ describe API::Issues, api: true do include_examples 'time tracking endpoints', 'issue' end + describe 'GET :id/issues/:issue_iid/closed_by' do + let(:merge_request) do + create(:merge_request, + :simple, + author: user, + source_project: project, + target_project: project, + description: "closes #{issue.to_reference}") + end + + before do + create(:merge_requests_closing_issues, issue: issue, merge_request: merge_request) + end + + it 'returns merge requests that will close issue on merge' do + get api("/projects/#{project.id}/issues/#{issue.iid}/closed_by", user) + + expect_paginated_array_response(size: 1) + end + + context 'when no merge requests will close issue' do + it 'returns empty array' do + get api("/projects/#{project.id}/issues/#{closed_issue.iid}/closed_by", user) + + expect_paginated_array_response(size: 0) + end + end + + it "returns 404 when issue doesn't exists" do + get api("/projects/#{project.id}/issues/9999/closed_by", user) + + expect(response).to have_http_status(404) + end + end + def expect_paginated_array_response(size: nil) expect(response).to have_http_status(200) expect(response).to include_pagination_headers -- cgit v1.2.1