Commit 67c7e0fc authored by Shinya Maeda's avatar Shinya Maeda

Fail jobs if its dependency is missing

parent f9229281
......@@ -139,6 +139,12 @@ module Ci
Ci::Build.retry(build, build.user)
end
end
before_transition any => [:running] do |build|
if !build.empty_dependencies? && build.dependencies.empty?
raise Gitlab::Ci::Error::MissingDependencies
end
end
end
def detailed_status(current_user)
......
......@@ -43,7 +43,8 @@ class CommitStatus < ActiveRecord::Base
script_failure: 1,
api_failure: 2,
stuck_or_timeout_failure: 3,
runner_system_failure: 4
runner_system_failure: 4,
missing_dependency_failure: 5
}
##
......
......@@ -54,6 +54,9 @@ module Ci
# we still have to return 409 in the end,
# to make sure that this is properly handled by runner.
valid = false
rescue Gitlab::Ci::Error::MissingDependencies
build.drop!(:missing_dependency_failure)
valid = false
end
end
......
module Gitlab
module Ci
module Error
class MissingDependencies < StandardError; end
end
end
end
require 'spec_helper'
describe Gitlab::Ci::Error::MissingDependencies do
it { expect(described_class).to be < StandardError }
end
......@@ -1868,6 +1868,36 @@ describe Ci::Build do
end
end
describe 'state transition: any => [:running]' do
let(:build) { create(:ci_build, :pending, pipeline: pipeline, stage_idx: 1, options: options) }
context 'when "dependencies" keyword is not defined' do
let(:options) { {} }
it { expect { build.run! }.not_to raise_error }
end
context 'when "dependencies" keyword is empty' do
let(:options) { { dependencies: [] } }
it { expect { build.run! }.not_to raise_error }
end
context 'when "dependencies" keyword is specified' do
let(:options) { { dependencies: ['test'] } }
context 'when a depended job exists' do
let!(:pre_build) { create(:ci_build, pipeline: pipeline, name: 'test', stage_idx: 0) }
it { expect { build.run! }.not_to raise_error }
end
context 'when depended jobs do not exist' do
it { expect { build.run! }.to raise_error(Gitlab::Ci::Error::MissingDependencies) }
end
end
end
describe 'state transition when build fails' do
let(:service) { MergeRequests::AddTodoWhenBuildFailsService.new(project, user) }
......
......@@ -276,6 +276,34 @@ module Ci
end
end
context 'when "dependencies" keyword is specified' do
let!(:pre_stage_job) { create(:ci_build, :success, pipeline: pipeline, name: job_name, stage_idx: 0) }
let!(:pending_job) do
create(:ci_build, :pending, pipeline: pipeline, stage_idx: 1, options: { dependencies: ['spec'] } )
end
let(:picked_job) { execute(specific_runner) }
context 'when a depended job exists' do
let(:job_name) { 'spec' }
it "picks the build" do
expect(picked_job).to eq(pending_job)
end
end
context 'when depended jobs do not exist' do
let(:job_name) { 'robocop' }
it 'does not pick the build and drops the build' do
expect(picked_job).to be_nil
expect(pending_job.reload).to be_failed
expect(pending_job).to be_missing_dependency_failure
end
end
end
def execute(runner)
described_class.new(runner).execute.build
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