diff --git a/changelogs/unreleased/53861-api-promote-project-milestone-to-a-group-milestone.yml b/changelogs/unreleased/53861-api-promote-project-milestone-to-a-group-milestone.yml new file mode 100644 index 00000000000..6c621763e2e --- /dev/null +++ b/changelogs/unreleased/53861-api-promote-project-milestone-to-a-group-milestone.yml @@ -0,0 +1,5 @@ +--- +title: 'API: Promote project milestone to a group milestone' +merge_request: 25203 +author: Nermin Vehabovic +type: added diff --git a/doc/api/milestones.md b/doc/api/milestones.md index fa8f8a0bcf0..897184d51af 100644 --- a/doc/api/milestones.md +++ b/doc/api/milestones.md @@ -130,3 +130,18 @@ Parameters: - `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user - `milestone_id` (required) - The ID of a project milestone + +## Promote project milestone to a group milestone + +> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/53861) in GitLab 11.9 + +Only for users with developer access to the group. + +``` +POST /projects/:id/milestones/:milestone_id/promote +``` + +Parameters: + +- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user +- `milestone_id` (required) - The ID of a project milestone diff --git a/lib/api/project_milestones.rb b/lib/api/project_milestones.rb index da31bcb8dac..ca24742b7a3 100644 --- a/lib/api/project_milestones.rb +++ b/lib/api/project_milestones.rb @@ -98,6 +98,23 @@ module API milestone_issuables_for(user_project, :merge_request) end + + desc 'Promote a milestone to group milestone' do + detail 'This feature was introduced in GitLab 11.9' + end + post ':id/milestones/:milestone_id/promote' do + begin + authorize! :admin_milestone, user_project + authorize! :admin_milestone, user_project.group + + milestone = user_project.milestones.find(params[:milestone_id]) + Milestones::PromoteService.new(user_project, current_user).execute(milestone) + + status(200) + rescue Milestones::PromoteService::PromoteMilestoneError => error + render_api_error!(error.message, 400) + end + end end end end diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb index 1a4be2bd30f..01bab2a1361 100644 --- a/spec/requests/api/issues_spec.rb +++ b/spec/requests/api/issues_spec.rb @@ -366,7 +366,7 @@ describe API::Issues do end it 'returns an empty array if iid does not exist' do - get api("/issues", user), params: { iids: [99999] } + get api("/issues", user), params: { iids: [0] } expect_paginated_array_response([]) end @@ -627,7 +627,7 @@ describe API::Issues do end it 'returns an empty array if iid does not exist' do - get api(base_url, user), params: { iids: [99999] } + get api(base_url, user), params: { iids: [0] } expect_paginated_array_response([]) end @@ -873,7 +873,7 @@ describe API::Issues do end it 'returns an empty array if iid does not exist' do - get api("#{base_url}/issues", user), params: { iids: [99999] } + get api("#{base_url}/issues", user), params: { iids: [0] } expect_paginated_array_response([]) end @@ -1909,7 +1909,7 @@ describe API::Issues do end it "returns 404 when issue doesn't exists" do - get api("/projects/#{project.id}/issues/9999/closed_by", user) + get api("/projects/#{project.id}/issues/0/closed_by", user) expect(response).to have_gitlab_http_status(404) end @@ -1994,7 +1994,7 @@ describe API::Issues do end it "returns 404 when issue doesn't exists" do - get_related_merge_requests(project.id, 999999, user) + get_related_merge_requests(project.id, 0, user) expect(response).to have_gitlab_http_status(404) end diff --git a/spec/requests/api/keys_spec.rb b/spec/requests/api/keys_spec.rb index 3c4719964b6..f37d84fddef 100644 --- a/spec/requests/api/keys_spec.rb +++ b/spec/requests/api/keys_spec.rb @@ -16,7 +16,7 @@ describe API::Keys do context 'when authenticated' do it 'returns 404 for non-existing key' do - get api('/keys/999999', admin) + get api('/keys/0', admin) expect(response).to have_gitlab_http_status(404) expect(json_response['message']).to eq('404 Not found') end diff --git a/spec/requests/api/merge_request_diffs_spec.rb b/spec/requests/api/merge_request_diffs_spec.rb index 6530dc956cb..8a67d98fc4c 100644 --- a/spec/requests/api/merge_request_diffs_spec.rb +++ b/spec/requests/api/merge_request_diffs_spec.rb @@ -30,7 +30,7 @@ describe API::MergeRequestDiffs, 'MergeRequestDiffs' do end it 'returns a 404 when merge_request_iid not found' do - get api("/projects/#{project.id}/merge_requests/999/versions", user) + get api("/projects/#{project.id}/merge_requests/0/versions", user) expect(response).to have_gitlab_http_status(404) end end @@ -53,7 +53,7 @@ describe API::MergeRequestDiffs, 'MergeRequestDiffs' do end it 'returns a 404 when merge_request version_id is not found' do - get api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/versions/999", user) + get api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/versions/0", user) expect(response).to have_gitlab_http_status(404) end diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb index b4cd3130dc5..db56739af2f 100644 --- a/spec/requests/api/merge_requests_spec.rb +++ b/spec/requests/api/merge_requests_spec.rb @@ -441,7 +441,7 @@ describe API::MergeRequests do end it "returns a 404 error if merge_request_iid not found" do - get api("/projects/#{project.id}/merge_requests/999", user) + get api("/projects/#{project.id}/merge_requests/0", user) expect(response).to have_gitlab_http_status(404) end @@ -531,7 +531,7 @@ describe API::MergeRequests do end it 'returns a 404 when merge_request_iid not found' do - get api("/projects/#{project.id}/merge_requests/999/commits", user) + get api("/projects/#{project.id}/merge_requests/0/commits", user) expect(response).to have_gitlab_http_status(404) end @@ -551,7 +551,7 @@ describe API::MergeRequests do end it 'returns a 404 when merge_request_iid not found' do - get api("/projects/#{project.id}/merge_requests/999/changes", user) + get api("/projects/#{project.id}/merge_requests/0/changes", user) expect(response).to have_gitlab_http_status(404) end diff --git a/spec/requests/api/namespaces_spec.rb b/spec/requests/api/namespaces_spec.rb index 145356c4df5..2e376109b42 100644 --- a/spec/requests/api/namespaces_spec.rb +++ b/spec/requests/api/namespaces_spec.rb @@ -149,7 +149,7 @@ describe API::Namespaces do context "when namespace doesn't exist" do it 'returns not-found' do - get api('/namespaces/9999', request_actor) + get api('/namespaces/0', request_actor) expect(response).to have_gitlab_http_status(404) end diff --git a/spec/requests/api/project_milestones_spec.rb b/spec/requests/api/project_milestones_spec.rb index 49b5dfb0b33..895f05a98e8 100644 --- a/spec/requests/api/project_milestones_spec.rb +++ b/spec/requests/api/project_milestones_spec.rb @@ -23,13 +23,13 @@ describe API::ProjectMilestones do end it 'returns 404 response when the project does not exists' do - delete api("/projects/999/milestones/#{milestone.id}", user) + delete api("/projects/0/milestones/#{milestone.id}", user) expect(response).to have_gitlab_http_status(404) end it 'returns 404 response when the milestone does not exists' do - delete api("/projects/#{project.id}/milestones/999", user) + delete api("/projects/#{project.id}/milestones/0", user) expect(response).to have_gitlab_http_status(404) end @@ -49,4 +49,74 @@ describe API::ProjectMilestones do params: { state_event: 'close' } end end + + describe 'POST /projects/:id/milestones/:milestone_id/promote' do + let(:group) { create(:group) } + + before do + project.update(namespace: group) + end + + context 'when user does not have permission to promote milestone' do + before do + group.add_guest(user) + end + + it 'returns 403' do + post api("/projects/#{project.id}/milestones/#{milestone.id}/promote", user) + + expect(response).to have_gitlab_http_status(403) + end + end + + context 'when user has permission' do + before do + group.add_developer(user) + end + + it 'returns 200' do + post api("/projects/#{project.id}/milestones/#{milestone.id}/promote", user) + + expect(response).to have_gitlab_http_status(200) + expect(group.milestones.first.title).to eq(milestone.title) + end + + it 'returns 200 for closed milestone' do + post api("/projects/#{project.id}/milestones/#{closed_milestone.id}/promote", user) + + expect(response).to have_gitlab_http_status(200) + expect(group.milestones.first.title).to eq(closed_milestone.title) + end + end + + context 'when no such resources' do + before do + group.add_developer(user) + end + + it 'returns 404 response when the project does not exist' do + post api("/projects/0/milestones/#{milestone.id}/promote", user) + + expect(response).to have_gitlab_http_status(404) + end + + it 'returns 404 response when the milestone does not exist' do + post api("/projects/#{project.id}/milestones/0/promote", user) + + expect(response).to have_gitlab_http_status(404) + end + end + + context 'when project does not belong to group' do + before do + project.update(namespace: user.namespace) + end + + it 'returns 403' do + post api("/projects/#{project.id}/milestones/#{milestone.id}/promote", user) + + expect(response).to have_gitlab_http_status(403) + end + end + end end diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 792abdb2972..856fe1bbe89 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -778,7 +778,7 @@ describe API::Projects do let!(:public_project) { create(:project, :public, name: 'public_project', creator_id: user4.id, namespace: user4.namespace) } it 'returns error when user not found' do - get api('/users/9999/projects/') + get api('/users/0/projects/') expect(response).to have_gitlab_http_status(404) expect(json_response['message']).to eq('404 User Not Found') @@ -1385,7 +1385,7 @@ describe API::Projects do end it 'fails if forked_from project which does not exist' do - post api("/projects/#{project_fork_target.id}/fork/9999", admin) + post api("/projects/#{project_fork_target.id}/fork/0", admin) expect(response).to have_gitlab_http_status(404) end @@ -1936,7 +1936,7 @@ describe API::Projects do end it 'returns not_found(404) for not existing project' do - get api("/projects/9999999999/languages", user) + get api("/projects/0/languages", user) expect(response).to have_gitlab_http_status(:not_found) end diff --git a/spec/requests/api/runners_spec.rb b/spec/requests/api/runners_spec.rb index 7f11c8c9fe8..5ca442bc448 100644 --- a/spec/requests/api/runners_spec.rb +++ b/spec/requests/api/runners_spec.rb @@ -241,7 +241,7 @@ describe API::Runners do end it 'returns 404 if runner does not exists' do - get api('/runners/9999', admin) + get api('/runners/0', admin) expect(response).to have_gitlab_http_status(404) end @@ -394,7 +394,7 @@ describe API::Runners do end it 'returns 404 if runner does not exists' do - update_runner(9999, admin, description: 'test') + update_runner(0, admin, description: 'test') expect(response).to have_gitlab_http_status(404) end @@ -468,7 +468,7 @@ describe API::Runners do end it 'returns 404 if runner does not exists' do - delete api('/runners/9999', admin) + delete api('/runners/0', admin) expect(response).to have_gitlab_http_status(404) end @@ -573,7 +573,7 @@ describe API::Runners do context "when runner doesn't exist" do it 'returns 404' do - get api('/runners/9999/jobs', admin) + get api('/runners/0/jobs', admin) expect(response).to have_gitlab_http_status(404) end @@ -626,7 +626,7 @@ describe API::Runners do context "when runner doesn't exist" do it 'returns 404' do - get api('/runners/9999/jobs', user) + get api('/runners/0/jobs', user) expect(response).to have_gitlab_http_status(404) end @@ -857,7 +857,7 @@ describe API::Runners do end it 'returns 404 is runner is not found' do - delete api("/projects/#{project.id}/runners/9999", user) + delete api("/projects/#{project.id}/runners/0", user) expect(response).to have_gitlab_http_status(404) end diff --git a/spec/requests/api/search_spec.rb b/spec/requests/api/search_spec.rb index 831f47debeb..c48ca832c85 100644 --- a/spec/requests/api/search_spec.rb +++ b/spec/requests/api/search_spec.rb @@ -126,7 +126,7 @@ describe API::Search do context 'when group does not exist' do it 'returns 404 error' do - get api('/groups/9999/search', user), params: { scope: 'issues', search: 'awesome' } + get api('/groups/0/search', user), params: { scope: 'issues', search: 'awesome' } expect(response).to have_gitlab_http_status(404) end @@ -222,7 +222,7 @@ describe API::Search do context 'when project does not exist' do it 'returns 404 error' do - get api('/projects/9999/search', user), params: { scope: 'issues', search: 'awesome' } + get api('/projects/0/search', user), params: { scope: 'issues', search: 'awesome' } expect(response).to have_gitlab_http_status(404) end diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb index b381431306d..a879426589d 100644 --- a/spec/requests/api/users_spec.rb +++ b/spec/requests/api/users_spec.rb @@ -335,7 +335,7 @@ describe API::Users do end it "returns a 404 error if user id not found" do - get api("/users/9999", user) + get api("/users/0", user) expect(response).to have_gitlab_http_status(404) expect(json_response['message']).to eq('404 User Not Found') @@ -732,7 +732,7 @@ describe API::Users do end it "returns 404 for non-existing user" do - put api("/users/999999", admin), params: { bio: 'update should fail' } + put api("/users/0", admin), params: { bio: 'update should fail' } expect(response).to have_gitlab_http_status(404) expect(json_response['message']).to eq('404 User Not Found') @@ -836,7 +836,7 @@ describe API::Users do end it "returns 400 for invalid ID" do - post api("/users/999999/keys", admin) + post api("/users/0/keys", admin) expect(response).to have_gitlab_http_status(400) end end @@ -895,7 +895,7 @@ describe API::Users do it 'returns 404 error if user not found' do user.keys << key user.save - delete api("/users/999999/keys/#{key.id}", admin) + delete api("/users/0/keys/#{key.id}", admin) expect(response).to have_gitlab_http_status(404) expect(json_response['message']).to eq('404 User Not Found') end @@ -930,7 +930,7 @@ describe API::Users do end it 'returns 400 for invalid ID' do - post api('/users/999999/gpg_keys', admin) + post api('/users/0/gpg_keys', admin) expect(response).to have_gitlab_http_status(400) end @@ -951,7 +951,7 @@ describe API::Users do context 'when authenticated' do it 'returns 404 for non-existing user' do - get api('/users/999999/gpg_keys', admin) + get api('/users/0/gpg_keys', admin) expect(response).to have_gitlab_http_status(404) expect(json_response['message']).to eq('404 User Not Found') @@ -1007,7 +1007,7 @@ describe API::Users do user.keys << key user.save - delete api("/users/999999/gpg_keys/#{gpg_key.id}", admin) + delete api("/users/0/gpg_keys/#{gpg_key.id}", admin) expect(response).to have_gitlab_http_status(404) expect(json_response['message']).to eq('404 User Not Found') @@ -1051,7 +1051,7 @@ describe API::Users do user.gpg_keys << gpg_key user.save - post api("/users/999999/gpg_keys/#{gpg_key.id}/revoke", admin) + post api("/users/0/gpg_keys/#{gpg_key.id}/revoke", admin) expect(response).to have_gitlab_http_status(404) expect(json_response['message']).to eq('404 User Not Found') @@ -1089,7 +1089,7 @@ describe API::Users do end it "returns a 400 for invalid ID" do - post api("/users/999999/emails", admin) + post api("/users/0/emails", admin) expect(response).to have_gitlab_http_status(400) end @@ -1121,7 +1121,7 @@ describe API::Users do context 'when authenticated' do it 'returns 404 for non-existing user' do - get api('/users/999999/emails', admin) + get api('/users/0/emails', admin) expect(response).to have_gitlab_http_status(404) expect(json_response['message']).to eq('404 User Not Found') end @@ -1177,7 +1177,7 @@ describe API::Users do it 'returns 404 error if user not found' do user.emails << email user.save - delete api("/users/999999/emails/#{email.id}", admin) + delete api("/users/0/emails/#{email.id}", admin) expect(response).to have_gitlab_http_status(404) expect(json_response['message']).to eq('404 User Not Found') end @@ -1227,7 +1227,7 @@ describe API::Users do end it "returns 404 for non-existing user" do - perform_enqueued_jobs { delete api("/users/999999", admin) } + perform_enqueued_jobs { delete api("/users/0", admin) } expect(response).to have_gitlab_http_status(404) expect(json_response['message']).to eq('404 User Not Found') end @@ -1778,7 +1778,7 @@ describe API::Users do end it 'returns a 404 error if user id not found' do - post api('/users/9999/block', admin) + post api('/users/0/block', admin) expect(response).to have_gitlab_http_status(404) expect(json_response['message']).to eq('404 User Not Found') end @@ -1816,7 +1816,7 @@ describe API::Users do end it 'returns a 404 error if user id not found' do - post api('/users/9999/block', admin) + post api('/users/0/block', admin) expect(response).to have_gitlab_http_status(404) expect(json_response['message']).to eq('404 User Not Found') end