Merge branch 'feature/gb/add-complex-jobs-only-except-config-policy' into 'master'
New syntax for CI/CD job triggering policy that supports variables expressions See merge request !13769
This commit is contained in:
commit
a0b5684634
17 changed files with 334 additions and 156 deletions
|
@ -8,6 +8,10 @@ module Gitlab
|
||||||
class_methods do
|
class_methods do
|
||||||
def attributes(*attributes)
|
def attributes(*attributes)
|
||||||
attributes.flatten.each do |attribute|
|
attributes.flatten.each do |attribute|
|
||||||
|
if method_defined?(attribute)
|
||||||
|
raise ArgumentError, 'Method already defined!'
|
||||||
|
end
|
||||||
|
|
||||||
define_method(attribute) do
|
define_method(attribute) do
|
||||||
return unless config.is_a?(Hash)
|
return unless config.is_a?(Hash)
|
||||||
|
|
||||||
|
|
|
@ -15,9 +15,10 @@ module Gitlab
|
||||||
#
|
#
|
||||||
module Configurable
|
module Configurable
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
include Validatable
|
|
||||||
|
|
||||||
included do
|
included do
|
||||||
|
include Validatable
|
||||||
|
|
||||||
validations do
|
validations do
|
||||||
validates :config, type: Hash
|
validates :config, type: Hash
|
||||||
end
|
end
|
||||||
|
|
|
@ -59,10 +59,10 @@ module Gitlab
|
||||||
entry :services, Entry::Services,
|
entry :services, Entry::Services,
|
||||||
description: 'Services that will be used to execute this job.'
|
description: 'Services that will be used to execute this job.'
|
||||||
|
|
||||||
entry :only, Entry::Trigger,
|
entry :only, Entry::Policy,
|
||||||
description: 'Refs policy this job will be executed for.'
|
description: 'Refs policy this job will be executed for.'
|
||||||
|
|
||||||
entry :except, Entry::Trigger,
|
entry :except, Entry::Policy,
|
||||||
description: 'Refs policy this job will be executed for.'
|
description: 'Refs policy this job will be executed for.'
|
||||||
|
|
||||||
entry :variables, Entry::Variables,
|
entry :variables, Entry::Variables,
|
||||||
|
|
|
@ -16,8 +16,9 @@ module Gitlab
|
||||||
@metadata = metadata
|
@metadata = metadata
|
||||||
@entries = {}
|
@entries = {}
|
||||||
|
|
||||||
@validator = self.class.validator.new(self)
|
self.class.aspects.to_a.each do |aspect|
|
||||||
@validator.validate(:new)
|
instance_exec(&aspect)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def [](key)
|
def [](key)
|
||||||
|
@ -47,7 +48,7 @@ module Gitlab
|
||||||
end
|
end
|
||||||
|
|
||||||
def errors
|
def errors
|
||||||
@validator.messages + descendants.flat_map(&:errors)
|
[]
|
||||||
end
|
end
|
||||||
|
|
||||||
def value
|
def value
|
||||||
|
@ -70,6 +71,13 @@ module Gitlab
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def location
|
||||||
|
name = @key.presence || self.class.name.to_s.demodulize
|
||||||
|
.underscore.humanize.downcase
|
||||||
|
|
||||||
|
ancestors.map(&:key).append(name).compact.join(':')
|
||||||
|
end
|
||||||
|
|
||||||
def inspect
|
def inspect
|
||||||
val = leaf? ? config : descendants
|
val = leaf? ? config : descendants
|
||||||
unspecified = specified? ? '' : '(unspecified) '
|
unspecified = specified? ? '' : '(unspecified) '
|
||||||
|
@ -79,8 +87,8 @@ module Gitlab
|
||||||
def self.default
|
def self.default
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.validator
|
def self.aspects
|
||||||
Validator
|
@aspects ||= []
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
31
lib/gitlab/ci/config/entry/policy.rb
Normal file
31
lib/gitlab/ci/config/entry/policy.rb
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
module Gitlab
|
||||||
|
module Ci
|
||||||
|
class Config
|
||||||
|
module Entry
|
||||||
|
##
|
||||||
|
# Entry that represents an only/except trigger policy for the job.
|
||||||
|
#
|
||||||
|
class Policy < Simplifiable
|
||||||
|
strategy :RefsPolicy, if: -> (config) { config.is_a?(Array) }
|
||||||
|
|
||||||
|
class RefsPolicy < Entry::Node
|
||||||
|
include Entry::Validatable
|
||||||
|
|
||||||
|
validations do
|
||||||
|
validates :config, array_of_strings_or_regexps: true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class UnknownStrategy < Entry::Node
|
||||||
|
def errors
|
||||||
|
["#{location} has to be either an array of conditions or a hash"]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.default
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
43
lib/gitlab/ci/config/entry/simplifiable.rb
Normal file
43
lib/gitlab/ci/config/entry/simplifiable.rb
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
module Gitlab
|
||||||
|
module Ci
|
||||||
|
class Config
|
||||||
|
module Entry
|
||||||
|
class Simplifiable < SimpleDelegator
|
||||||
|
EntryStrategy = Struct.new(:name, :condition)
|
||||||
|
|
||||||
|
def initialize(config, **metadata)
|
||||||
|
unless self.class.const_defined?(:UnknownStrategy)
|
||||||
|
raise ArgumentError, 'UndefinedStrategy not available!'
|
||||||
|
end
|
||||||
|
|
||||||
|
strategy = self.class.strategies.find do |variant|
|
||||||
|
variant.condition.call(config)
|
||||||
|
end
|
||||||
|
|
||||||
|
entry = self.class.entry_class(strategy)
|
||||||
|
|
||||||
|
super(entry.new(config, metadata))
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.strategy(name, **opts)
|
||||||
|
EntryStrategy.new(name, opts.fetch(:if)).tap do |strategy|
|
||||||
|
strategies.append(strategy)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.strategies
|
||||||
|
@strategies ||= []
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.entry_class(strategy)
|
||||||
|
if strategy.present?
|
||||||
|
self.const_get(strategy.name)
|
||||||
|
else
|
||||||
|
self::UnknownStrategy
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,18 +0,0 @@
|
||||||
module Gitlab
|
|
||||||
module Ci
|
|
||||||
class Config
|
|
||||||
module Entry
|
|
||||||
##
|
|
||||||
# Entry that represents a trigger policy for the job.
|
|
||||||
#
|
|
||||||
class Trigger < Node
|
|
||||||
include Validatable
|
|
||||||
|
|
||||||
validations do
|
|
||||||
validates :config, array_of_strings_or_regexps: true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -5,6 +5,17 @@ module Gitlab
|
||||||
module Validatable
|
module Validatable
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
|
def self.included(node)
|
||||||
|
node.aspects.append -> do
|
||||||
|
@validator = self.class.validator.new(self)
|
||||||
|
@validator.validate(:new)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def errors
|
||||||
|
@validator.messages + descendants.flat_map(&:errors)
|
||||||
|
end
|
||||||
|
|
||||||
class_methods do
|
class_methods do
|
||||||
def validator
|
def validator
|
||||||
@validator ||= Class.new(Entry::Validator).tap do |validator|
|
@validator ||= Class.new(Entry::Validator).tap do |validator|
|
||||||
|
|
|
@ -8,7 +8,6 @@ module Gitlab
|
||||||
|
|
||||||
def initialize(entry)
|
def initialize(entry)
|
||||||
super(entry)
|
super(entry)
|
||||||
@entry = entry
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def messages
|
def messages
|
||||||
|
@ -20,21 +19,6 @@ module Gitlab
|
||||||
def self.name
|
def self.name
|
||||||
'Validator'
|
'Validator'
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def location
|
|
||||||
predecessors = ancestors.map(&:key).compact
|
|
||||||
predecessors.append(key_name).join(':')
|
|
||||||
end
|
|
||||||
|
|
||||||
def key_name
|
|
||||||
if key.blank?
|
|
||||||
@entry.class.name.demodulize.underscore.humanize
|
|
||||||
else
|
|
||||||
key
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -344,28 +344,31 @@ module Ci
|
||||||
let(:config) { { rspec: { script: "rspec", type: "test", only: only } } }
|
let(:config) { { rspec: { script: "rspec", type: "test", only: only } } }
|
||||||
let(:processor) { GitlabCiYamlProcessor.new(YAML.dump(config)) }
|
let(:processor) { GitlabCiYamlProcessor.new(YAML.dump(config)) }
|
||||||
|
|
||||||
shared_examples 'raises an error' do
|
|
||||||
it do
|
|
||||||
expect { processor }.to raise_error(GitlabCiYamlProcessor::ValidationError, 'jobs:rspec:only config should be an array of strings or regexps')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when it is integer' do
|
context 'when it is integer' do
|
||||||
let(:only) { 1 }
|
let(:only) { 1 }
|
||||||
|
|
||||||
it_behaves_like 'raises an error'
|
it do
|
||||||
|
expect { processor }.to raise_error(GitlabCiYamlProcessor::ValidationError,
|
||||||
|
'jobs:rspec:only has to be either an array of conditions or a hash')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when it is an array of integers' do
|
context 'when it is an array of integers' do
|
||||||
let(:only) { [1, 1] }
|
let(:only) { [1, 1] }
|
||||||
|
|
||||||
it_behaves_like 'raises an error'
|
it do
|
||||||
|
expect { processor }.to raise_error(GitlabCiYamlProcessor::ValidationError,
|
||||||
|
'jobs:rspec:only config should be an array of strings or regexps')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when it is invalid regex' do
|
context 'when it is invalid regex' do
|
||||||
let(:only) { ["/*invalid/"] }
|
let(:only) { ["/*invalid/"] }
|
||||||
|
|
||||||
it_behaves_like 'raises an error'
|
it do
|
||||||
|
expect { processor }.to raise_error(GitlabCiYamlProcessor::ValidationError,
|
||||||
|
'jobs:rspec:only config should be an array of strings or regexps')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -518,28 +521,31 @@ module Ci
|
||||||
let(:config) { { rspec: { script: "rspec", except: except } } }
|
let(:config) { { rspec: { script: "rspec", except: except } } }
|
||||||
let(:processor) { GitlabCiYamlProcessor.new(YAML.dump(config)) }
|
let(:processor) { GitlabCiYamlProcessor.new(YAML.dump(config)) }
|
||||||
|
|
||||||
shared_examples 'raises an error' do
|
|
||||||
it do
|
|
||||||
expect { processor }.to raise_error(GitlabCiYamlProcessor::ValidationError, 'jobs:rspec:except config should be an array of strings or regexps')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when it is integer' do
|
context 'when it is integer' do
|
||||||
let(:except) { 1 }
|
let(:except) { 1 }
|
||||||
|
|
||||||
it_behaves_like 'raises an error'
|
it do
|
||||||
|
expect { processor }.to raise_error(GitlabCiYamlProcessor::ValidationError,
|
||||||
|
'jobs:rspec:except has to be either an array of conditions or a hash')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when it is an array of integers' do
|
context 'when it is an array of integers' do
|
||||||
let(:except) { [1, 1] }
|
let(:except) { [1, 1] }
|
||||||
|
|
||||||
it_behaves_like 'raises an error'
|
it do
|
||||||
|
expect { processor }.to raise_error(GitlabCiYamlProcessor::ValidationError,
|
||||||
|
'jobs:rspec:except config should be an array of strings or regexps')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when it is invalid regex' do
|
context 'when it is invalid regex' do
|
||||||
let(:except) { ["/*invalid/"] }
|
let(:except) { ["/*invalid/"] }
|
||||||
|
|
||||||
it_behaves_like 'raises an error'
|
it do
|
||||||
|
expect { processor }.to raise_error(GitlabCiYamlProcessor::ValidationError,
|
||||||
|
'jobs:rspec:except config should be an array of strings or regexps')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,18 +1,21 @@
|
||||||
require 'spec_helper'
|
require 'spec_helper'
|
||||||
|
|
||||||
describe Gitlab::Ci::Config::Entry::Attributable do
|
describe Gitlab::Ci::Config::Entry::Attributable do
|
||||||
let(:node) { Class.new }
|
let(:node) do
|
||||||
|
Class.new do
|
||||||
|
include Gitlab::Ci::Config::Entry::Attributable
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
let(:instance) { node.new }
|
let(:instance) { node.new }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
node.include(described_class)
|
|
||||||
|
|
||||||
node.class_eval do
|
node.class_eval do
|
||||||
attributes :name, :test
|
attributes :name, :test
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'config is a hash' do
|
context 'when config is a hash' do
|
||||||
before do
|
before do
|
||||||
allow(instance)
|
allow(instance)
|
||||||
.to receive(:config)
|
.to receive(:config)
|
||||||
|
@ -29,7 +32,7 @@ describe Gitlab::Ci::Config::Entry::Attributable do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'config is not a hash' do
|
context 'when config is not a hash' do
|
||||||
before do
|
before do
|
||||||
allow(instance)
|
allow(instance)
|
||||||
.to receive(:config)
|
.to receive(:config)
|
||||||
|
@ -40,4 +43,18 @@ describe Gitlab::Ci::Config::Entry::Attributable do
|
||||||
expect(instance.test).to be_nil
|
expect(instance.test).to be_nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when method is already defined in a superclass' do
|
||||||
|
it 'raises an error' do
|
||||||
|
expectation = expect do
|
||||||
|
Class.new(String) do
|
||||||
|
include Gitlab::Ci::Config::Entry::Attributable
|
||||||
|
|
||||||
|
attributes :length
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
expectation.to raise_error(ArgumentError, 'Method already defined!')
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,40 +1,26 @@
|
||||||
require 'spec_helper'
|
require 'spec_helper'
|
||||||
|
|
||||||
describe Gitlab::Ci::Config::Entry::Configurable do
|
describe Gitlab::Ci::Config::Entry::Configurable do
|
||||||
let(:entry) { Class.new }
|
let(:entry) do
|
||||||
|
Class.new(Gitlab::Ci::Config::Entry::Node) do
|
||||||
before do
|
include Gitlab::Ci::Config::Entry::Configurable
|
||||||
entry.include(described_class)
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'validations' do
|
describe 'validations' do
|
||||||
let(:validator) { entry.validator.new(instance) }
|
context 'when entry is a hash' do
|
||||||
|
|
||||||
before do
|
|
||||||
entry.class_eval do
|
|
||||||
attr_reader :config
|
|
||||||
|
|
||||||
def initialize(config)
|
|
||||||
@config = config
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
validator.validate
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when entry validator is invalid' do
|
|
||||||
let(:instance) { entry.new('ls') }
|
|
||||||
|
|
||||||
it 'returns invalid validator' do
|
|
||||||
expect(validator).to be_invalid
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when entry instance is valid' do
|
|
||||||
let(:instance) { entry.new(key: 'value') }
|
let(:instance) { entry.new(key: 'value') }
|
||||||
|
|
||||||
it 'returns valid validator' do
|
it 'correctly validates an instance' do
|
||||||
expect(validator).to be_valid
|
expect(instance).to be_valid
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when entry is not a hash' do
|
||||||
|
let(:instance) { entry.new('ls') }
|
||||||
|
|
||||||
|
it 'invalidates the instance' do
|
||||||
|
expect(instance).not_to be_valid
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
73
spec/lib/gitlab/ci/config/entry/policy_spec.rb
Normal file
73
spec/lib/gitlab/ci/config/entry/policy_spec.rb
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe Gitlab::Ci::Config::Entry::Policy do
|
||||||
|
let(:entry) { described_class.new(config) }
|
||||||
|
|
||||||
|
context 'when using simplified policy' do
|
||||||
|
describe 'validations' do
|
||||||
|
context 'when entry config value is valid' do
|
||||||
|
context 'when config is a branch or tag name' do
|
||||||
|
let(:config) { %w[master feature/branch] }
|
||||||
|
|
||||||
|
describe '#valid?' do
|
||||||
|
it 'is valid' do
|
||||||
|
expect(entry).to be_valid
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#value' do
|
||||||
|
it 'returns key value' do
|
||||||
|
expect(entry.value).to eq config
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when config is a regexp' do
|
||||||
|
let(:config) { ['/^issue-.*$/'] }
|
||||||
|
|
||||||
|
describe '#valid?' do
|
||||||
|
it 'is valid' do
|
||||||
|
expect(entry).to be_valid
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when config is a special keyword' do
|
||||||
|
let(:config) { %w[tags triggers branches] }
|
||||||
|
|
||||||
|
describe '#valid?' do
|
||||||
|
it 'is valid' do
|
||||||
|
expect(entry).to be_valid
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when entry value is not valid' do
|
||||||
|
let(:config) { [1] }
|
||||||
|
|
||||||
|
describe '#errors' do
|
||||||
|
it 'saves errors' do
|
||||||
|
expect(entry.errors)
|
||||||
|
.to include /policy config should be an array of strings or regexps/
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when policy strategy does not match' do
|
||||||
|
let(:config) { 'string strategy' }
|
||||||
|
|
||||||
|
it 'returns information about errors' do
|
||||||
|
expect(entry.errors)
|
||||||
|
.to include /has to be either an array of conditions or a hash/
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '.default' do
|
||||||
|
it 'does not have a default value' do
|
||||||
|
expect(described_class.default).to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
88
spec/lib/gitlab/ci/config/entry/simplifiable_spec.rb
Normal file
88
spec/lib/gitlab/ci/config/entry/simplifiable_spec.rb
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe Gitlab::Ci::Config::Entry::Simplifiable do
|
||||||
|
describe '.strategy' do
|
||||||
|
let(:entry) do
|
||||||
|
Class.new(described_class) do
|
||||||
|
strategy :Something, if: -> { 'condition' }
|
||||||
|
strategy :DifferentOne, if: -> { 'condition' }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'defines entry strategies' do
|
||||||
|
expect(entry.strategies.size).to eq 2
|
||||||
|
expect(entry.strategies.map(&:name))
|
||||||
|
.to eq %i[Something DifferentOne]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'setting strategy by a condition' do
|
||||||
|
let(:first) { double('first strategy') }
|
||||||
|
let(:second) { double('second strategy') }
|
||||||
|
let(:unknown) { double('unknown strategy') }
|
||||||
|
|
||||||
|
before do
|
||||||
|
stub_const("#{described_class.name}::Something", first)
|
||||||
|
stub_const("#{described_class.name}::DifferentOne", second)
|
||||||
|
stub_const("#{described_class.name}::UnknownStrategy", unknown)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when first strategy should be used' do
|
||||||
|
let(:entry) do
|
||||||
|
Class.new(described_class) do
|
||||||
|
strategy :Something, if: -> (arg) { arg == 'something' }
|
||||||
|
strategy :DifferentOne, if: -> (*) { false }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'attemps to load a first strategy' do
|
||||||
|
expect(first).to receive(:new).with('something', anything)
|
||||||
|
|
||||||
|
entry.new('something')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when second strategy should be used' do
|
||||||
|
let(:entry) do
|
||||||
|
Class.new(described_class) do
|
||||||
|
strategy :Something, if: -> (arg) { arg == 'something' }
|
||||||
|
strategy :DifferentOne, if: -> (arg) { arg == 'test' }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'attemps to load a second strategy' do
|
||||||
|
expect(second).to receive(:new).with('test', anything)
|
||||||
|
|
||||||
|
entry.new('test')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when neither one is a valid strategy' do
|
||||||
|
let(:entry) do
|
||||||
|
Class.new(described_class) do
|
||||||
|
strategy :Something, if: -> (*) { false }
|
||||||
|
strategy :DifferentOne, if: -> (*) { false }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'instantiates an unknown strategy' do
|
||||||
|
expect(unknown).to receive(:new).with('test', anything)
|
||||||
|
|
||||||
|
entry.new('test')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when a unknown strategy class is not defined' do
|
||||||
|
let(:entry) do
|
||||||
|
Class.new(described_class) do
|
||||||
|
strategy :String, if: -> (*) { true }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'raises an error when being initialized' do
|
||||||
|
expect { entry.new('something') }
|
||||||
|
.to raise_error ArgumentError, /UndefinedStrategy not available!/
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,56 +0,0 @@
|
||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe Gitlab::Ci::Config::Entry::Trigger do
|
|
||||||
let(:entry) { described_class.new(config) }
|
|
||||||
|
|
||||||
describe 'validations' do
|
|
||||||
context 'when entry config value is valid' do
|
|
||||||
context 'when config is a branch or tag name' do
|
|
||||||
let(:config) { %w[master feature/branch] }
|
|
||||||
|
|
||||||
describe '#valid?' do
|
|
||||||
it 'is valid' do
|
|
||||||
expect(entry).to be_valid
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '#value' do
|
|
||||||
it 'returns key value' do
|
|
||||||
expect(entry.value).to eq config
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when config is a regexp' do
|
|
||||||
let(:config) { ['/^issue-.*$/'] }
|
|
||||||
|
|
||||||
describe '#valid?' do
|
|
||||||
it 'is valid' do
|
|
||||||
expect(entry).to be_valid
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when config is a special keyword' do
|
|
||||||
let(:config) { %w[tags triggers branches] }
|
|
||||||
|
|
||||||
describe '#valid?' do
|
|
||||||
it 'is valid' do
|
|
||||||
expect(entry).to be_valid
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when entry value is not valid' do
|
|
||||||
let(:config) { [1] }
|
|
||||||
|
|
||||||
describe '#errors' do
|
|
||||||
it 'saves errors' do
|
|
||||||
expect(entry.errors)
|
|
||||||
.to include 'trigger config should be an array of strings or regexps'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,10 +1,10 @@
|
||||||
require 'spec_helper'
|
require 'spec_helper'
|
||||||
|
|
||||||
describe Gitlab::Ci::Config::Entry::Validatable do
|
describe Gitlab::Ci::Config::Entry::Validatable do
|
||||||
let(:entry) { Class.new }
|
let(:entry) do
|
||||||
|
Class.new(Gitlab::Ci::Config::Entry::Node) do
|
||||||
before do
|
include Gitlab::Ci::Config::Entry::Validatable
|
||||||
entry.include(described_class)
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '.validator' do
|
describe '.validator' do
|
||||||
|
@ -28,7 +28,7 @@ describe Gitlab::Ci::Config::Entry::Validatable do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when validating entry instance' do
|
context 'when validating entry instance' do
|
||||||
let(:entry_instance) { entry.new }
|
let(:entry_instance) { entry.new('something') }
|
||||||
|
|
||||||
context 'when attribute is valid' do
|
context 'when attribute is valid' do
|
||||||
before do
|
before do
|
||||||
|
|
|
@ -48,7 +48,7 @@ describe Gitlab::Ci::Config::Entry::Validator do
|
||||||
validator_instance.validate
|
validator_instance.validate
|
||||||
|
|
||||||
expect(validator_instance.messages)
|
expect(validator_instance.messages)
|
||||||
.to include "node test attribute can't be blank"
|
.to include /test attribute can't be blank/
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue