Commit b14c9af4 authored by Furkan Ayhan's avatar Furkan Ayhan

Allow cross-db transaction for Build#drop_with_exit_code!

When dropping a build with this method, it wraps the execution with
a transaction.

If this build;
- Configured as auto-retry
- Has a pipeline related to an MR
- Has a TODO with that MR
Then Ci::RetryBuildService;
- Retries the job
- Closes the TODO

And those two updates should not be in a single transaction because
they refer to different DBs.

The next step is to remove this cross-db transaction.
parent f13747c5
......@@ -1051,9 +1051,11 @@ module Ci
end
def drop_with_exit_code!(failure_reason, exit_code)
transaction do
conditionally_allow_failure!(exit_code)
drop!(failure_reason)
::Gitlab::Database::QueryAnalyzers::PreventCrossDatabaseModification.allow_cross_database_modification_within_transaction(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/348495') do
transaction do
conditionally_allow_failure!(exit_code)
drop!(failure_reason)
end
end
end
......
......@@ -5223,6 +5223,26 @@ RSpec.describe Ci::Build do
it_behaves_like 'drops the build without changing allow_failure'
end
end
context 'when build is configured to be retried' do
let(:options) { { retry: 3 } }
context 'when there is an MR attached to the pipeline and a failed job todo for that MR' do
let!(:merge_request) { create(:merge_request, source_project: project, author: user, head_pipeline: pipeline) }
let!(:todo) { create(:todo, :build_failed, user: user, project: project, author: user, target: merge_request) }
before do
build.update!(user: user)
project.add_developer(user)
end
it 'resolves the todo for the old failed build' do
expect do
drop_with_exit_code
end.to change { todo.reload.state }.from('pending').to('done')
end
end
end
end
describe '#exit_codes_defined?' do
......
......@@ -188,13 +188,6 @@ RSpec.describe Ci::RetryBuildService do
expect(new_build).to be_pending
end
it 'resolves todos for old build that failed' do
expect(::MergeRequests::AddTodoWhenBuildFailsService)
.to receive_message_chain(:new, :close)
service.execute(build)
end
context 'when there are subsequent processables that are skipped' do
let!(:subsequent_build) do
create(:ci_build, :skipped, stage_idx: 2,
......@@ -272,6 +265,17 @@ RSpec.describe Ci::RetryBuildService do
expect(bridge.reload).to be_pending
end
end
context 'when there is a failed job todo for the MR' do
let!(:merge_request) { create(:merge_request, source_project: project, author: user, head_pipeline: pipeline) }
let!(:todo) { create(:todo, :build_failed, user: user, project: project, author: user, target: merge_request) }
it 'resolves the todo for the old failed build' do
expect do
service.execute(build)
end.to change { todo.reload.state }.from('pending').to('done')
end
end
end
context 'when user does not have ability to execute build' do
......
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