diff options
author | Kamil Trzcinski <ayufan@ayufan.eu> | 2016-11-19 14:04:11 +0100 |
---|---|---|
committer | Kamil Trzcinski <ayufan@ayufan.eu> | 2016-11-19 14:04:11 +0100 |
commit | ca639c9b824d6c8effb620bc71255eb0895ab2cc (patch) | |
tree | 1d4dc50805946ecbff39416052a04ffa0fbbcb1f | |
parent | 92a83aaee1c5715bf95715649aa8ced50a70dea8 (diff) | |
download | gitlab-ce-ca639c9b824d6c8effb620bc71255eb0895ab2cc.tar.gz |
Allow to retry failed or canceled builds and fix cancel running specs failure
-rw-r--r-- | app/models/ci/pipeline.rb | 14 | ||||
-rw-r--r-- | app/models/concerns/has_status.rb | 1 | ||||
-rw-r--r-- | spec/models/ci/pipeline_spec.rb | 63 |
3 files changed, 69 insertions, 9 deletions
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 4eb85f62ee4..c0f2c8ba787 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -161,9 +161,7 @@ module Ci end def retryable? - builds.latest.any? do |build| - (build.failed? || build.canceled?) && build.retryable? - end + builds.latest.failed_or_canceled.any?(&:retryable?) end def cancelable? @@ -171,12 +169,16 @@ module Ci end def cancel_running - statuses.cancelable.each(&:cancel) + Gitlab::OptimisticLocking.retry_lock(statuses.cancelable) do |cancelable| + cancelable.each(&:cancel) + end end def retry_failed(user) - builds.latest.failed.select(&:retryable?).each do |build| - Ci::Build.retry(build, user) + Gitlab::OptimisticLocking.retry_lock(builds.latest.failed_or_canceled) do |failed| + failed.select(&:retryable?).each do |build| + Ci::Build.retry(build, user) + end end end diff --git a/app/models/concerns/has_status.rb b/app/models/concerns/has_status.rb index 1332743429d..2f5aa91a964 100644 --- a/app/models/concerns/has_status.rb +++ b/app/models/concerns/has_status.rb @@ -73,6 +73,7 @@ module HasStatus scope :skipped, -> { where(status: 'skipped') } scope :running_or_pending, -> { where(status: [:running, :pending]) } scope :finished, -> { where(status: [:success, :failed, :canceled]) } + scope :failed_or_canceled, -> { where(status: [:failed, :canceled]) } scope :cancelable, -> do where(status: [:running, :pending, :created]) diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 74579e0c832..af619a02ed9 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -455,17 +455,74 @@ describe Ci::Pipeline, models: true do end describe '#cancel_running' do + let(:latest_status) { pipeline.statuses.pluck(:status) } + context 'when there is a running external job and created build' do before do + create(:ci_build, :running, pipeline: pipeline) create(:generic_commit_status, :running, pipeline: pipeline) - create(:ci_build, :created, pipeline: pipeline) pipeline.cancel_running end it 'cancels both jobs' do - expect(pipeline.statuses.pluck(:status)). - to contain_exactly('canceled', 'canceled') + expect(latest_status).to contain_exactly('canceled', 'canceled') + end + end + + context 'when builds are in different stages' do + before do + create(:ci_build, :running, stage_idx: 0, pipeline: pipeline) + create(:ci_build, :running, stage_idx: 1, pipeline: pipeline) + + pipeline.cancel_running + end + + it 'cancels both jobs' do + expect(latest_status).to contain_exactly('canceled', 'canceled') + end + end + end + + describe '#retry_failed' do + let(:latest_status) { pipeline.statuses.latest.pluck(:status) } + + context 'when there is a failed build and failed external status' do + before do + create(:ci_build, :failed, name: 'build', pipeline: pipeline) + create(:generic_commit_status, :failed, name: 'jenkins', pipeline: pipeline) + + pipeline.retry_failed(nil) + end + + it 'retries only build' do + expect(latest_status).to contain_exactly('pending', 'failed') + end + end + + context 'when builds are in different stages' do + before do + create(:ci_build, :failed, name: 'build', stage_idx: 0, pipeline: pipeline) + create(:ci_build, :failed, name: 'jenkins', stage_idx: 1, pipeline: pipeline) + + pipeline.retry_failed(nil) + end + + it 'retries both builds' do + expect(latest_status).to contain_exactly('pending', 'pending') + end + end + + context 'when there are canceled and failed' do + before do + create(:ci_build, :failed, name: 'build', stage_idx: 0, pipeline: pipeline) + create(:ci_build, :canceled, name: 'jenkins', stage_idx: 1, pipeline: pipeline) + + pipeline.retry_failed(nil) + end + + it 'retries both builds' do + expect(latest_status).to contain_exactly('pending', 'pending') end end end |