From 94495f984c0a81d32b6f748fd977848dc5c6721e Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Tue, 14 Feb 2017 12:20:02 +0100 Subject: [PATCH] Use new pipeline retry service with optimistic locking --- app/models/ci/pipeline.rb | 10 ++--- app/services/ci/retry_build_service.rb | 2 + app/services/ci/retry_pipeline_service.rb | 54 ++++++++++++++--------- 3 files changed, 39 insertions(+), 27 deletions(-) diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 8d43f3051ee..49bd2e1d7f0 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -224,13 +224,9 @@ module Ci end end - def retry_failed(user) - Gitlab::OptimisticLocking.retry_lock( - builds.latest.failed_or_canceled) do |failed_or_canceled| - failed_or_canceled.select(&:retryable?).each do |build| - Ci::Build.retry(build, user) - end - end + def retry_failed(current_user) + Ci::RetryPipelineService.new(project, current_user) + .execute(self) end def mark_as_processable_after_stage(stage_idx) diff --git a/app/services/ci/retry_build_service.rb b/app/services/ci/retry_build_service.rb index e470bd6ee6a..009fbeaff20 100644 --- a/app/services/ci/retry_build_service.rb +++ b/app/services/ci/retry_build_service.rb @@ -1,6 +1,8 @@ module Ci class RetryBuildService < ::BaseService def execute(build) + # return unless build.retryable? + self.retry(build).tap do |new_build| MergeRequests::AddTodoWhenBuildFailsService .new(build.project, current_user) diff --git a/app/services/ci/retry_pipeline_service.rb b/app/services/ci/retry_pipeline_service.rb index b062c50e82d..1b931455fb8 100644 --- a/app/services/ci/retry_pipeline_service.rb +++ b/app/services/ci/retry_pipeline_service.rb @@ -7,34 +7,48 @@ module Ci raise Gitlab::Access::AccessDeniedError end - ## - # Reprocess builds in subsequent stages - # - pipeline.builds - .after_stage(resume_stage.index) - .failed_or_canceled.find_each do |build| - Ci::RetryBuildService - .new(project, current_user) - .reprocess(build) - end - - ## - # Mark skipped builds as processable again - # pipeline.mark_as_processable_after_stage(resume_stage.index) - ## - # Retry builds in the first unsuccessful stage - # - resume_stage.builds.failed_or_canceled.find_each do |build| - Ci::RetryBuildService - .new(project, current_user) + retryable_builds_in_subsequent_stages do |build| + Ci::RetryBuildService.new(project, current_user) + .reprocess(build) + end + + retryable_builds_in_first_unsuccessful_stage do |build| + Ci::RetryBuildService.new(project, current_user) .retry(build) end end private + def retryable_builds_in_subsequent_stages + relation = @pipeline.builds + .after_stage(resume_stage.index) + .failed_or_canceled + + each_retryable_build_with_locking(relation) do |build| + yield build + end + end + + def retryable_builds_in_first_unsuccessful_stage + relation = resume_stage.builds.failed_or_canceled + + each_retryable_build_with_locking(relation) do |build| + yield build + end + end + + def each_retryable_build_with_locking(relation) + Gitlab::OptimisticLocking.retry_lock(relation) do |builds| + builds.find_each do |build| + next unless build.retryable? + yield build + end + end + end + def resume_stage @resume_stage ||= @pipeline.stages.find do |stage| stage.failed? || stage.canceled?