Integration variables collections with expressions

This commit is contained in:
Grzegorz Bizon 2018-03-23 13:44:12 +01:00
parent 96d6193cab
commit 8a2bc9b445
9 changed files with 71 additions and 45 deletions

View file

@ -8,9 +8,13 @@ module Gitlab
end
def satisfied_by?(pipeline, build)
variables = Gitlab::Ci::Variables::Collection
.new(build.simple_variables)
.to_hash
statements = @expressions.map do |statement|
::Gitlab::Ci::Pipeline::Expression::Statement
.new(statement, pipeline)
.new(statement, variables)
end
statements.any?(&:truthful?)

View file

@ -11,7 +11,7 @@ module Gitlab
end
def evaluate(variables = {})
HashWithIndifferentAccess.new(variables).fetch(@name, nil)
variables.with_indifferent_access.fetch(@name, nil)
end
def self.build(string)

View file

@ -14,24 +14,9 @@ module Gitlab
%w[variable]
].freeze
def initialize(statement, pipeline = nil)
def initialize(statement, variables = {})
@lexer = Expression::Lexer.new(statement)
return if pipeline.nil?
# REFACTORING, temporary refactoring stubs
#
@variables = pipeline.project.predefined_variables.map do |variable|
[variable[:key], variable[:value]]
end
@variables += pipeline.variables.map do |variable|
[variable.key, variable.value]
end
@variables += pipeline.predefined_variables.map do |variable|
[variable[:key], variable[:value]]
end
@variables = variables.with_indifferent_access
end
def parse_tree

View file

@ -30,7 +30,13 @@ module Gitlab
end
def to_runner_variables
self.map(&:to_hash)
self.map(&:to_runner_variable)
end
def to_hash
self.to_runner_variables
.map { |env| [env.fetch(:key), env.fetch(:value)] }
.to_h.with_indifferent_access
end
end
end

View file

@ -17,7 +17,7 @@ module Gitlab
end
def ==(other)
to_hash == self.class.fabricate(other).to_hash
to_runner_variable == self.class.fabricate(other).to_runner_variable
end
##
@ -25,7 +25,7 @@ module Gitlab
# don't expose `file` attribute at all (stems from what the runner
# expects).
#
def to_hash
def to_runner_variable
@variable.reject do |hash_key, hash_value|
hash_key == :file && hash_value == false
end

View file

@ -1,42 +1,58 @@
require 'spec_helper'
describe Gitlab::Ci::Build::Policy::Variables do
let(:pipeline) { build_stubbed(:ci_empty_pipeline, ref: 'master') }
let(:build) { build_stubbed(:ci_build, pipeline: pipeline, ref: 'master') }
set(:project) { create(:project) }
let(:ci_pipeline) do
build(:ci_empty_pipeline, project: project, ref: 'master')
end
let(:ci_build) do
build(:ci_build, pipeline: ci_pipeline, project: project, ref: 'master')
end
before do
pipeline.variables.build(key: 'CI_PROJECT_NAME', value: '')
ci_pipeline.variables.build(key: 'CI_PROJECT_NAME', value: '')
end
describe '#satisfied_by?' do
it 'is satisfied by a defined and existing variable' do
policy = described_class.new(['$CI_PROJECT_ID', '$UNDEFINED'])
expect(policy).to be_satisfied_by(pipeline, build)
expect(policy).to be_satisfied_by(ci_pipeline, ci_build)
end
it 'is not satisfied by an overriden empty variable' do
policy = described_class.new(['$CI_PROJECT_NAME'])
expect(policy).not_to be_satisfied_by(pipeline, build)
expect(policy).not_to be_satisfied_by(ci_pipeline, ci_build)
end
it 'is satisfied by a truthy pipeline expression' do
policy = described_class.new([%($CI_PIPELINE_SOURCE == "#{pipeline.source}")])
policy = described_class.new([%($CI_PIPELINE_SOURCE == "#{ci_pipeline.source}")])
expect(policy).to be_satisfied_by(pipeline, build)
expect(policy).to be_satisfied_by(ci_pipeline, ci_build)
end
it 'is not satisfied by a falsy pipeline expression' do
policy = described_class.new([%($CI_PIPELINE_SOURCE == "invalid source")])
expect(policy).not_to be_satisfied_by(pipeline, build)
expect(policy).not_to be_satisfied_by(ci_pipeline, ci_build)
end
it 'is satisfied by a truthy expression using undefined variable' do
policy = described_class.new(['$UNDEFINED', '$UNDEFINED == null'])
expect(policy).to be_satisfied_by(pipeline, build)
expect(policy).to be_satisfied_by(ci_pipeline, ci_build)
end
it 'does not persist neither pipeline nor build' do
described_class.new('$VAR').satisfied_by?(ci_pipeline, ci_build)
expect(ci_pipeline).not_to be_persisted
expect(ci_build).not_to be_persisted
end
pending 'test for secret variables'
end
end

View file

@ -1,22 +1,18 @@
require 'spec_helper'
describe Gitlab::Ci::Pipeline::Expression::Statement do
let(:pipeline) { build(:ci_pipeline) }
subject do
described_class.new(text, pipeline)
described_class.new(text, variables)
end
before do
variables = [{ key: 'PRESENT_VARIABLE', value: 'my variable' },
{ key: 'EMPTY_VARIABLE', value: '' }]
pipeline.variables.build(variables)
let(:variables) do
{ 'PRESENT_VARIABLE' => 'my variable',
EMPTY_VARIABLE: '' }
end
describe '.new' do
context 'when pipeline is not provided' do
it 'allows to properly initialize the statement' do
context 'when variables are not provided' do
it 'allows to properly initializes the statement' do
statement = described_class.new('$PRESENT_VARIABLE')
expect(statement.evaluate).to be_nil

View file

@ -46,9 +46,13 @@ describe Gitlab::Ci::Variables::Collection::Item do
end
end
describe '#to_hash' do
it 'returns a hash representation of a collection item' do
expect(described_class.new(**variable).to_hash).to eq variable
describe '#to_runner_variable' do
it 'returns a runner-compatible hash representation' do
runner_variable = described_class
.new(**variable)
.to_runner_variable
expect(runner_variable).to eq variable
end
end
end

View file

@ -7,7 +7,7 @@ describe Gitlab::Ci::Variables::Collection do
collection = described_class.new([variable])
expect(collection.first.to_hash).to eq variable
expect(collection.first.to_runner_variable).to eq variable
end
it 'can be initialized without an argument' do
@ -96,4 +96,19 @@ describe Gitlab::Ci::Variables::Collection do
.to eq [{ key: 'TEST', value: 1, public: true }]
end
end
describe '#to_hash' do
it 'returns regular hash in valid order without duplicates' do
collection = described_class.new
.append(key: 'TEST1', value: 'test-1')
.append(key: 'TEST2', value: 'test-2')
.append(key: 'TEST1', value: 'test-3')
expect(collection.to_hash).to eq('TEST1' => 'test-3',
'TEST2' => 'test-2')
expect(collection.to_hash).to include(TEST1: 'test-3')
expect(collection.to_hash).not_to include(TEST1: 'test-1')
end
end
end