Commit 002e6ed1 authored by Grzegorz Bizon's avatar Grzegorz Bizon

Improve CI config entries validations prototype

parent 95520dfc
...@@ -15,6 +15,7 @@ module Gitlab ...@@ -15,6 +15,7 @@ module Gitlab
# #
module Configurable module Configurable
extend ActiveSupport::Concern extend ActiveSupport::Concern
include Validatable
included do included do
validations do validations do
...@@ -28,10 +29,6 @@ module Gitlab ...@@ -28,10 +29,6 @@ module Gitlab
end end
end end
def allowed_nodes
self.class.allowed_nodes || {}
end
private private
def create_node(key, factory) def create_node(key, factory)
...@@ -41,7 +38,7 @@ module Gitlab ...@@ -41,7 +38,7 @@ module Gitlab
end end
class_methods do class_methods do
def allowed_nodes def nodes
Hash[@allowed_nodes.map { |key, factory| [key, factory.dup] }] Hash[@allowed_nodes.map { |key, factory| [key, factory.dup] }]
end end
......
...@@ -7,7 +7,6 @@ module Gitlab ...@@ -7,7 +7,6 @@ module Gitlab
# #
class Entry class Entry
class InvalidError < StandardError; end class InvalidError < StandardError; end
include Validatable
attr_reader :config attr_reader :config
attr_accessor :key, :description attr_accessor :key, :description
...@@ -16,6 +15,7 @@ module Gitlab ...@@ -16,6 +15,7 @@ module Gitlab
@config = config @config = config
@nodes = {} @nodes = {}
@validator = self.class.validator.new(self) @validator = self.class.validator.new(self)
@validator.validate
end end
def process! def process!
...@@ -31,7 +31,7 @@ module Gitlab ...@@ -31,7 +31,7 @@ module Gitlab
end end
def leaf? def leaf?
allowed_nodes.none? self.class.nodes.none?
end end
def key def key
...@@ -47,18 +47,22 @@ module Gitlab ...@@ -47,18 +47,22 @@ module Gitlab
nodes.map(&:errors).flatten nodes.map(&:errors).flatten
end end
def allowed_nodes def value
raise NotImplementedError
end
def self.nodes
{} {}
end end
def value def self.validator
raise NotImplementedError Validator
end end
private private
def compose! def compose!
allowed_nodes.each do |key, essence| self.class.nodes.each do |key, essence|
@nodes[key] = create_node(key, essence) @nodes[key] = create_node(key, essence)
end end
end end
......
...@@ -11,6 +11,8 @@ module Gitlab ...@@ -11,6 +11,8 @@ module Gitlab
# implementation in Runner. # implementation in Runner.
# #
class Script < Entry class Script < Entry
include Validatable
validations do validations do
include ValidationHelpers include ValidationHelpers
......
...@@ -8,7 +8,6 @@ module Gitlab ...@@ -8,7 +8,6 @@ module Gitlab
class_methods do class_methods do
def validator def validator
validator = Class.new(Node::Validator) validator = Class.new(Node::Validator)
validator.include(ActiveModel::Validations)
if defined?(@validations) if defined?(@validations)
@validations.each { |rules| validator.class_eval(&rules) } @validations.each { |rules| validator.class_eval(&rules) }
......
...@@ -3,10 +3,11 @@ module Gitlab ...@@ -3,10 +3,11 @@ module Gitlab
class Config class Config
module Node module Node
class Validator < SimpleDelegator class Validator < SimpleDelegator
include ActiveModel::Validations
def initialize(node) def initialize(node)
@node = node
super(node) super(node)
validate @node = node
end end
def full_errors def full_errors
......
...@@ -4,30 +4,29 @@ describe Gitlab::Ci::Config::Node::Configurable do ...@@ -4,30 +4,29 @@ describe Gitlab::Ci::Config::Node::Configurable do
let(:node) { Class.new } let(:node) { Class.new }
before do before do
node.include(Gitlab::Ci::Config::Node::Validatable)
node.include(described_class) node.include(described_class)
end end
describe 'allowed nodes' do describe 'configured nodes' do
before do before do
node.class_eval do node.class_eval do
allow_node :object, Object, description: 'test object' allow_node :object, Object, description: 'test object'
end end
end end
describe '#allowed_nodes' do describe '.nodes' do
it 'has valid allowed nodes' do it 'has valid nodes' do
expect(node.allowed_nodes).to include :object expect(node.nodes).to include :object
end end
it 'creates a node factory' do it 'creates a node factory' do
expect(node.allowed_nodes[:object]) expect(node.nodes[:object])
.to be_an_instance_of Gitlab::Ci::Config::Node::Factory .to be_an_instance_of Gitlab::Ci::Config::Node::Factory
end end
it 'returns a duplicated factory object' do it 'returns a duplicated factory object' do
first_factory = node.allowed_nodes[:object] first_factory = node.nodes[:object]
second_factory = node.allowed_nodes[:object] second_factory = node.nodes[:object]
expect(first_factory).not_to be_equal(second_factory) expect(first_factory).not_to be_equal(second_factory)
end end
......
...@@ -3,13 +3,13 @@ require 'spec_helper' ...@@ -3,13 +3,13 @@ require 'spec_helper'
describe Gitlab::Ci::Config::Node::Global do describe Gitlab::Ci::Config::Node::Global do
let(:global) { described_class.new(hash) } let(:global) { described_class.new(hash) }
describe '#allowed_nodes' do describe '.nodes' do
it 'can contain global config keys' do it 'can contain global config keys' do
expect(global.allowed_nodes).to include :before_script expect(described_class.nodes).to include :before_script
end end
it 'returns a hash' do it 'returns a hash' do
expect(global.allowed_nodes).to be_a Hash expect(described_class.nodes).to be_a Hash
end end
end end
......
require 'spec_helper'
describe Gitlab::Ci::Config::Node::Validatable do
let(:node) { Class.new }
before do
node.include(described_class)
end
describe '.validator' do
before do
node.class_eval do
attr_accessor :test_attribute
validations do
validates :test_attribute, presence: true
end
end
end
it 'returns validator' do
expect(node.validator.superclass)
.to be Gitlab::Ci::Config::Node::Validator
end
context 'when validating node instance' do
let(:node_instance) { node.new }
context 'when attribute is valid' do
before do
node_instance.test_attribute = 'valid'
end
it 'instance of validator is valid' do
expect(node.validator.new(node_instance)).to be_valid
end
end
context 'when attribute is not valid' do
before do
node_instance.test_attribute = nil
end
it 'instance of validator is invalid' do
expect(node.validator.new(node_instance)).to be_invalid
end
end
end
end
end
require 'spec_helper'
describe Gitlab::Ci::Config::Node::Validator do
let(:validator) { Class.new(described_class) }
let(:validator_instance) { validator.new(node) }
let(:node) { spy('node') }
shared_examples 'delegated validator' do
context 'when node is valid' do
before do
allow(node).to receive(:test_attribute).and_return('valid value')
end
it 'validates attribute in node' do
expect(node).to receive(:test_attribute)
expect(validator_instance).to be_valid
end
it 'returns no errors' do
validator_instance.validate
expect(validator_instance.full_errors).to be_empty
end
end
context 'when node is invalid' do
before do
allow(node).to receive(:test_attribute).and_return(nil)
end
it 'validates attribute in node' do
expect(node).to receive(:test_attribute)
expect(validator_instance).to be_invalid
end
it 'returns errors' do
validator_instance.validate
expect(validator_instance.full_errors).not_to be_empty
end
end
end
describe 'attributes validations' do
before do
validator.class_eval do
validates :test_attribute, presence: true
end
end
it_behaves_like 'delegated validator'
end
describe 'interface validations' do
before do
validator.class_eval do
validate do
unless @node.test_attribute == 'valid value'
errors.add(:test_attribute, 'invalid value')
end
end
end
end
it_behaves_like 'delegated validator'
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