Move CI stages configuration to new CI config
This commit is contained in:
parent
2240807c1a
commit
29b96d92c1
12 changed files with 147 additions and 29 deletions
|
@ -4,7 +4,6 @@ module Ci
|
||||||
|
|
||||||
include Gitlab::Ci::Config::Node::LegacyValidationHelpers
|
include Gitlab::Ci::Config::Node::LegacyValidationHelpers
|
||||||
|
|
||||||
DEFAULT_STAGES = %w(build test deploy)
|
|
||||||
DEFAULT_STAGE = 'test'
|
DEFAULT_STAGE = 'test'
|
||||||
ALLOWED_YAML_KEYS = [:before_script, :after_script, :image, :services, :types, :stages, :variables, :cache]
|
ALLOWED_YAML_KEYS = [:before_script, :after_script, :image, :services, :types, :stages, :variables, :cache]
|
||||||
ALLOWED_JOB_KEYS = [:tags, :script, :only, :except, :type, :image, :services,
|
ALLOWED_JOB_KEYS = [:tags, :script, :only, :except, :type, :image, :services,
|
||||||
|
@ -46,7 +45,7 @@ module Ci
|
||||||
end
|
end
|
||||||
|
|
||||||
def stages
|
def stages
|
||||||
@stages || DEFAULT_STAGES
|
@stages
|
||||||
end
|
end
|
||||||
|
|
||||||
def global_variables
|
def global_variables
|
||||||
|
@ -68,8 +67,8 @@ module Ci
|
||||||
@after_script = @ci_config.after_script
|
@after_script = @ci_config.after_script
|
||||||
@services = @ci_config.services
|
@services = @ci_config.services
|
||||||
@variables = @ci_config.variables
|
@variables = @ci_config.variables
|
||||||
|
@stages = @ci_config.stages
|
||||||
|
|
||||||
@stages = @config[:stages] || @config[:types]
|
|
||||||
@cache = @config[:cache]
|
@cache = @config[:cache]
|
||||||
@jobs = {}
|
@jobs = {}
|
||||||
|
|
||||||
|
@ -90,7 +89,7 @@ module Ci
|
||||||
|
|
||||||
def build_job(name, job)
|
def build_job(name, job)
|
||||||
{
|
{
|
||||||
stage_idx: stages.index(job[:stage]),
|
stage_idx: @stages.index(job[:stage]),
|
||||||
stage: job[:stage],
|
stage: job[:stage],
|
||||||
commands: [job[:before_script] || @before_script, job[:script]].flatten.compact.join("\n"),
|
commands: [job[:before_script] || @before_script, job[:script]].flatten.compact.join("\n"),
|
||||||
tag_list: job[:tags] || [],
|
tag_list: job[:tags] || [],
|
||||||
|
@ -112,7 +111,7 @@ module Ci
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate!
|
def validate!
|
||||||
validate_global!
|
validate_global_cache! if @cache
|
||||||
|
|
||||||
@jobs.each do |name, job|
|
@jobs.each do |name, job|
|
||||||
validate_job!(name, job)
|
validate_job!(name, job)
|
||||||
|
@ -121,14 +120,6 @@ module Ci
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_global!
|
|
||||||
unless @stages.nil? || validate_array_of_strings(@stages)
|
|
||||||
raise ValidationError, "stages should be an array of strings"
|
|
||||||
end
|
|
||||||
|
|
||||||
validate_global_cache! if @cache
|
|
||||||
end
|
|
||||||
|
|
||||||
def validate_global_cache!
|
def validate_global_cache!
|
||||||
@cache.keys.each do |key|
|
@cache.keys.each do |key|
|
||||||
unless ALLOWED_CACHE_KEYS.include? key
|
unless ALLOWED_CACHE_KEYS.include? key
|
||||||
|
@ -225,8 +216,8 @@ module Ci
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_job_stage!(name, job)
|
def validate_job_stage!(name, job)
|
||||||
unless job[:stage].is_a?(String) && job[:stage].in?(stages)
|
unless job[:stage].is_a?(String) && job[:stage].in?(@stages)
|
||||||
raise ValidationError, "#{name} job: stage parameter should be #{stages.join(", ")}"
|
raise ValidationError, "#{name} job: stage parameter should be #{@stages.join(", ")}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -290,12 +281,12 @@ module Ci
|
||||||
raise ValidationError, "#{name} job: dependencies parameter should be an array of strings"
|
raise ValidationError, "#{name} job: dependencies parameter should be an array of strings"
|
||||||
end
|
end
|
||||||
|
|
||||||
stage_index = stages.index(job[:stage])
|
stage_index = @stages.index(job[:stage])
|
||||||
|
|
||||||
job[:dependencies].each do |dependency|
|
job[:dependencies].each do |dependency|
|
||||||
raise ValidationError, "#{name} job: undefined dependency: #{dependency}" unless @jobs[dependency.to_sym]
|
raise ValidationError, "#{name} job: undefined dependency: #{dependency}" unless @jobs[dependency.to_sym]
|
||||||
|
|
||||||
unless stages.index(@jobs[dependency.to_sym][:stage]) < stage_index
|
unless @stages.index(@jobs[dependency.to_sym][:stage]) < stage_index
|
||||||
raise ValidationError, "#{name} job: dependency #{dependency} is not defined in prior stages"
|
raise ValidationError, "#{name} job: dependency #{dependency} is not defined in prior stages"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,7 +8,7 @@ module Gitlab
|
||||||
# Temporary delegations that should be removed after refactoring
|
# Temporary delegations that should be removed after refactoring
|
||||||
#
|
#
|
||||||
delegate :before_script, :image, :services, :after_script, :variables,
|
delegate :before_script, :image, :services, :after_script, :variables,
|
||||||
to: :@global
|
:stages, to: :@global
|
||||||
|
|
||||||
def initialize(config)
|
def initialize(config)
|
||||||
@config = Loader.new(config).load!
|
@config = Loader.new(config).load!
|
||||||
|
|
|
@ -38,14 +38,20 @@ module Gitlab
|
||||||
private
|
private
|
||||||
|
|
||||||
def node(symbol, entry_class, metadata)
|
def node(symbol, entry_class, metadata)
|
||||||
factory = Node::Factory.new(entry_class)
|
define_method("#{symbol}_defined?") do
|
||||||
.with(description: metadata[:description])
|
@nodes[symbol].try(:defined?)
|
||||||
|
end
|
||||||
|
|
||||||
define_method(symbol) do
|
define_method("#{symbol}_value") do
|
||||||
raise Entry::InvalidError unless valid?
|
raise Entry::InvalidError unless valid?
|
||||||
@nodes[symbol].try(:value)
|
@nodes[symbol].try(:value)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
alias_method symbol.to_sym, "#{symbol}_value".to_sym
|
||||||
|
|
||||||
|
factory = Node::Factory.new(entry_class)
|
||||||
|
.with(description: metadata[:description])
|
||||||
|
|
||||||
(@nodes ||= {}).merge!(symbol => factory)
|
(@nodes ||= {}).merge!(symbol => factory)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -52,6 +52,10 @@ module Gitlab
|
||||||
@config
|
@config
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def defined?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
def self.default
|
def self.default
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ module Gitlab
|
||||||
raise InvalidFactory unless @attributes.has_key?(:value)
|
raise InvalidFactory unless @attributes.has_key?(:value)
|
||||||
|
|
||||||
##
|
##
|
||||||
# We assume unspecified entry is undefined.
|
# We assume that unspecified entry is undefined.
|
||||||
# See issue #18775.
|
# See issue #18775.
|
||||||
#
|
#
|
||||||
if @attributes[:value].nil?
|
if @attributes[:value].nil?
|
||||||
|
|
|
@ -23,6 +23,16 @@ module Gitlab
|
||||||
|
|
||||||
node :variables, Variables,
|
node :variables, Variables,
|
||||||
description: 'Environment variables that will be used.'
|
description: 'Environment variables that will be used.'
|
||||||
|
|
||||||
|
node :stages, Stages,
|
||||||
|
description: 'Configuration of stages for this pipeline.'
|
||||||
|
|
||||||
|
node :types, Stages,
|
||||||
|
description: 'Stages for this pipeline (deprecated key).'
|
||||||
|
|
||||||
|
def stages
|
||||||
|
stages_defined? ? stages_value : types_value
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
22
lib/gitlab/ci/config/node/stages.rb
Normal file
22
lib/gitlab/ci/config/node/stages.rb
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
module Gitlab
|
||||||
|
module Ci
|
||||||
|
class Config
|
||||||
|
module Node
|
||||||
|
##
|
||||||
|
# Entry that represents a configuration for pipeline stages.
|
||||||
|
#
|
||||||
|
class Stages < Entry
|
||||||
|
include Validatable
|
||||||
|
|
||||||
|
validations do
|
||||||
|
validates :config, array_of_strings: true
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.default
|
||||||
|
%w(build test deploy)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -19,6 +19,10 @@ module Gitlab
|
||||||
def value
|
def value
|
||||||
@config.default
|
@config.default
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def defined?
|
||||||
|
false
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1081,17 +1081,17 @@ EOT
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns errors if stages is not an array" do
|
it "returns errors if stages is not an array" do
|
||||||
config = YAML.dump({ types: "test", rspec: { script: "test" } })
|
config = YAML.dump({ stages: "test", rspec: { script: "test" } })
|
||||||
expect do
|
expect do
|
||||||
GitlabCiYamlProcessor.new(config, path)
|
GitlabCiYamlProcessor.new(config, path)
|
||||||
end.to raise_error(GitlabCiYamlProcessor::ValidationError, "stages should be an array of strings")
|
end.to raise_error(GitlabCiYamlProcessor::ValidationError, "Stages config should be an array of strings")
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns errors if stages is not an array of strings" do
|
it "returns errors if stages is not an array of strings" do
|
||||||
config = YAML.dump({ types: [true, "test"], rspec: { script: "test" } })
|
config = YAML.dump({ stages: [true, "test"], rspec: { script: "test" } })
|
||||||
expect do
|
expect do
|
||||||
GitlabCiYamlProcessor.new(config, path)
|
GitlabCiYamlProcessor.new(config, path)
|
||||||
end.to raise_error(GitlabCiYamlProcessor::ValidationError, "stages should be an array of strings")
|
end.to raise_error(GitlabCiYamlProcessor::ValidationError, "Stages config should be an array of strings")
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns errors if variables is not a map" do
|
it "returns errors if variables is not a map" do
|
||||||
|
|
|
@ -26,7 +26,8 @@ describe Gitlab::Ci::Config::Node::Global do
|
||||||
image: 'ruby:2.2',
|
image: 'ruby:2.2',
|
||||||
services: ['postgres:9.1', 'mysql:5.5'],
|
services: ['postgres:9.1', 'mysql:5.5'],
|
||||||
variables: { VAR: 'value' },
|
variables: { VAR: 'value' },
|
||||||
after_script: ['make clean'] }
|
after_script: ['make clean'],
|
||||||
|
stages: ['build', 'pages'] }
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#process!' do
|
describe '#process!' do
|
||||||
|
@ -37,7 +38,7 @@ describe Gitlab::Ci::Config::Node::Global do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'creates node object for each entry' do
|
it 'creates node object for each entry' do
|
||||||
expect(global.nodes.count).to eq 5
|
expect(global.nodes.count).to eq 7
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'creates node object using valid class' do
|
it 'creates node object using valid class' do
|
||||||
|
@ -101,6 +102,22 @@ describe Gitlab::Ci::Config::Node::Global do
|
||||||
expect(global.variables).to eq(VAR: 'value')
|
expect(global.variables).to eq(VAR: 'value')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#stages' do
|
||||||
|
context 'when stages key defined' do
|
||||||
|
it 'returns array of stages' do
|
||||||
|
expect(global.stages).to eq %w[build pages]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when deprecated types key defined' do
|
||||||
|
let(:hash) { { types: ['test', 'deploy'] } }
|
||||||
|
|
||||||
|
it 'returns array of types as stages' do
|
||||||
|
expect(global.stages).to eq %w[test deploy]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -110,7 +127,7 @@ describe Gitlab::Ci::Config::Node::Global do
|
||||||
|
|
||||||
describe '#nodes' do
|
describe '#nodes' do
|
||||||
it 'instantizes all nodes' do
|
it 'instantizes all nodes' do
|
||||||
expect(global.nodes.count).to eq 5
|
expect(global.nodes.count).to eq 7
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'contains undefined nodes' do
|
it 'contains undefined nodes' do
|
||||||
|
@ -124,6 +141,12 @@ describe Gitlab::Ci::Config::Node::Global do
|
||||||
expect(global.variables).to eq({})
|
expect(global.variables).to eq({})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#stages' do
|
||||||
|
it 'returns an array of default stages' do
|
||||||
|
expect(global.stages).to eq %w[build test deploy]
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -188,4 +211,10 @@ describe Gitlab::Ci::Config::Node::Global do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#defined?' do
|
||||||
|
it 'is concrete entry that is defined' do
|
||||||
|
expect(global.defined?).to be true
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
46
spec/lib/gitlab/ci/config/node/stages_spec.rb
Normal file
46
spec/lib/gitlab/ci/config/node/stages_spec.rb
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe Gitlab::Ci::Config::Node::Stages do
|
||||||
|
let(:entry) { described_class.new(config) }
|
||||||
|
|
||||||
|
describe 'validations' do
|
||||||
|
context 'when entry config value is correct' do
|
||||||
|
let(:config) { [:stage1, :stage2] }
|
||||||
|
|
||||||
|
describe '#value' do
|
||||||
|
it 'returns array of stages' do
|
||||||
|
expect(entry.value).to eq config
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#valid?' do
|
||||||
|
it 'is valid' do
|
||||||
|
expect(entry).to be_valid
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when entry value is not correct' do
|
||||||
|
let(:config) { { test: true } }
|
||||||
|
|
||||||
|
describe '#errors' do
|
||||||
|
it 'saves errors' do
|
||||||
|
expect(entry.errors)
|
||||||
|
.to include 'Stages config should be an array of strings'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#valid?' do
|
||||||
|
it 'is not valid' do
|
||||||
|
expect(entry).not_to be_valid
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '.default' do
|
||||||
|
it 'returns default stages' do
|
||||||
|
expect(described_class.default).to eq %w[build test deploy]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -31,4 +31,10 @@ describe Gitlab::Ci::Config::Node::Undefined do
|
||||||
expect(undefined.value).to eq 'some value'
|
expect(undefined.value).to eq 'some value'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#undefined?' do
|
||||||
|
it 'is not a concrete entry that is defined' do
|
||||||
|
expect(undefined.defined?).to be false
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue