Commit 59a59439 authored by Mayra Cabrera's avatar Mayra Cabrera

Merge branch 'id-refactor-handle-merge-request-errors' into 'master'

Refactor handle_merge_request_errors! method

See merge request gitlab-org/gitlab!36600
parents 1caef3c3 850d87cf
...@@ -8,6 +8,8 @@ module EE ...@@ -8,6 +8,8 @@ module EE
prepended do prepended do
before { authenticate_non_get! } before { authenticate_non_get! }
helpers ::API::Helpers::MergeRequestsHelpers
helpers do helpers do
params :ee_approval_params do params :ee_approval_params do
optional :approval_password, type: String, desc: 'Current user\'s password if project is set to require explicit auth on approval' optional :approval_password, type: String, desc: 'Current user\'s password if project is set to require explicit auth on approval'
...@@ -17,22 +19,6 @@ module EE ...@@ -17,22 +19,6 @@ module EE
present merge_request.approval_state, with: ::EE::API::Entities::ApprovalState, current_user: current_user present merge_request.approval_state, with: ::EE::API::Entities::ApprovalState, current_user: current_user
end end
def handle_merge_request_errors!(errors)
if errors.has_key? :project_access
error!(errors[:project_access], 422)
elsif errors.has_key? :branch_conflict
error!(errors[:branch_conflict], 422)
elsif errors.has_key? :validate_fork
error!(errors[:validate_fork], 422)
elsif errors.has_key? :validate_branches
conflict!(errors[:validate_branches])
elsif errors.has_key? :base
error!(errors[:base], 422)
end
render_api_error!(errors, 400)
end
def present_merge_request_approval_state(presenter:, target_branch: nil) def present_merge_request_approval_state(presenter:, target_branch: nil)
merge_request = find_merge_request_with_access(params[:merge_request_iid]) merge_request = find_merge_request_with_access(params[:merge_request_iid])
...@@ -71,6 +57,7 @@ module EE ...@@ -71,6 +57,7 @@ module EE
present_merge_request_approval_state(presenter: ::EE::API::Entities::MergeRequestApprovalState) present_merge_request_approval_state(presenter: ::EE::API::Entities::MergeRequestApprovalState)
end end
# Deprecated in favor of approval rules API
desc 'Change approval-related configuration' do desc 'Change approval-related configuration' do
detail 'This feature was introduced in 10.6' detail 'This feature was introduced in 10.6'
success ::EE::API::Entities::ApprovalState success ::EE::API::Entities::ApprovalState
...@@ -85,13 +72,13 @@ module EE ...@@ -85,13 +72,13 @@ module EE
merge_request = ::MergeRequests::UpdateService.new(user_project, current_user, approvals_before_merge: params[:approvals_required]).execute(merge_request) merge_request = ::MergeRequests::UpdateService.new(user_project, current_user, approvals_before_merge: params[:approvals_required]).execute(merge_request)
if merge_request.valid? # Merge request shouldn't be in an invalid state after the changes, but handling errors to be safe
present_approval(merge_request) handle_merge_request_errors!(merge_request)
else
handle_merge_request_errors! merge_request.errors present_approval(merge_request)
end
end end
# Deprecated in favor of approval rules API
desc 'Update approvers and approver groups' do desc 'Update approvers and approver groups' do
detail 'This feature was introduced in 10.6' detail 'This feature was introduced in 10.6'
success ::EE::API::Entities::ApprovalState success ::EE::API::Entities::ApprovalState
...@@ -109,11 +96,10 @@ module EE ...@@ -109,11 +96,10 @@ module EE
merge_request = ::MergeRequests::UpdateService.new(user_project, current_user, declared(params, include_parent_namespaces: false).merge(remove_old_approvers: true)).execute(merge_request) merge_request = ::MergeRequests::UpdateService.new(user_project, current_user, declared(params, include_parent_namespaces: false).merge(remove_old_approvers: true)).execute(merge_request)
if merge_request.valid? # Merge request shouldn't be in an invalid state after the changes, but handling errors to be safe
present_approval(merge_request) handle_merge_request_errors!(merge_request)
else
handle_merge_request_errors! merge_request.errors present_approval(merge_request)
end
end end
end end
end end
......
...@@ -404,6 +404,10 @@ module API ...@@ -404,6 +404,10 @@ module API
render_api_error!(message || '409 Conflict', 409) render_api_error!(message || '409 Conflict', 409)
end end
def unprocessable_entity!(message = nil)
render_api_error!(message || '422 Unprocessable Entity', :unprocessable_entity)
end
def file_too_large! def file_too_large!
render_api_error!('413 Request Entity Too Large', 413) render_api_error!('413 Request Entity Too Large', 413)
end end
......
...@@ -4,6 +4,9 @@ module API ...@@ -4,6 +4,9 @@ module API
module Helpers module Helpers
module MergeRequestsHelpers module MergeRequestsHelpers
extend Grape::API::Helpers extend Grape::API::Helpers
extend ActiveSupport::Concern
UNPROCESSABLE_ERROR_KEYS = [:project_access, :branch_conflict, :validate_fork, :base].freeze
params :merge_requests_negatable_params do params :merge_requests_negatable_params do
optional :author_id, type: Integer, desc: 'Return merge requests which are authored by the user with the given ID' optional :author_id, type: Integer, desc: 'Return merge requests which are authored by the user with the given ID'
...@@ -79,6 +82,20 @@ module API ...@@ -79,6 +82,20 @@ module API
default: 'created_by_me', default: 'created_by_me',
desc: 'Return merge requests for the given scope: `created_by_me`, `assigned_to_me` or `all`' desc: 'Return merge requests for the given scope: `created_by_me`, `assigned_to_me` or `all`'
end end
def handle_merge_request_errors!(merge_request)
return if merge_request.valid?
errors = merge_request.errors
UNPROCESSABLE_ERROR_KEYS.each do |error|
unprocessable_entity!(errors[error]) if errors.has_key?(error)
end
conflict!(errors[:validate_branches]) if errors.has_key?(:validate_branches)
render_validation_error!(merge_request)
end
end end
end end
end end
...@@ -153,22 +153,6 @@ module API ...@@ -153,22 +153,6 @@ module API
include TimeTrackingEndpoints include TimeTrackingEndpoints
helpers do helpers do
def handle_merge_request_errors!(errors)
if errors[:project_access].any?
error!(errors[:project_access], 422)
elsif errors[:branch_conflict].any?
error!(errors[:branch_conflict], 422)
elsif errors[:validate_fork].any?
error!(errors[:validate_fork], 422)
elsif errors[:validate_branches].any?
conflict!(errors[:validate_branches])
elsif errors[:base].any?
error!(errors[:base], 422)
end
render_api_error!(errors, 400)
end
params :optional_params do params :optional_params do
optional :description, type: String, desc: 'The description of the merge request' optional :description, type: String, desc: 'The description of the merge request'
optional :assignee_id, type: Integer, desc: 'The ID of a user to assign the merge request' optional :assignee_id, type: Integer, desc: 'The ID of a user to assign the merge request'
...@@ -226,11 +210,9 @@ module API ...@@ -226,11 +210,9 @@ module API
merge_request = ::MergeRequests::CreateService.new(user_project, current_user, mr_params).execute merge_request = ::MergeRequests::CreateService.new(user_project, current_user, mr_params).execute
if merge_request.valid? handle_merge_request_errors!(merge_request)
present merge_request, with: Entities::MergeRequest, current_user: current_user, project: user_project
else present merge_request, with: Entities::MergeRequest, current_user: current_user, project: user_project
handle_merge_request_errors! merge_request.errors
end
end end
desc 'Delete a merge request' desc 'Delete a merge request'
...@@ -420,11 +402,9 @@ module API ...@@ -420,11 +402,9 @@ module API
merge_request = ::MergeRequests::UpdateService.new(user_project, current_user, mr_params).execute(merge_request) merge_request = ::MergeRequests::UpdateService.new(user_project, current_user, mr_params).execute(merge_request)
if merge_request.valid? handle_merge_request_errors!(merge_request)
present merge_request, with: Entities::MergeRequest, current_user: current_user, project: user_project
else present merge_request, with: Entities::MergeRequest, current_user: current_user, project: user_project
handle_merge_request_errors! merge_request.errors
end
end end
desc 'Merge a merge request' do desc 'Merge a merge request' do
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe API::Helpers::MergeRequestsHelpers do
describe '#handle_merge_request_errors!' do
let(:helper) do
Class.new do
include API::Helpers::MergeRequestsHelpers
end.new
end
let(:merge_request) { double }
context 'when merge request is valid' do
it 'returns nil' do
allow(merge_request).to receive(:valid?).and_return(true)
expect(merge_request).not_to receive(:errors)
helper.handle_merge_request_errors!(merge_request)
end
end
context 'when merge request is invalid' do
before do
allow(merge_request).to receive(:valid?).and_return(false)
allow(helper).to receive_messages([
:unprocessable_entity!, :conflict!, :render_validation_error!
])
end
API::Helpers::MergeRequestsHelpers::UNPROCESSABLE_ERROR_KEYS.each do |error_key|
it "responds to a #{error_key} error with unprocessable_entity" do
error = double
allow(merge_request).to receive(:errors).and_return({ error_key => error })
expect(helper).to receive(:unprocessable_entity!).with(error)
helper.handle_merge_request_errors!(merge_request)
end
end
it 'responds to a validate_branches error with conflict' do
error = double
allow(merge_request).to receive(:errors).and_return({ validate_branches: error })
expect(helper).to receive(:conflict!).with(error)
helper.handle_merge_request_errors!(merge_request)
end
it 'responds with bad request' do
error = double
allow(merge_request).to receive(:errors).and_return({ other_error: error })
expect(helper).to receive(:render_validation_error!).with(merge_request)
helper.handle_merge_request_errors!(merge_request)
end
end
end
end
...@@ -1551,25 +1551,33 @@ RSpec.describe API::MergeRequests do ...@@ -1551,25 +1551,33 @@ RSpec.describe API::MergeRequests do
it "returns 422 when source_branch equals target_branch" do it "returns 422 when source_branch equals target_branch" do
post api("/projects/#{project.id}/merge_requests", user), post api("/projects/#{project.id}/merge_requests", user),
params: { title: "Test merge_request", source_branch: "master", target_branch: "master", author: user } params: { title: "Test merge_request", source_branch: "master", target_branch: "master", author: user }
expect(response).to have_gitlab_http_status(:unprocessable_entity) expect(response).to have_gitlab_http_status(:unprocessable_entity)
expect(json_response['message']).to eq(["You can't use same project/branch for source and target"])
end end
it "returns 400 when source_branch is missing" do it "returns 400 when source_branch is missing" do
post api("/projects/#{project.id}/merge_requests", user), post api("/projects/#{project.id}/merge_requests", user),
params: { title: "Test merge_request", target_branch: "master", author: user } params: { title: "Test merge_request", target_branch: "master", author: user }
expect(response).to have_gitlab_http_status(:bad_request) expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['error']).to eq('source_branch is missing')
end end
it "returns 400 when target_branch is missing" do it "returns 400 when target_branch is missing" do
post api("/projects/#{project.id}/merge_requests", user), post api("/projects/#{project.id}/merge_requests", user),
params: { title: "Test merge_request", source_branch: "markdown", author: user } params: { title: "Test merge_request", source_branch: "markdown", author: user }
expect(response).to have_gitlab_http_status(:bad_request) expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['error']).to eq('target_branch is missing')
end end
it "returns 400 when title is missing" do it "returns 400 when title is missing" do
post api("/projects/#{project.id}/merge_requests", user), post api("/projects/#{project.id}/merge_requests", user),
params: { target_branch: 'master', source_branch: 'markdown' } params: { target_branch: 'master', source_branch: 'markdown' }
expect(response).to have_gitlab_http_status(:bad_request) expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['error']).to eq('title is missing')
end end
context 'with existing MR' do context 'with existing MR' do
...@@ -1594,7 +1602,9 @@ RSpec.describe API::MergeRequests do ...@@ -1594,7 +1602,9 @@ RSpec.describe API::MergeRequests do
author: user author: user
} }
end.to change { MergeRequest.count }.by(0) end.to change { MergeRequest.count }.by(0)
expect(response).to have_gitlab_http_status(:conflict) expect(response).to have_gitlab_http_status(:conflict)
expect(json_response['message']).to eq(["Another open merge request already exists for this source branch: !5"])
end end
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment