Commit 92f5a5fd authored by Douwe Maan's avatar Douwe Maan

Merge branch '3142-fix-merge-request-approvals-validation-error' into 'master'

fix the approvals_before_merge project fallback

Closes #3142

See merge request gitlab-org/gitlab-ee!2932
parents 82d65226 f2f8de61
---
title: Fix a merge request validation error on forked projects.
merge_request: 2932
author:
type: fixed
...@@ -36,8 +36,15 @@ module EE ...@@ -36,8 +36,15 @@ module EE
def clamp_approvals_before_merge(mr_params) def clamp_approvals_before_merge(mr_params)
return mr_params unless mr_params[:approvals_before_merge] return mr_params unless mr_params[:approvals_before_merge]
target_project = @project.forked_from_project if @project.id.to_s != mr_params[:target_project_id] # Target the MR target project in priority, else it depends whether the project
target_project ||= @project # is forked.
target_project = if @merge_request
@merge_request.target_project
elsif @project.forked? && @project.id.to_s != mr_params[:target_project_id]
@project.forked_from_project
else
@project
end
if mr_params[:approvals_before_merge].to_i <= target_project.approvals_before_merge if mr_params[:approvals_before_merge].to_i <= target_project.approvals_before_merge
mr_params[:approvals_before_merge] = nil mr_params[:approvals_before_merge] = nil
......
require 'spec_helper' require 'spec_helper'
describe Projects::MergeRequestsController do shared_examples 'approvals' do
let(:project) { create(:project, :repository) } def json_response
let(:merge_request) { create(:merge_request_with_diffs, target_project: project, source_project: project) } JSON.parse(response.body)
let(:user) { project.owner } end
let(:viewer) { user }
let!(:approver) { create(:approver, target: project) }
let!(:user_approver) { create(:approver, target: project, user: user) }
before do before do
sign_in(viewer) merge_request.update_attribute :approvals_before_merge, 2
project.team << [approver.user, :developer]
end end
context 'approvals' do describe 'approve' do
def json_response before do
JSON.parse(response.body) post :approve,
namespace_id: project.namespace.to_param,
project_id: project.to_param,
id: merge_request.iid,
format: :json
end end
let(:approver) { create(:user) } it 'approves the merge request' do
approvals = json_response
before do
merge_request.update_attribute :approvals_before_merge, 2 expect(response).to be_success
project.team << [approver, :developer] expect(approvals['approvals_left']).to eq 1
project.approver_ids = [user, approver].map(&:id).join(',') expect(approvals['approved_by'].size).to eq 1
expect(approvals['approved_by'][0]['user']['username']).to eq user.username
expect(approvals['user_has_approved']).to be true
expect(approvals['user_can_approve']).to be false
expect(approvals['suggested_approvers'].size).to eq 1
expect(approvals['suggested_approvers'][0]['username']).to eq approver.user.username
end end
end
describe 'approve' do describe 'approvals' do
before do let!(:approval) { create(:approval, merge_request: merge_request, user: approver.user) }
post :approve,
before do
get :approvals,
namespace_id: project.namespace.to_param, namespace_id: project.namespace.to_param,
project_id: project.to_param, project_id: project.to_param,
id: merge_request.iid, id: merge_request.iid,
format: :json format: :json
end end
it 'approves the merge request' do it 'shows approval information' do
expect(response).to be_success approvals = json_response
expect(json_response['approvals_left']).to eq 1
expect(json_response['approved_by'].size).to eq 1 expect(response).to be_success
expect(json_response['approved_by'][0]['user']['username']).to eq user.username expect(approvals['approvals_left']).to eq 1
expect(json_response['user_has_approved']).to be true expect(approvals['approved_by'].size).to eq 1
expect(json_response['user_can_approve']).to be false expect(approvals['approved_by'][0]['user']['username']).to eq approver.user.username
expect(json_response['suggested_approvers'].size).to eq 1 expect(approvals['user_has_approved']).to be false
expect(json_response['suggested_approvers'][0]['username']).to eq approver.username expect(approvals['user_can_approve']).to be true
end expect(approvals['suggested_approvers'].size).to eq 1
expect(approvals['suggested_approvers'][0]['username']).to eq user.username
end end
end
describe 'approvals' do describe 'unapprove' do
before do let!(:approval) { create(:approval, merge_request: merge_request, user: user) }
merge_request.approvals.create(user: approver)
get :approvals,
namespace_id: project.namespace.to_param,
project_id: project.to_param,
id: merge_request.iid,
format: :json
end
it 'shows approval information' do before do
expect(response).to be_success delete :unapprove,
expect(json_response['approvals_left']).to eq 1 namespace_id: project.namespace.to_param,
expect(json_response['approved_by'].size).to eq 1 project_id: project.to_param,
expect(json_response['approved_by'][0]['user']['username']).to eq approver.username id: merge_request.iid,
expect(json_response['user_has_approved']).to be false format: :json
expect(json_response['user_can_approve']).to be true
expect(json_response['suggested_approvers'].size).to eq 1
expect(json_response['suggested_approvers'][0]['username']).to eq user.username
end
end end
describe 'unapprove' do it 'unapproves the merge request' do
before do approvals = json_response
merge_request.approvals.create(user: user)
delete :unapprove,
namespace_id: project.namespace.to_param,
project_id: project.to_param,
id: merge_request.iid,
format: :json
end
it 'unapproves the merge request' do expect(response).to be_success
expect(response).to be_success expect(approvals['approvals_left']).to eq 2
expect(json_response['approvals_left']).to eq 2 expect(approvals['approved_by']).to be_empty
expect(json_response['approved_by']).to be_empty expect(approvals['user_has_approved']).to be false
expect(json_response['user_has_approved']).to be false expect(approvals['user_can_approve']).to be true
expect(json_response['user_can_approve']).to be true expect(approvals['suggested_approvers'].size).to eq 2
expect(json_response['suggested_approvers'].size).to eq 2
end
end end
end end
end
describe Projects::MergeRequestsController do
let(:project) { create(:project, :repository) }
let(:merge_request) { create(:merge_request_with_diffs, target_project: project, source_project: project) }
let(:user) { project.owner }
let(:viewer) { user }
before do
sign_in(viewer)
end
it_behaves_like 'approvals'
describe 'PUT update' do describe 'PUT update' do
before do
project.update_attributes(approvals_before_merge: 2)
end
def update_merge_request(params = {}) def update_merge_request(params = {})
post :update, post :update,
namespace_id: project.namespace.to_param, namespace_id: merge_request.target_project.namespace.to_param,
project_id: project.to_param, project_id: merge_request.target_project.to_param,
id: merge_request.iid, id: merge_request.iid,
merge_request: params merge_request: params
end end
...@@ -126,7 +140,7 @@ describe Projects::MergeRequestsController do ...@@ -126,7 +140,7 @@ describe Projects::MergeRequestsController do
let(:new_approver_group) { create(:approver_group) } let(:new_approver_group) { create(:approver_group) }
before do before do
project.team << [new_approver, :developer] project.add_developer(new_approver)
project.update_attributes(disable_overriding_approvers_per_merge_request: true) project.update_attributes(disable_overriding_approvers_per_merge_request: true)
end end
...@@ -150,7 +164,7 @@ describe Projects::MergeRequestsController do ...@@ -150,7 +164,7 @@ describe Projects::MergeRequestsController do
end end
end end
context 'the approvals_before_merge param' do shared_examples 'approvals_before_merge param' do
before do before do
project.update_attributes(approvals_before_merge: 2) project.update_attributes(approvals_before_merge: 2)
end end
...@@ -162,12 +176,12 @@ describe Projects::MergeRequestsController do ...@@ -162,12 +176,12 @@ describe Projects::MergeRequestsController do
end end
it 'sets the param to nil' do it 'sets the param to nil' do
expect(merge_request.reload.approvals_before_merge).to eq(nil) expect(merge_request.approvals_before_merge).to eq(nil)
end end
it 'updates the merge request' do it 'updates the merge request' do
expect(merge_request.reload).to be_valid expect(merge_request).to be_valid
expect(response).to redirect_to(project_merge_request_path(project, merge_request)) expect(response).to redirect_to(project_merge_request_path(merge_request.target_project, merge_request))
end end
end end
...@@ -182,7 +196,7 @@ describe Projects::MergeRequestsController do ...@@ -182,7 +196,7 @@ describe Projects::MergeRequestsController do
it 'updates the merge request' do it 'updates the merge request' do
expect(merge_request.reload).to be_valid expect(merge_request.reload).to be_valid
expect(response).to redirect_to(project_merge_request_path(project, merge_request)) expect(response).to redirect_to(project_merge_request_path(merge_request.target_project, merge_request))
end end
end end
...@@ -197,7 +211,7 @@ describe Projects::MergeRequestsController do ...@@ -197,7 +211,7 @@ describe Projects::MergeRequestsController do
it 'updates the merge request' do it 'updates the merge request' do
expect(merge_request.reload).to be_valid expect(merge_request.reload).to be_valid
expect(response).to redirect_to(project_merge_request_path(project, merge_request)) expect(response).to redirect_to(project_merge_request_path(merge_request.target_project, merge_request))
end end
end end
end end
...@@ -218,7 +232,7 @@ describe Projects::MergeRequestsController do ...@@ -218,7 +232,7 @@ describe Projects::MergeRequestsController do
it 'updates the merge request' do it 'updates the merge request' do
expect(merge_request.reload).to be_valid expect(merge_request.reload).to be_valid
expect(response).to redirect_to(project_merge_request_path(project, merge_request)) expect(response).to redirect_to(project_merge_request_path(merge_request.target_project, merge_request))
end end
end end
...@@ -233,7 +247,7 @@ describe Projects::MergeRequestsController do ...@@ -233,7 +247,7 @@ describe Projects::MergeRequestsController do
it 'updates the merge request' do it 'updates the merge request' do
expect(merge_request.reload).to be_valid expect(merge_request.reload).to be_valid
expect(response).to redirect_to(project_merge_request_path(project, merge_request)) expect(response).to redirect_to(project_merge_request_path(merge_request.target_project, merge_request))
end end
end end
...@@ -248,7 +262,7 @@ describe Projects::MergeRequestsController do ...@@ -248,7 +262,7 @@ describe Projects::MergeRequestsController do
it 'updates the merge request' do it 'updates the merge request' do
expect(merge_request.reload).to be_valid expect(merge_request.reload).to be_valid
expect(response).to redirect_to(project_merge_request_path(project, merge_request)) expect(response).to redirect_to(project_merge_request_path(merge_request.target_project, merge_request))
end end
end end
...@@ -263,11 +277,42 @@ describe Projects::MergeRequestsController do ...@@ -263,11 +277,42 @@ describe Projects::MergeRequestsController do
it 'updates the merge request' do it 'updates the merge request' do
expect(merge_request.reload).to be_valid expect(merge_request.reload).to be_valid
expect(response).to redirect_to(project_merge_request_path(project, merge_request)) expect(response).to redirect_to(project_merge_request_path(merge_request.target_project, merge_request))
end end
end end
end end
end end
context 'when the MR targets the project' do
it_behaves_like 'approvals_before_merge param'
end
context 'when the project is a fork' do
let(:upstream) { create(:project, :repository) }
let(:project) { create(:project, :repository, forked_from_project: upstream) }
context 'when the MR target upstream' do
let(:merge_request) { create(:merge_request, title: 'This is targeting upstream', source_project: project, target_project: upstream) }
before do
upstream.add_developer(user)
upstream.update_attributes(approvals_before_merge: 2)
end
it_behaves_like 'approvals_before_merge param'
end
context 'when the MR target the fork' do
let(:merge_request) { create(:merge_request, title: 'This is targeting the fork', source_project: project, target_project: project) }
before do
project.add_developer(user)
project.update_attributes(approvals_before_merge: 0)
end
it_behaves_like 'approvals_before_merge param'
end
end
end end
describe 'POST merge' do describe 'POST merge' do
...@@ -353,6 +398,8 @@ describe Projects::MergeRequestsController do ...@@ -353,6 +398,8 @@ describe Projects::MergeRequestsController do
fork_project.add_reporter(user) fork_project.add_reporter(user)
end end
it_behaves_like 'approvals'
context 'user cannot push to source branch' do context 'user cannot push to source branch' do
it 'returns 404' do it 'returns 404' do
expect_rebase_worker_for(viewer).never expect_rebase_worker_for(viewer).never
......
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