Commit ad3dc1d7 authored by Shinya Maeda's avatar Shinya Maeda

Always Refresh Merge Requests in Merge Train from the beginning

This commit adds the new service to improve merge train refresh
service.
parent 9bcd2fd0
---
name: ci_always_refresh_merge_requests_from_beginning
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45232
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/268215
type: development
group: group::continuous integration
default_enabled: false
......@@ -19,7 +19,7 @@ module MergeTrains
result = queue.safe_execute([merge_request.id], lock_timeout: 15.minutes) do |items|
logging("Successfuly obtained the exclusive lock. Found merge requests to be refreshed", merge_request_ids: items.map(&:to_i))
first_merge_request = MergeTrain.first_in_train_from(items)
first_merge_request = get_first_in_train(items)
unsafe_refresh(first_merge_request)
end
......@@ -30,7 +30,7 @@ module MergeTrains
if result[:status] == :finished && result[:new_items].present?
logging("Found more merge requests to be refreshed", merge_request_ids: result[:new_items].map(&:to_i))
MergeTrain.first_in_train_from(result[:new_items]).try do |first_merge_request|
get_first_in_train(result[:new_items]).try do |first_merge_request|
logging("Rescheduled to refresh the merge train from", merge_request_ids: [first_merge_request.id])
AutoMergeProcessWorker.perform_async(first_merge_request.id)
......@@ -42,6 +42,14 @@ module MergeTrains
attr_reader :merge_request
def get_first_in_train(items)
if Feature.enabled?(:ci_always_refresh_merge_requests_from_beginning, merge_request.target_project)
MergeTrain.first_in_train(merge_request.target_project, merge_request.target_branch)
else
MergeTrain.first_in_train_from(items)
end
end
def unsafe_refresh(first_merge_request)
require_next_recreate = false
......
......@@ -174,45 +174,70 @@ RSpec.describe MergeTrains::RefreshMergeRequestsService do
context 'when merge request 2 is passed' do
let(:merge_request) { merge_request_2 }
it 'executes RefreshMergeRequestService to all the following merge requests' do
expect(refresh_service_1).not_to receive(:execute).with(merge_request_1)
it 'executes RefreshMergeRequestService to all the merge requests from beginning' do
expect(refresh_service_1).to receive(:execute).with(merge_request_1)
expect(refresh_service_2).to receive(:execute).with(merge_request_2)
subject
end
it_behaves_like 'logging results', 2
context 'when merge request 1 was tried to be refreshed while the system is refreshing merge request 2' do
context 'when ci_always_refresh_merge_requests_from_beginning is disabled' do
before do
allow_any_instance_of(described_class).to receive(:unsafe_refresh).with(merge_request_2) do
service.execute(merge_request_1)
end
stub_feature_flags(ci_always_refresh_merge_requests_from_beginning: false)
end
it 'refreshes the merge request 1 later with AutoMergeProcessWorker' do
expect(AutoMergeProcessWorker).to receive(:perform_async).with(merge_request_1.id).once
it 'executes RefreshMergeRequestService to all the following merge requests' do
expect(refresh_service_1).not_to receive(:execute).with(merge_request_1)
expect(refresh_service_2).to receive(:execute).with(merge_request_2)
subject
end
it_behaves_like 'logging results', 4
context 'when merge request 1 has already been merged' do
context 'when merge request 1 was tried to be refreshed while the system is refreshing merge request 2' do
before do
allow(merge_request_1.merge_train).to receive(:cleanup_ref)
merge_request_1.merge_train.update_column(:status, MergeTrain.state_machines[:status].states[:merged].value)
allow_any_instance_of(described_class).to receive(:unsafe_refresh).with(merge_request_2) do
service.execute(merge_request_1)
end
end
it 'does not refresh the merge request 1' do
expect(AutoMergeProcessWorker).not_to receive(:perform_async).with(merge_request_1.id)
it 'refreshes the merge request 1 later with AutoMergeProcessWorker' do
expect(AutoMergeProcessWorker).to receive(:perform_async).with(merge_request_1.id).once
subject
end
it_behaves_like 'logging results', 1
context 'when ci_always_refresh_merge_requests_from_beginning is disabled' do
before do
stub_feature_flags(ci_always_refresh_merge_requests_from_beginning: false)
end
it 'refreshes the merge request 1 later with AutoMergeProcessWorker' do
expect(AutoMergeProcessWorker).to receive(:perform_async).with(merge_request_1.id).once
subject
end
end
it_behaves_like 'logging results', 4
context 'when merge request 1 has already been merged' do
before do
allow(merge_request_1.merge_train).to receive(:cleanup_ref)
merge_request_1.merge_train.update_column(:status, MergeTrain.state_machines[:status].states[:merged].value)
end
it 'does not refresh the merge request 1' do
expect(AutoMergeProcessWorker).not_to receive(:perform_async).with(merge_request_1.id)
subject
end
it_behaves_like 'logging results', 1
end
end
end
it_behaves_like 'logging results', 3
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