summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKamil Trzcinski <ayufan@ayufan.eu>2016-11-19 14:04:11 +0100
committerKamil Trzcinski <ayufan@ayufan.eu>2016-11-19 14:04:11 +0100
commitca639c9b824d6c8effb620bc71255eb0895ab2cc (patch)
tree1d4dc50805946ecbff39416052a04ffa0fbbcb1f
parent92a83aaee1c5715bf95715649aa8ced50a70dea8 (diff)
downloadgitlab-ce-ca639c9b824d6c8effb620bc71255eb0895ab2cc.tar.gz
Allow to retry failed or canceled builds and fix cancel running specs failure
-rw-r--r--app/models/ci/pipeline.rb14
-rw-r--r--app/models/concerns/has_status.rb1
-rw-r--r--spec/models/ci/pipeline_spec.rb63
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