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 ...@@ -19,7 +19,7 @@ module MergeTrains
result = queue.safe_execute([merge_request.id], lock_timeout: 15.minutes) do |items| 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)) 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) unsafe_refresh(first_merge_request)
end end
...@@ -30,7 +30,7 @@ module MergeTrains ...@@ -30,7 +30,7 @@ module MergeTrains
if result[:status] == :finished && result[:new_items].present? 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)) 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]) logging("Rescheduled to refresh the merge train from", merge_request_ids: [first_merge_request.id])
AutoMergeProcessWorker.perform_async(first_merge_request.id) AutoMergeProcessWorker.perform_async(first_merge_request.id)
...@@ -42,6 +42,14 @@ module MergeTrains ...@@ -42,6 +42,14 @@ module MergeTrains
attr_reader :merge_request 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) def unsafe_refresh(first_merge_request)
require_next_recreate = false require_next_recreate = false
......
...@@ -174,45 +174,70 @@ RSpec.describe MergeTrains::RefreshMergeRequestsService do ...@@ -174,45 +174,70 @@ RSpec.describe MergeTrains::RefreshMergeRequestsService do
context 'when merge request 2 is passed' do context 'when merge request 2 is passed' do
let(:merge_request) { merge_request_2 } let(:merge_request) { merge_request_2 }
it 'executes RefreshMergeRequestService to all the following merge requests' do it 'executes RefreshMergeRequestService to all the merge requests from beginning' do
expect(refresh_service_1).not_to receive(:execute).with(merge_request_1) expect(refresh_service_1).to receive(:execute).with(merge_request_1)
expect(refresh_service_2).to receive(:execute).with(merge_request_2) expect(refresh_service_2).to receive(:execute).with(merge_request_2)
subject subject
end end
it_behaves_like 'logging results', 2 context 'when ci_always_refresh_merge_requests_from_beginning is disabled' do
context 'when merge request 1 was tried to be refreshed while the system is refreshing merge request 2' do
before do before do
allow_any_instance_of(described_class).to receive(:unsafe_refresh).with(merge_request_2) do stub_feature_flags(ci_always_refresh_merge_requests_from_beginning: false)
service.execute(merge_request_1)
end
end end
it 'refreshes the merge request 1 later with AutoMergeProcessWorker' do it 'executes RefreshMergeRequestService to all the following merge requests' do
expect(AutoMergeProcessWorker).to receive(:perform_async).with(merge_request_1.id).once expect(refresh_service_1).not_to receive(:execute).with(merge_request_1)
expect(refresh_service_2).to receive(:execute).with(merge_request_2)
subject subject
end end
it_behaves_like 'logging results', 4 context 'when merge request 1 was tried to be refreshed while the system is refreshing merge request 2' do
context 'when merge request 1 has already been merged' do
before do before do
allow(merge_request_1.merge_train).to receive(:cleanup_ref) allow_any_instance_of(described_class).to receive(:unsafe_refresh).with(merge_request_2) do
merge_request_1.merge_train.update_column(:status, MergeTrain.state_machines[:status].states[:merged].value) service.execute(merge_request_1)
end
end end
it 'does not refresh the merge request 1' do it 'refreshes the merge request 1 later with AutoMergeProcessWorker' do
expect(AutoMergeProcessWorker).not_to receive(:perform_async).with(merge_request_1.id) expect(AutoMergeProcessWorker).to receive(:perform_async).with(merge_request_1.id).once
subject subject
end 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
end end
it_behaves_like 'logging results', 3
end end
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