Skip to content
Snippets Groups Projects
Commit c65e9606 authored by Grzegorz Bizon's avatar Grzegorz Bizon
Browse files

Implement new pipeline retry service

The new service takes stages order into account.
parent 19ef4083
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -19,6 +19,10 @@ module Ci
name
end
 
def index
statuses.first.stage_idx
end
def statuses_count
@statuses_count ||= statuses.count
end
Loading
Loading
@@ -45,6 +49,14 @@ module Ci
status.to_s == 'success'
end
 
def failed?
status.to_s == 'failed'
end
def canceled?
status.to_s == 'canceled'
end
def has_warnings?
if @warnings.nil?
statuses.latest.failed_but_allowed.any?
Loading
Loading
Loading
Loading
@@ -9,11 +9,7 @@ module Ci
end
 
def retry!
unless can?(@user, :update_build, @build)
raise Gitlab::Access::AccessDeniedError
end
clone_build.tap do |new_build|
reprocess!.tap do |new_build|
new_build.enqueue!
 
MergeRequests::AddTodoWhenBuildFailsService
Loading
Loading
@@ -24,9 +20,11 @@ module Ci
end
end
 
private
def reprocess!
unless can?(@user, :update_build, @build)
raise Gitlab::Access::AccessDeniedError
end
 
def clone_build
Ci::Build.create(
ref: @build.ref,
tag: @build.tag,
Loading
Loading
Loading
Loading
@@ -12,10 +12,31 @@ module Ci
raise Gitlab::Access::AccessDeniedError
end
 
@pipeline.stages.each do |stage|
stage.builds.failed_or_canceled.find_each do |build|
Ci::Build.retry(build, @user)
##
# Reprocess builds in subsequent stages if any
#
# TODO, refactor.
#
@pipeline.builds
.where('stage_idx > ?', resume_stage.index)
.failed_or_canceled.find_each do |build|
Ci::RetryBuildService.new(build, @user).reprocess!
end
##
# Retry builds in the first unsuccessful stage
#
resume_stage.builds.failed_or_canceled.find_each do |build|
Ci::Build.retry(build, @user)
end
end
private
def resume_stage
@resume_stage ||= @pipeline.stages.find do |stage|
stage.failed? || stage.canceled?
end
end
end
Loading
Loading
Loading
Loading
@@ -21,6 +21,51 @@ describe Ci::RetryPipelineService, '#execute', :services do
 
expect(build('rspec 2')).to be_pending
expect(build('rspec 3')).to be_pending
expect(pipeline.reload).to be_running
end
end
context 'when there are failed or canceled builds in the first stage' do
before do
create_build(name: 'rspec 1', status: :failed, stage_num: 0)
create_build(name: 'rspec 2', status: :canceled, stage_num: 0)
create_build(name: 'rspec 3', status: :skipped, stage_num: 1)
create_build(name: 'deploy 1', status: :skipped, stage_num: 2)
end
it 'retries builds failed builds and marks subsequent for processing' do
service.execute
expect(build('rspec 1')).to be_pending
expect(build('rspec 2')).to be_pending
expect(build('rspec 3')).to be_created
expect(build('deploy 1')).to be_created
expect(pipeline.reload).to be_running
end
end
context 'when there is failed build present which was run on failure' do
before do
create_build(name: 'rspec 1', status: :failed, stage_num: 0)
create_build(name: 'rspec 2', status: :canceled, stage_num: 0)
create_build(name: 'rspec 3', status: :skipped, stage_num: 1)
create_build(name: 'report 1', status: :failed, stage_num: 2)
end
it 'retries builds failed builds and marks subsequent for processing' do
service.execute
expect(build('rspec 1')).to be_pending
expect(build('rspec 2')).to be_pending
expect(build('rspec 3')).to be_created
expect(build('report 1')).to be_created
expect(pipeline.reload).to be_running
end
it 'creates a new job for report job in this case' do
service.execute
expect(statuses.where(name: 'report 1').count).to eq 2
end
end
end
Loading
Loading
@@ -32,8 +77,12 @@ describe Ci::RetryPipelineService, '#execute', :services do
end
end
 
def statuses
pipeline.reload.statuses
end
def build(name)
pipeline.statuses.find_by(name: name)
statuses.latest.find_by(name: name)
end
 
def create_build(name:, status:, stage_num:)
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment