2019-05-22 07:45:27 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
require 'spec_helper'
|
|
|
|
|
|
|
|
describe AutoMergeService do
|
2020-04-21 11:21:10 -04:00
|
|
|
let_it_be(:project) { create(:project, :repository) }
|
2020-01-10 04:07:49 -05:00
|
|
|
let_it_be(:user) { create(:user) }
|
2019-05-22 07:45:27 -04:00
|
|
|
let(:service) { described_class.new(project, user) }
|
|
|
|
|
2020-04-21 11:21:10 -04:00
|
|
|
before_all do
|
|
|
|
project.add_maintainer(user)
|
|
|
|
end
|
2019-05-22 07:45:27 -04:00
|
|
|
|
2020-04-21 11:21:10 -04:00
|
|
|
describe '.all_strategies_ordered_by_preference' do
|
|
|
|
subject { described_class.all_strategies_ordered_by_preference }
|
|
|
|
|
|
|
|
it 'returns all strategies in preference order' do
|
|
|
|
if Gitlab.ee?
|
|
|
|
is_expected.to eq(
|
|
|
|
[AutoMergeService::STRATEGY_MERGE_TRAIN,
|
|
|
|
AutoMergeService::STRATEGY_ADD_TO_MERGE_TRAIN_WHEN_PIPELINE_SUCCEEDS,
|
|
|
|
AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS])
|
|
|
|
else
|
|
|
|
is_expected.to eq([AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS])
|
|
|
|
end
|
2019-05-22 07:45:27 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe '#available_strategies' do
|
|
|
|
subject { service.available_strategies(merge_request) }
|
|
|
|
|
2020-04-21 11:21:10 -04:00
|
|
|
let(:merge_request) do
|
|
|
|
create(:merge_request, source_project: project)
|
|
|
|
end
|
|
|
|
|
2019-05-22 07:45:27 -04:00
|
|
|
let(:pipeline_status) { :running }
|
|
|
|
|
|
|
|
before do
|
|
|
|
create(:ci_pipeline, pipeline_status, ref: merge_request.source_branch,
|
|
|
|
sha: merge_request.diff_head_sha,
|
|
|
|
project: merge_request.source_project)
|
|
|
|
|
|
|
|
merge_request.update_head_pipeline
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'returns available strategies' do
|
|
|
|
is_expected.to include('merge_when_pipeline_succeeds')
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when the head piipeline succeeded' do
|
|
|
|
let(:pipeline_status) { :success }
|
|
|
|
|
|
|
|
it 'returns available strategies' do
|
|
|
|
is_expected.to be_empty
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-04-21 11:21:10 -04:00
|
|
|
describe '#preferred_strategy' do
|
|
|
|
subject { service.preferred_strategy(merge_request) }
|
|
|
|
|
|
|
|
let(:merge_request) do
|
|
|
|
create(:merge_request, source_project: project)
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:pipeline_status) { :running }
|
|
|
|
|
|
|
|
before do
|
|
|
|
create(:ci_pipeline, pipeline_status, ref: merge_request.source_branch,
|
|
|
|
sha: merge_request.diff_head_sha,
|
|
|
|
project: merge_request.source_project)
|
|
|
|
|
|
|
|
merge_request.update_head_pipeline
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'returns preferred strategy' do
|
|
|
|
is_expected.to eq('merge_when_pipeline_succeeds')
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when the head piipeline succeeded' do
|
|
|
|
let(:pipeline_status) { :success }
|
|
|
|
|
|
|
|
it 'returns available strategies' do
|
|
|
|
is_expected.to be_nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-05-22 07:45:27 -04:00
|
|
|
describe '.get_service_class' do
|
|
|
|
subject { described_class.get_service_class(strategy) }
|
|
|
|
|
|
|
|
let(:strategy) { AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS }
|
|
|
|
|
|
|
|
it 'returns service instance' do
|
|
|
|
is_expected.to eq(AutoMerge::MergeWhenPipelineSucceedsService)
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when strategy is not present' do
|
|
|
|
let(:strategy) { }
|
|
|
|
|
|
|
|
it 'returns nil' do
|
|
|
|
is_expected.to be_nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe '#execute' do
|
|
|
|
subject { service.execute(merge_request, strategy) }
|
|
|
|
|
2020-04-21 11:21:10 -04:00
|
|
|
let(:merge_request) do
|
|
|
|
create(:merge_request, source_project: project)
|
|
|
|
end
|
|
|
|
|
2019-05-22 07:45:27 -04:00
|
|
|
let(:pipeline_status) { :running }
|
|
|
|
let(:strategy) { AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS }
|
|
|
|
|
|
|
|
before do
|
|
|
|
create(:ci_pipeline, pipeline_status, ref: merge_request.source_branch,
|
|
|
|
sha: merge_request.diff_head_sha,
|
|
|
|
project: merge_request.source_project)
|
|
|
|
|
|
|
|
merge_request.update_head_pipeline
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'delegates to a relevant service instance' do
|
|
|
|
expect_next_instance_of(AutoMerge::MergeWhenPipelineSucceedsService) do |service|
|
|
|
|
expect(service).to receive(:execute).with(merge_request)
|
|
|
|
end
|
|
|
|
|
|
|
|
subject
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when the head piipeline succeeded' do
|
|
|
|
let(:pipeline_status) { :success }
|
|
|
|
|
|
|
|
it 'returns failed' do
|
|
|
|
is_expected.to eq(:failed)
|
|
|
|
end
|
|
|
|
end
|
2020-04-21 11:21:10 -04:00
|
|
|
|
|
|
|
context 'when strategy is not specified' do
|
|
|
|
let(:strategy) { }
|
|
|
|
|
|
|
|
it 'chooses the most preferred strategy' do
|
|
|
|
is_expected.to eq(:merge_when_pipeline_succeeds)
|
|
|
|
end
|
|
|
|
end
|
2019-05-22 07:45:27 -04:00
|
|
|
end
|
|
|
|
|
2019-06-06 03:25:06 -04:00
|
|
|
describe '#update' do
|
|
|
|
subject { service.update(merge_request) }
|
|
|
|
|
|
|
|
context 'when auto merge is enabled' do
|
|
|
|
let(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds) }
|
|
|
|
|
|
|
|
it 'delegates to a relevant service instance' do
|
|
|
|
expect_next_instance_of(AutoMerge::MergeWhenPipelineSucceedsService) do |service|
|
|
|
|
expect(service).to receive(:update).with(merge_request)
|
|
|
|
end
|
|
|
|
|
|
|
|
subject
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when auto merge is not enabled' do
|
|
|
|
let(:merge_request) { create(:merge_request) }
|
|
|
|
|
|
|
|
it 'returns failed' do
|
|
|
|
is_expected.to eq(:failed)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-05-22 07:45:27 -04:00
|
|
|
describe '#process' do
|
|
|
|
subject { service.process(merge_request) }
|
|
|
|
|
|
|
|
let(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds) }
|
|
|
|
|
|
|
|
it 'delegates to a relevant service instance' do
|
|
|
|
expect_next_instance_of(AutoMerge::MergeWhenPipelineSucceedsService) do |service|
|
|
|
|
expect(service).to receive(:process).with(merge_request)
|
|
|
|
end
|
|
|
|
|
|
|
|
subject
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when auto merge is not enabled' do
|
|
|
|
let(:merge_request) { create(:merge_request) }
|
|
|
|
|
|
|
|
it 'returns nil' do
|
|
|
|
is_expected.to be_nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe '#cancel' do
|
|
|
|
subject { service.cancel(merge_request) }
|
|
|
|
|
|
|
|
let(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds) }
|
|
|
|
|
|
|
|
it 'delegates to a relevant service instance' do
|
|
|
|
expect_next_instance_of(AutoMerge::MergeWhenPipelineSucceedsService) do |service|
|
|
|
|
expect(service).to receive(:cancel).with(merge_request)
|
|
|
|
end
|
|
|
|
|
|
|
|
subject
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when auto merge is not enabled' do
|
|
|
|
let(:merge_request) { create(:merge_request) }
|
|
|
|
|
|
|
|
it 'returns error' do
|
|
|
|
expect(subject[:message]).to eq("Can't cancel the automatic merge")
|
|
|
|
expect(subject[:status]).to eq(:error)
|
|
|
|
expect(subject[:http_status]).to eq(406)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2019-06-26 08:24:09 -04:00
|
|
|
|
|
|
|
describe '#abort' do
|
|
|
|
subject { service.abort(merge_request, error) }
|
|
|
|
|
|
|
|
let(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds) }
|
|
|
|
let(:error) { 'an error' }
|
|
|
|
|
|
|
|
it 'delegates to a relevant service instance' do
|
|
|
|
expect_next_instance_of(AutoMerge::MergeWhenPipelineSucceedsService) do |service|
|
|
|
|
expect(service).to receive(:abort).with(merge_request, error)
|
|
|
|
end
|
|
|
|
|
|
|
|
subject
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when auto merge is not enabled' do
|
|
|
|
let(:merge_request) { create(:merge_request) }
|
|
|
|
|
|
|
|
it 'returns error' do
|
|
|
|
expect(subject[:message]).to eq("Can't abort the automatic merge")
|
|
|
|
expect(subject[:status]).to eq(:error)
|
|
|
|
expect(subject[:http_status]).to eq(406)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2019-05-22 07:45:27 -04:00
|
|
|
end
|