Commit 474f0643 authored by Shinya Maeda's avatar Shinya Maeda

Create Deployment in a separate transaction for Job Retry

This commit separates the deployments INSERT query
from the transaction for ci_builds.
parent b819e1f9
......@@ -2,6 +2,8 @@
module Ci
class RetryBuildService < ::BaseService
include Gitlab::Utils::StrongMemoize
def self.clone_accessors
%i[pipeline project ref tag options name
allow_failure stage stage_id stage_idx trigger_request
......@@ -45,6 +47,11 @@ module Ci
job.save!
end
end
if create_deployment_in_separate_transaction?
clone_deployment!(new_build, build)
end
build.reset # refresh the data to get new values of `retried` and `processed`.
new_build
......@@ -63,9 +70,11 @@ module Ci
def clone_build(build)
project.builds.new(build_attributes(build)).tap do |new_build|
unless create_deployment_in_separate_transaction?
new_build.assign_attributes(deployment_attributes_for(new_build, build))
end
end
end
def build_attributes(build)
clone_attributes = if ::Feature.enabled?(:clone_job_variables_at_job_retry, build.project, default_enabled: :yaml)
......@@ -78,6 +87,11 @@ module Ci
[attribute, build.public_send(attribute)] # rubocop:disable GitlabSecurity/PublicSend
end
if create_deployment_in_separate_transaction? && build.persisted_environment.present?
attributes[:metadata_attributes] ||= {}
attributes[:metadata_attributes][:expanded_environment_name] = build.expanded_environment_name
end
attributes[:user] = current_user
attributes
end
......@@ -86,6 +100,26 @@ module Ci
::Gitlab::Ci::Pipeline::Seed::Build
.deployment_attributes_for(new_build, old_build.persisted_environment)
end
def clone_deployment!(new_build, old_build)
return unless old_build.deployment.present?
# We should clone the previous deployment attributes instead of initializing
# new object with `Seed::Deployment`.
# See https://gitlab.com/gitlab-org/gitlab/-/issues/347206
deployment = ::Gitlab::Ci::Pipeline::Seed::Deployment
.new(new_build, old_build.persisted_environment).to_resource
return unless deployment
new_build.create_deployment!(deployment.attributes)
end
def create_deployment_in_separate_transaction?
strong_memoize(:create_deployment_in_separate_transaction) do
::Feature.enabled?(:create_deployment_in_separate_transaction, project, default_enabled: :yaml)
end
end
end
end
......
......@@ -333,7 +333,7 @@ RSpec.describe Ci::RetryBuildService do
expect(build).to be_processed
end
context 'when build with deployment is retried' do
shared_examples_for 'when build with deployment is retried' do
let!(:build) do
create(:ci_build, :with_deployment, :deploy_to_production,
pipeline: pipeline, stage_id: stage.id, project: project)
......@@ -352,7 +352,7 @@ RSpec.describe Ci::RetryBuildService do
end
end
context 'when build with dynamic environment is retried' do
shared_examples_for 'when build with dynamic environment is retried' do
let_it_be(:other_developer) { create(:user).tap { |u| project.add_developer(other_developer) } }
let(:environment_name) { 'review/$CI_COMMIT_REF_SLUG-$GITLAB_USER_ID' }
......@@ -379,6 +379,18 @@ RSpec.describe Ci::RetryBuildService do
end
end
it_behaves_like 'when build with deployment is retried'
it_behaves_like 'when build with dynamic environment is retried'
context 'when create_deployment_in_separate_transaction feature flag is disabled' do
before do
stub_feature_flags(create_deployment_in_separate_transaction: false)
end
it_behaves_like 'when build with deployment is retried'
it_behaves_like 'when build with dynamic environment is retried'
end
context 'when build has needs' do
before do
create(:ci_build_need, build: build, name: 'build1')
......
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