Commit 6a398883 authored by Kamil Trzciński's avatar Kamil Trzciński

Merge branch 'fix/gb/pipeline-retry-skipped-jobs' into 'master'

Fix reprocessing skipped jobs when retrying pipeline

See merge request !9436
parents 70997dea ca378aa3
module Ci module Ci
class RetryPipelineService < ::BaseService class RetryPipelineService < ::BaseService
include Gitlab::OptimisticLocking
def execute(pipeline) def execute(pipeline)
unless can?(current_user, :update_pipeline, pipeline) unless can?(current_user, :update_pipeline, pipeline)
raise Gitlab::Access::AccessDeniedError raise Gitlab::Access::AccessDeniedError
...@@ -12,6 +14,10 @@ module Ci ...@@ -12,6 +14,10 @@ module Ci
.reprocess(build) .reprocess(build)
end end
pipeline.builds.skipped.find_each do |skipped|
retry_optimistic_lock(skipped) { |build| build.process }
end
MergeRequests::AddTodoWhenBuildFailsService MergeRequests::AddTodoWhenBuildFailsService
.new(project, current_user) .new(project, current_user)
.close_all(pipeline) .close_all(pipeline)
......
module Gitlab module Gitlab
module OptimisticLocking module OptimisticLocking
extend self module_function
def retry_lock(subject, retries = 100, &block) def retry_lock(subject, retries = 100, &block)
loop do loop do
...@@ -15,5 +15,7 @@ module Gitlab ...@@ -15,5 +15,7 @@ module Gitlab
end end
end end
end end
alias_method :retry_optimistic_lock, :retry_lock
end end
end end
require 'spec_helper' require 'spec_helper'
describe Gitlab::OptimisticLocking, lib: true do describe Gitlab::OptimisticLocking, lib: true do
describe '#retry_lock' do
let!(:pipeline) { create(:ci_pipeline) } let!(:pipeline) { create(:ci_pipeline) }
let!(:pipeline2) { Ci::Pipeline.find(pipeline.id) } let!(:pipeline2) { Ci::Pipeline.find(pipeline.id) }
describe '#retry_lock' do
it 'does not reload object if state changes' do it 'does not reload object if state changes' do
expect(pipeline).not_to receive(:reload) expect(pipeline).not_to receive(:reload)
expect(pipeline).to receive(:succeed).and_call_original expect(pipeline).to receive(:succeed).and_call_original
...@@ -36,4 +36,17 @@ describe Gitlab::OptimisticLocking, lib: true do ...@@ -36,4 +36,17 @@ describe Gitlab::OptimisticLocking, lib: true do
end.to raise_error(ActiveRecord::StaleObjectError) end.to raise_error(ActiveRecord::StaleObjectError)
end end
end end
describe '#retry_optimistic_lock' do
context 'when locking module is mixed in' do
let(:unlockable) do
Class.new.include(described_class).new
end
it 'is an alias for retry_lock' do
expect(unlockable.method(:retry_optimistic_lock))
.to eq unlockable.method(:retry_lock)
end
end
end
end end
...@@ -69,6 +69,25 @@ describe Ci::RetryPipelineService, '#execute', :services do ...@@ -69,6 +69,25 @@ describe Ci::RetryPipelineService, '#execute', :services do
end end
end end
context 'when the last stage was skipepd' do
before do
create_build('build 1', :success, 0)
create_build('test 2', :failed, 1)
create_build('report 3', :skipped, 2)
create_build('report 4', :skipped, 2)
end
it 'retries builds only in the first stage' do
service.execute(pipeline)
expect(build('build 1')).to be_success
expect(build('test 2')).to be_pending
expect(build('report 3')).to be_created
expect(build('report 4')).to be_created
expect(pipeline.reload).to be_running
end
end
context 'when pipeline contains manual actions' do context 'when pipeline contains manual actions' do
context 'when there is a canceled manual action in first stage' do context 'when there is a canceled manual action in first stage' do
before do before do
...@@ -90,14 +109,16 @@ describe Ci::RetryPipelineService, '#execute', :services do ...@@ -90,14 +109,16 @@ describe Ci::RetryPipelineService, '#execute', :services do
context 'when there is a skipped manual action in last stage' do context 'when there is a skipped manual action in last stage' do
before do before do
create_build('rspec 1', :canceled, 0) create_build('rspec 1', :canceled, 0)
create_build('rspec 2', :skipped, 0, :manual)
create_build('staging', :skipped, 1, :manual) create_build('staging', :skipped, 1, :manual)
end end
it 'retries canceled job and skips manual action' do it 'retries canceled job and reprocesses manual actions' do
service.execute(pipeline) service.execute(pipeline)
expect(build('rspec 1')).to be_pending expect(build('rspec 1')).to be_pending
expect(build('staging')).to be_skipped expect(build('rspec 2')).to be_skipped
expect(build('staging')).to be_created
expect(pipeline.reload).to be_running expect(pipeline.reload).to be_running
end end
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment