summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGrzegorz Bizon <grzesiek.bizon@gmail.com>2017-02-13 16:38:08 +0100
committerGrzegorz Bizon <grzesiek.bizon@gmail.com>2017-02-13 16:38:08 +0100
commitc65e96061bf2dae9f79ffbbf4b291cb12bf47d90 (patch)
treede563ab8b9c5433984ec3c9f77c60515abd70ff1
parent19ef4083f373dd5fdc6b4c59325a4cb14179e699 (diff)
downloadgitlab-ce-c65e96061bf2dae9f79ffbbf4b291cb12bf47d90.tar.gz
Implement new pipeline retry service
The new service takes stages order into account.
-rw-r--r--app/models/ci/stage.rb12
-rw-r--r--app/services/ci/retry_build_service.rb12
-rw-r--r--app/services/ci/retry_pipeline_service.rb27
-rw-r--r--spec/services/ci/retry_pipeline_service_spec.rb51
4 files changed, 91 insertions, 11 deletions
diff --git a/app/models/ci/stage.rb b/app/models/ci/stage.rb
index ca74c91b062..c6a7984870f 100644
--- a/app/models/ci/stage.rb
+++ b/app/models/ci/stage.rb
@@ -19,6 +19,10 @@ module Ci
name
end
+ def index
+ statuses.first.stage_idx
+ end
+
def statuses_count
@statuses_count ||= statuses.count
end
@@ -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?
diff --git a/app/services/ci/retry_build_service.rb b/app/services/ci/retry_build_service.rb
index de410be7f14..b7a9a55dd9e 100644
--- a/app/services/ci/retry_build_service.rb
+++ b/app/services/ci/retry_build_service.rb
@@ -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
@@ -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,
diff --git a/app/services/ci/retry_pipeline_service.rb b/app/services/ci/retry_pipeline_service.rb
index f873acc9964..9d8e4d361f4 100644
--- a/app/services/ci/retry_pipeline_service.rb
+++ b/app/services/ci/retry_pipeline_service.rb
@@ -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
diff --git a/spec/services/ci/retry_pipeline_service_spec.rb b/spec/services/ci/retry_pipeline_service_spec.rb
index 6fc1d884920..aeb3ee228ad 100644
--- a/spec/services/ci/retry_pipeline_service_spec.rb
+++ b/spec/services/ci/retry_pipeline_service_spec.rb
@@ -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
@@ -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:)