diff options
Diffstat (limited to 'spec/lib/gitlab/ci/config')
-rw-r--r-- | spec/lib/gitlab/ci/config/entry/environment_spec.rb | 10 | ||||
-rw-r--r-- | spec/lib/gitlab/ci/config/entry/image_spec.rb | 27 | ||||
-rw-r--r-- | spec/lib/gitlab/ci/config/entry/job_spec.rb | 3 | ||||
-rw-r--r-- | spec/lib/gitlab/ci/config/entry/legacy_variables_spec.rb | 173 | ||||
-rw-r--r-- | spec/lib/gitlab/ci/config/entry/port_spec.rb | 2 | ||||
-rw-r--r-- | spec/lib/gitlab/ci/config/entry/processable_spec.rb | 32 | ||||
-rw-r--r-- | spec/lib/gitlab/ci/config/entry/product/matrix_spec.rb | 2 | ||||
-rw-r--r-- | spec/lib/gitlab/ci/config/entry/root_spec.rb | 149 | ||||
-rw-r--r-- | spec/lib/gitlab/ci/config/entry/rules/rule_spec.rb | 18 | ||||
-rw-r--r-- | spec/lib/gitlab/ci/config/entry/service_spec.rb | 25 | ||||
-rw-r--r-- | spec/lib/gitlab/ci/config/entry/variable_spec.rb | 212 | ||||
-rw-r--r-- | spec/lib/gitlab/ci/config/entry/variables_spec.rb | 82 | ||||
-rw-r--r-- | spec/lib/gitlab/ci/config/external/file/remote_spec.rb | 39 | ||||
-rw-r--r-- | spec/lib/gitlab/ci/config/external/mapper_spec.rb | 4 | ||||
-rw-r--r-- | spec/lib/gitlab/ci/config/external/processor_spec.rb | 30 |
15 files changed, 659 insertions, 149 deletions
diff --git a/spec/lib/gitlab/ci/config/entry/environment_spec.rb b/spec/lib/gitlab/ci/config/entry/environment_spec.rb index 36c26c8ee4f..3562706ff33 100644 --- a/spec/lib/gitlab/ci/config/entry/environment_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/environment_spec.rb @@ -230,12 +230,12 @@ RSpec.describe Gitlab::Ci::Config::Entry::Environment do end end - context 'when auto_stop_in is invalid format' do - let(:auto_stop_in) { 'invalid' } + context 'when variables are used for auto_stop_in' do + let(:auto_stop_in) { '$TTL' } - it 'becomes invalid' do - expect(entry).not_to be_valid - expect(entry.errors).to include 'environment auto stop in should be a duration' + it 'becomes valid' do + expect(entry).to be_valid + expect(entry.auto_stop_in).to eq(auto_stop_in) end end end diff --git a/spec/lib/gitlab/ci/config/entry/image_spec.rb b/spec/lib/gitlab/ci/config/entry/image_spec.rb index 6121c28070f..b37498ba10a 100644 --- a/spec/lib/gitlab/ci/config/entry/image_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/image_spec.rb @@ -4,8 +4,6 @@ require 'spec_helper' RSpec.describe Gitlab::Ci::Config::Entry::Image do before do - stub_feature_flags(ci_docker_image_pull_policy: true) - entry.compose! end @@ -129,18 +127,6 @@ RSpec.describe Gitlab::Ci::Config::Entry::Image do it 'is valid' do expect(entry).to be_valid end - - context 'when the feature flag ci_docker_image_pull_policy is disabled' do - before do - stub_feature_flags(ci_docker_image_pull_policy: false) - entry.compose! - end - - it 'is not valid' do - expect(entry).not_to be_valid - expect(entry.errors).to include('image config contains unknown keys: pull_policy') - end - end end describe '#value' do @@ -150,19 +136,6 @@ RSpec.describe Gitlab::Ci::Config::Entry::Image do pull_policy: ['if-not-present'] ) end - - context 'when the feature flag ci_docker_image_pull_policy is disabled' do - before do - stub_feature_flags(ci_docker_image_pull_policy: false) - entry.compose! - end - - it 'is not valid' do - expect(entry.value).to eq( - name: 'image:1.0' - ) - end - end end end end diff --git a/spec/lib/gitlab/ci/config/entry/job_spec.rb b/spec/lib/gitlab/ci/config/entry/job_spec.rb index ca336c3ecaa..75ac2ca87ab 100644 --- a/spec/lib/gitlab/ci/config/entry/job_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/job_spec.rb @@ -605,8 +605,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Job do let(:deps) do double('deps', 'default_entry' => default, - 'workflow_entry' => workflow, - 'variables_value' => nil) + 'workflow_entry' => workflow) end context 'when job config overrides default config' do diff --git a/spec/lib/gitlab/ci/config/entry/legacy_variables_spec.rb b/spec/lib/gitlab/ci/config/entry/legacy_variables_spec.rb new file mode 100644 index 00000000000..e9edec9a0a4 --- /dev/null +++ b/spec/lib/gitlab/ci/config/entry/legacy_variables_spec.rb @@ -0,0 +1,173 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Ci::Config::Entry::LegacyVariables do + let(:config) { {} } + let(:metadata) { {} } + + subject(:entry) { described_class.new(config, **metadata) } + + before do + entry.compose! + end + + shared_examples 'valid config' do + describe '#value' do + it 'returns hash with key value strings' do + expect(entry.value).to eq result + end + end + + describe '#errors' do + it 'does not append errors' do + expect(entry.errors).to be_empty + end + end + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + end + + shared_examples 'invalid config' do |error_message| + describe '#valid?' do + it 'is not valid' do + expect(entry).not_to be_valid + end + end + + describe '#errors' do + it 'saves errors' do + expect(entry.errors) + .to include(error_message) + end + end + end + + context 'when entry config value has key-value pairs' do + let(:config) do + { 'VARIABLE_1' => 'value 1', 'VARIABLE_2' => 'value 2' } + end + + let(:result) do + { 'VARIABLE_1' => 'value 1', 'VARIABLE_2' => 'value 2' } + end + + it_behaves_like 'valid config' + + describe '#value_with_data' do + it 'returns variable with data' do + expect(entry.value_with_data).to eq( + 'VARIABLE_1' => { value: 'value 1' }, + 'VARIABLE_2' => { value: 'value 2' } + ) + end + end + end + + context 'with numeric keys and values in the config' do + let(:config) { { 10 => 20 } } + let(:result) do + { '10' => '20' } + end + + it_behaves_like 'valid config' + end + + context 'when key is an array' do + let(:config) { { ['VAR1'] => 'val1' } } + let(:result) do + { 'VAR1' => 'val1' } + end + + it_behaves_like 'invalid config', /should be a hash of key value pairs/ + end + + context 'when value is a symbol' do + let(:config) { { 'VAR1' => :val1 } } + let(:result) do + { 'VAR1' => 'val1' } + end + + it_behaves_like 'valid config' + end + + context 'when value is a boolean' do + let(:config) { { 'VAR1' => true } } + let(:result) do + { 'VAR1' => 'val1' } + end + + it_behaves_like 'invalid config', /should be a hash of key value pairs/ + end + + context 'when entry config value has key-value pair and hash' do + let(:config) do + { 'VARIABLE_1' => { value: 'value 1', description: 'variable 1' }, + 'VARIABLE_2' => 'value 2' } + end + + it_behaves_like 'invalid config', /should be a hash of key value pairs/ + + context 'when metadata has use_value_data: true' do + let(:metadata) { { use_value_data: true } } + + let(:result) do + { 'VARIABLE_1' => 'value 1', 'VARIABLE_2' => 'value 2' } + end + + it_behaves_like 'valid config' + + describe '#value_with_data' do + it 'returns variable with data' do + expect(entry.value_with_data).to eq( + 'VARIABLE_1' => { value: 'value 1', description: 'variable 1' }, + 'VARIABLE_2' => { value: 'value 2' } + ) + end + end + end + end + + context 'when entry value is an array' do + let(:config) { [:VAR, 'test'] } + + it_behaves_like 'invalid config', /should be a hash of key value pairs/ + end + + context 'when metadata has use_value_data: true' do + let(:metadata) { { use_value_data: true } } + + context 'when entry value has hash with other key-pairs' do + let(:config) do + { 'VARIABLE_1' => { value: 'value 1', hello: 'variable 1' }, + 'VARIABLE_2' => 'value 2' } + end + + it_behaves_like 'invalid config', /should be a hash of key value pairs, value can be a hash/ + end + + context 'when entry config value has hash with nil description' do + let(:config) do + { 'VARIABLE_1' => { value: 'value 1', description: nil } } + end + + it_behaves_like 'invalid config', /should be a hash of key value pairs, value can be a hash/ + end + + context 'when entry config value has hash without description' do + let(:config) do + { 'VARIABLE_1' => { value: 'value 1' } } + end + + let(:result) do + { 'VARIABLE_1' => 'value 1' } + end + + it_behaves_like 'valid config' + end + end +end diff --git a/spec/lib/gitlab/ci/config/entry/port_spec.rb b/spec/lib/gitlab/ci/config/entry/port_spec.rb index e2840c07f6b..77f846f95f0 100644 --- a/spec/lib/gitlab/ci/config/entry/port_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/port_spec.rb @@ -48,7 +48,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Port do let(:config) do { number: 80, protocol: 'http', - name: 'foobar' } + name: 'foobar' } end describe '#valid?' do diff --git a/spec/lib/gitlab/ci/config/entry/processable_spec.rb b/spec/lib/gitlab/ci/config/entry/processable_spec.rb index 714b0a3b6aa..5f42a8c49a7 100644 --- a/spec/lib/gitlab/ci/config/entry/processable_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/processable_spec.rb @@ -197,6 +197,34 @@ RSpec.describe Gitlab::Ci::Config::Entry::Processable do end end end + + context 'when a variable has an invalid data attribute' do + let(:config) do + { + script: 'echo', + variables: { 'VAR1' => 'val 1', 'VAR2' => { value: 'val 2', description: 'hello var 2' } } + } + end + + it 'reports error about variable' do + expect(entry.errors) + .to include 'variables:var2 config must be a string' + end + + context 'when the FF ci_variables_refactoring_to_variable is disabled' do + let(:entry_without_ff) { node_class.new(config, name: :rspec) } + + before do + stub_feature_flags(ci_variables_refactoring_to_variable: false) + entry_without_ff.compose! + end + + it 'reports error about variable' do + expect(entry_without_ff.errors) + .to include /config should be a hash of key value pairs/ + end + end + end end end @@ -212,13 +240,11 @@ RSpec.describe Gitlab::Ci::Config::Entry::Processable do let(:unspecified) { double('unspecified', 'specified?' => false) } let(:default) { double('default', '[]' => unspecified) } let(:workflow) { double('workflow', 'has_rules?' => false) } - let(:variables) {} let(:deps) do double('deps', default_entry: default, - workflow_entry: workflow, - variables_value: variables) + workflow_entry: workflow) end context 'with workflow rules' do diff --git a/spec/lib/gitlab/ci/config/entry/product/matrix_spec.rb b/spec/lib/gitlab/ci/config/entry/product/matrix_spec.rb index ff44a235ea5..394d91466bf 100644 --- a/spec/lib/gitlab/ci/config/entry/product/matrix_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/product/matrix_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'spec_helper' +require 'fast_spec_helper' require_dependency 'active_model' RSpec.describe ::Gitlab::Ci::Config::Entry::Product::Matrix do diff --git a/spec/lib/gitlab/ci/config/entry/root_spec.rb b/spec/lib/gitlab/ci/config/entry/root_spec.rb index 55ad119ea21..3d19987a0be 100644 --- a/spec/lib/gitlab/ci/config/entry/root_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/root_spec.rb @@ -117,49 +117,49 @@ RSpec.describe Gitlab::Ci::Config::Entry::Root do expect(root.jobs_value.keys).to eq([:rspec, :spinach, :release]) expect(root.jobs_value[:rspec]).to eq( { name: :rspec, - script: %w[rspec ls], - before_script: %w(ls pwd), - image: { name: 'image:1.0' }, - services: [{ name: 'postgres:9.1' }, { name: 'mysql:5.5' }], - stage: 'test', - cache: [{ key: 'k', untracked: true, paths: ['public/'], policy: 'pull-push', when: 'on_success' }], - job_variables: {}, - root_variables_inheritance: true, - ignore: false, - after_script: ['make clean'], - only: { refs: %w[branches tags] }, - scheduling_type: :stage } + script: %w[rspec ls], + before_script: %w(ls pwd), + image: { name: 'image:1.0' }, + services: [{ name: 'postgres:9.1' }, { name: 'mysql:5.5' }], + stage: 'test', + cache: [{ key: 'k', untracked: true, paths: ['public/'], policy: 'pull-push', when: 'on_success' }], + job_variables: {}, + root_variables_inheritance: true, + ignore: false, + after_script: ['make clean'], + only: { refs: %w[branches tags] }, + scheduling_type: :stage } ) expect(root.jobs_value[:spinach]).to eq( { name: :spinach, - before_script: [], - script: %w[spinach], - image: { name: 'image:1.0' }, - services: [{ name: 'postgres:9.1' }, { name: 'mysql:5.5' }], - stage: 'test', - cache: [{ key: 'k', untracked: true, paths: ['public/'], policy: 'pull-push', when: 'on_success' }], - job_variables: {}, - root_variables_inheritance: true, - ignore: false, - after_script: ['make clean'], - only: { refs: %w[branches tags] }, - scheduling_type: :stage } + before_script: [], + script: %w[spinach], + image: { name: 'image:1.0' }, + services: [{ name: 'postgres:9.1' }, { name: 'mysql:5.5' }], + stage: 'test', + cache: [{ key: 'k', untracked: true, paths: ['public/'], policy: 'pull-push', when: 'on_success' }], + job_variables: {}, + root_variables_inheritance: true, + ignore: false, + after_script: ['make clean'], + only: { refs: %w[branches tags] }, + scheduling_type: :stage } ) expect(root.jobs_value[:release]).to eq( { name: :release, - stage: 'release', - before_script: [], - script: ["make changelog | tee release_changelog.txt"], - release: { name: "Release $CI_TAG_NAME", tag_name: 'v0.06', description: "./release_changelog.txt" }, - image: { name: "image:1.0" }, - services: [{ name: "postgres:9.1" }, { name: "mysql:5.5" }], - cache: [{ key: "k", untracked: true, paths: ["public/"], policy: "pull-push", when: 'on_success' }], - only: { refs: %w(branches tags) }, - job_variables: { 'VAR' => 'job' }, - root_variables_inheritance: true, - after_script: [], - ignore: false, - scheduling_type: :stage } + stage: 'release', + before_script: [], + script: ["make changelog | tee release_changelog.txt"], + release: { name: "Release $CI_TAG_NAME", tag_name: 'v0.06', description: "./release_changelog.txt" }, + image: { name: "image:1.0" }, + services: [{ name: "postgres:9.1" }, { name: "mysql:5.5" }], + cache: [{ key: "k", untracked: true, paths: ["public/"], policy: "pull-push", when: 'on_success' }], + only: { refs: %w(branches tags) }, + job_variables: { 'VAR' => { value: 'job' } }, + root_variables_inheritance: true, + after_script: [], + ignore: false, + scheduling_type: :stage } ) end end @@ -196,31 +196,31 @@ RSpec.describe Gitlab::Ci::Config::Entry::Root do it 'returns jobs configuration' do expect(root.jobs_value).to eq( rspec: { name: :rspec, - script: %w[rspec ls], - before_script: %w(ls pwd), - image: { name: 'image:1.0' }, - services: [{ name: 'postgres:9.1' }, { name: 'mysql:5.5' }], - stage: 'test', - cache: [{ key: 'k', untracked: true, paths: ['public/'], policy: 'pull-push', when: 'on_success' }], - job_variables: {}, - root_variables_inheritance: true, - ignore: false, - after_script: ['make clean'], - only: { refs: %w[branches tags] }, - scheduling_type: :stage }, + script: %w[rspec ls], + before_script: %w(ls pwd), + image: { name: 'image:1.0' }, + services: [{ name: 'postgres:9.1' }, { name: 'mysql:5.5' }], + stage: 'test', + cache: [{ key: 'k', untracked: true, paths: ['public/'], policy: 'pull-push', when: 'on_success' }], + job_variables: {}, + root_variables_inheritance: true, + ignore: false, + after_script: ['make clean'], + only: { refs: %w[branches tags] }, + scheduling_type: :stage }, spinach: { name: :spinach, - before_script: [], - script: %w[spinach], - image: { name: 'image:1.0' }, - services: [{ name: 'postgres:9.1' }, { name: 'mysql:5.5' }], - stage: 'test', - cache: [{ key: 'k', untracked: true, paths: ['public/'], policy: 'pull-push', when: 'on_success' }], - job_variables: { 'VAR' => 'job' }, - root_variables_inheritance: true, - ignore: false, - after_script: ['make clean'], - only: { refs: %w[branches tags] }, - scheduling_type: :stage } + before_script: [], + script: %w[spinach], + image: { name: 'image:1.0' }, + services: [{ name: 'postgres:9.1' }, { name: 'mysql:5.5' }], + stage: 'test', + cache: [{ key: 'k', untracked: true, paths: ['public/'], policy: 'pull-push', when: 'on_success' }], + job_variables: { 'VAR' => { value: 'job' } }, + root_variables_inheritance: true, + ignore: false, + after_script: ['make clean'], + only: { refs: %w[branches tags] }, + scheduling_type: :stage } ) end end @@ -350,6 +350,33 @@ RSpec.describe Gitlab::Ci::Config::Entry::Root do end end end + + context 'when a variable has an invalid data key' do + let(:hash) do + { variables: { VAR1: { invalid: 'hello' } }, rspec: { script: 'hello' } } + end + + describe '#errors' do + it 'reports errors about the invalid variable' do + expect(root.errors) + .to include /var1 config uses invalid data keys: invalid/ + end + + context 'when the FF ci_variables_refactoring_to_variable is disabled' do + let(:root_without_ff) { described_class.new(hash, user: user, project: project) } + + before do + stub_feature_flags(ci_variables_refactoring_to_variable: false) + root_without_ff.compose! + end + + it 'reports errors about the invalid variable' do + expect(root_without_ff.errors) + .to include /variables config should be a hash of key value pairs, value can be a hash/ + end + end + end + end end context 'when value is not a hash' do diff --git a/spec/lib/gitlab/ci/config/entry/rules/rule_spec.rb b/spec/lib/gitlab/ci/config/entry/rules/rule_spec.rb index c85fe366da6..303d825c591 100644 --- a/spec/lib/gitlab/ci/config/entry/rules/rule_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/rules/rule_spec.rb @@ -1,8 +1,7 @@ # frozen_string_literal: true -require 'fast_spec_helper' +require 'spec_helper' require 'gitlab_chronic_duration' -require_dependency 'active_model' RSpec.describe Gitlab::Ci::Config::Entry::Rules::Rule do let(:factory) do @@ -363,7 +362,20 @@ RSpec.describe Gitlab::Ci::Config::Entry::Rules::Rule do it { is_expected.not_to be_valid } it 'returns an error about invalid variables:' do - expect(subject.errors).to include(/variables config should be a hash of key value pairs/) + expect(subject.errors).to include(/variables config should be a hash/) + end + + context 'when the FF ci_variables_refactoring_to_variable is disabled' do + let(:entry_without_ff) { factory.create! } + + before do + stub_feature_flags(ci_variables_refactoring_to_variable: false) + entry_without_ff.compose! + end + + it 'returns an error about invalid variables:' do + expect(subject.errors).to include(/variables config should be a hash/) + end end end end diff --git a/spec/lib/gitlab/ci/config/entry/service_spec.rb b/spec/lib/gitlab/ci/config/entry/service_spec.rb index 821ab442d61..e36484bb0ae 100644 --- a/spec/lib/gitlab/ci/config/entry/service_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/service_spec.rb @@ -4,7 +4,6 @@ require 'spec_helper' RSpec.describe Gitlab::Ci::Config::Entry::Service do before do - stub_feature_flags(ci_docker_image_pull_policy: true) entry.compose! end @@ -149,18 +148,6 @@ RSpec.describe Gitlab::Ci::Config::Entry::Service do it 'is valid' do expect(entry).to be_valid end - - context 'when the feature flag ci_docker_image_pull_policy is disabled' do - before do - stub_feature_flags(ci_docker_image_pull_policy: false) - entry.compose! - end - - it 'is not valid' do - expect(entry).not_to be_valid - expect(entry.errors).to include('service config contains unknown keys: pull_policy') - end - end end describe '#value' do @@ -170,18 +157,6 @@ RSpec.describe Gitlab::Ci::Config::Entry::Service do pull_policy: ['if-not-present'] ) end - - context 'when the feature flag ci_docker_image_pull_policy is disabled' do - before do - stub_feature_flags(ci_docker_image_pull_policy: false) - end - - it 'is not valid' do - expect(entry.value).to eq( - name: 'postgresql:9.5' - ) - end - end end end end diff --git a/spec/lib/gitlab/ci/config/entry/variable_spec.rb b/spec/lib/gitlab/ci/config/entry/variable_spec.rb new file mode 100644 index 00000000000..744a89d4509 --- /dev/null +++ b/spec/lib/gitlab/ci/config/entry/variable_spec.rb @@ -0,0 +1,212 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Ci::Config::Entry::Variable do + let(:config) { {} } + let(:metadata) { {} } + + subject(:entry) do + described_class.new(config, **metadata).tap do |entry| + entry.key = 'VAR1' # composable_hash requires key to be set + end + end + + before do + entry.compose! + end + + describe 'SimpleVariable' do + context 'when config is a string' do + let(:config) { 'value' } + + describe '#valid?' do + it { is_expected.to be_valid } + end + + describe '#value' do + subject(:value) { entry.value } + + it { is_expected.to eq('value') } + end + end + + context 'when config is an integer' do + let(:config) { 1 } + + describe '#valid?' do + it { is_expected.to be_valid } + end + + describe '#value' do + subject(:value) { entry.value } + + it { is_expected.to eq('1') } + end + end + + context 'when config is an array' do + let(:config) { [] } + + describe '#valid?' do + it { is_expected.not_to be_valid } + end + + describe '#errors' do + subject(:errors) { entry.errors } + + it { is_expected.to include 'variable definition must be either a string or a hash' } + end + end + end + + describe 'ComplexVariable' do + context 'when config is a hash with description' do + let(:config) { { value: 'value', description: 'description' } } + + context 'when metadata allowed_value_data is not provided' do + describe '#valid?' do + it { is_expected.not_to be_valid } + end + + describe '#errors' do + subject(:errors) { entry.errors } + + it { is_expected.to include 'var1 config must be a string' } + end + end + + context 'when metadata allowed_value_data is (value, description)' do + let(:metadata) { { allowed_value_data: %i[value description] } } + + describe '#valid?' do + it { is_expected.to be_valid } + end + + describe '#value' do + subject(:value) { entry.value } + + it { is_expected.to eq('value') } + end + + describe '#value_with_data' do + subject(:value_with_data) { entry.value_with_data } + + it { is_expected.to eq(value: 'value', description: 'description') } + end + + context 'when config value is a symbol' do + let(:config) { { value: :value, description: 'description' } } + + describe '#value' do + subject(:value) { entry.value } + + it { is_expected.to eq('value') } + end + + describe '#value_with_data' do + subject(:value_with_data) { entry.value_with_data } + + it { is_expected.to eq(value: 'value', description: 'description') } + end + end + + context 'when config value is an integer' do + let(:config) { { value: 123, description: 'description' } } + + describe '#value' do + subject(:value) { entry.value } + + it { is_expected.to eq('123') } + end + + describe '#value_with_data' do + subject(:value_with_data) { entry.value_with_data } + + it { is_expected.to eq(value: '123', description: 'description') } + end + end + + context 'when config value is an array' do + let(:config) { { value: ['value'], description: 'description' } } + + describe '#valid?' do + it { is_expected.not_to be_valid } + end + + describe '#errors' do + subject(:errors) { entry.errors } + + it { is_expected.to include 'var1 config value must be an alphanumeric string' } + end + end + + context 'when config description is a symbol' do + let(:config) { { value: 'value', description: :description } } + + describe '#value' do + subject(:value) { entry.value } + + it { is_expected.to eq('value') } + end + + describe '#value_with_data' do + subject(:value_with_data) { entry.value_with_data } + + it { is_expected.to eq(value: 'value', description: :description) } + end + end + end + + context 'when metadata allowed_value_data is (value, xyz)' do + let(:metadata) { { allowed_value_data: %i[value xyz] } } + + describe '#valid?' do + it { is_expected.not_to be_valid } + end + + describe '#errors' do + subject(:errors) { entry.errors } + + it { is_expected.to include 'var1 config uses invalid data keys: description' } + end + end + end + + context 'when config is a hash without description' do + let(:config) { { value: 'value' } } + + context 'when metadata allowed_value_data is not provided' do + describe '#valid?' do + it { is_expected.not_to be_valid } + end + + describe '#errors' do + subject(:errors) { entry.errors } + + it { is_expected.to include 'var1 config must be a string' } + end + end + + context 'when metadata allowed_value_data is (value, description)' do + let(:metadata) { { allowed_value_data: %i[value description] } } + + describe '#valid?' do + it { is_expected.to be_valid } + end + + describe '#value' do + subject(:value) { entry.value } + + it { is_expected.to eq('value') } + end + + describe '#value_with_data' do + subject(:value_with_data) { entry.value_with_data } + + it { is_expected.to eq(value: 'value') } + end + end + end + end +end diff --git a/spec/lib/gitlab/ci/config/entry/variables_spec.rb b/spec/lib/gitlab/ci/config/entry/variables_spec.rb index 78d37e228df..ad7290d0589 100644 --- a/spec/lib/gitlab/ci/config/entry/variables_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/variables_spec.rb @@ -3,41 +3,46 @@ require 'spec_helper' RSpec.describe Gitlab::Ci::Config::Entry::Variables do + let(:config) { {} } let(:metadata) { {} } - subject { described_class.new(config, **metadata) } + subject(:entry) { described_class.new(config, **metadata) } + + before do + entry.compose! + end shared_examples 'valid config' do describe '#value' do it 'returns hash with key value strings' do - expect(subject.value).to eq result + expect(entry.value).to eq result end end describe '#errors' do it 'does not append errors' do - expect(subject.errors).to be_empty + expect(entry.errors).to be_empty end end describe '#valid?' do it 'is valid' do - expect(subject).to be_valid + expect(entry).to be_valid end end end - shared_examples 'invalid config' do + shared_examples 'invalid config' do |error_message| describe '#valid?' do it 'is not valid' do - expect(subject).not_to be_valid + expect(entry).not_to be_valid end end describe '#errors' do it 'saves errors' do - expect(subject.errors) - .to include /should be a hash of key value pairs/ + expect(entry.errors) + .to include(error_message) end end end @@ -52,6 +57,15 @@ RSpec.describe Gitlab::Ci::Config::Entry::Variables do end it_behaves_like 'valid config' + + describe '#value_with_data' do + it 'returns variable with data' do + expect(entry.value_with_data).to eq( + 'VARIABLE_1' => { value: 'value 1' }, + 'VARIABLE_2' => { value: 'value 2' } + ) + end + end end context 'with numeric keys and values in the config' do @@ -63,33 +77,63 @@ RSpec.describe Gitlab::Ci::Config::Entry::Variables do it_behaves_like 'valid config' end + context 'when key is an array' do + let(:config) { { ['VAR1'] => 'val1' } } + + it_behaves_like 'invalid config', /must be an alphanumeric string/ + end + + context 'when value is a symbol' do + let(:config) { { 'VAR1' => :val1 } } + let(:result) do + { 'VAR1' => 'val1' } + end + + it_behaves_like 'valid config' + end + + context 'when value is a boolean' do + let(:config) { { 'VAR1' => true } } + + it_behaves_like 'invalid config', /must be either a string or a hash/ + end + context 'when entry config value has key-value pair and hash' do let(:config) do { 'VARIABLE_1' => { value: 'value 1', description: 'variable 1' }, 'VARIABLE_2' => 'value 2' } end - let(:result) do - { 'VARIABLE_1' => 'value 1', 'VARIABLE_2' => 'value 2' } - end + it_behaves_like 'invalid config', /variable_1 config must be a string/ - it_behaves_like 'invalid config' + context 'when metadata has allowed_value_data' do + let(:metadata) { { allowed_value_data: %i[value description] } } - context 'when metadata has use_value_data' do - let(:metadata) { { use_value_data: true } } + let(:result) do + { 'VARIABLE_1' => 'value 1', 'VARIABLE_2' => 'value 2' } + end it_behaves_like 'valid config' + + describe '#value_with_data' do + it 'returns variable with data' do + expect(entry.value_with_data).to eq( + 'VARIABLE_1' => { value: 'value 1', description: 'variable 1' }, + 'VARIABLE_2' => { value: 'value 2' } + ) + end + end end end context 'when entry value is an array' do let(:config) { [:VAR, 'test'] } - it_behaves_like 'invalid config' + it_behaves_like 'invalid config', /variables config should be a hash/ end - context 'when metadata has use_value_data' do - let(:metadata) { { use_value_data: true } } + context 'when metadata has allowed_value_data' do + let(:metadata) { { allowed_value_data: %i[value description] } } context 'when entry value has hash with other key-pairs' do let(:config) do @@ -97,7 +141,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Variables do 'VARIABLE_2' => 'value 2' } end - it_behaves_like 'invalid config' + it_behaves_like 'invalid config', /variable_1 config uses invalid data keys: hello/ end context 'when entry config value has hash with nil description' do @@ -105,7 +149,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Variables do { 'VARIABLE_1' => { value: 'value 1', description: nil } } end - it_behaves_like 'invalid config' + it_behaves_like 'invalid config', /variable_1 config description must be an alphanumeric string/ end context 'when entry config value has hash without description' do diff --git a/spec/lib/gitlab/ci/config/external/file/remote_spec.rb b/spec/lib/gitlab/ci/config/external/file/remote_spec.rb index 45dfea636f3..c22afb32756 100644 --- a/spec/lib/gitlab/ci/config/external/file/remote_spec.rb +++ b/spec/lib/gitlab/ci/config/external/file/remote_spec.rb @@ -219,4 +219,43 @@ RSpec.describe Gitlab::Ci::Config::External::File::Remote do ) } end + + describe '#to_hash' do + subject(:to_hash) { remote_file.to_hash } + + before do + stub_full_request(location).to_return(body: remote_file_content) + end + + context 'with a valid remote file' do + it 'returns the content as a hash' do + expect(to_hash).to eql( + before_script: ["apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs", + "ruby -v", + "which ruby", + "bundle install --jobs $(nproc) \"${FLAGS[@]}\""] + ) + end + end + + context 'when it has `include` with rules:exists' do + let(:remote_file_content) do + <<~HEREDOC + include: + - local: another-file.yml + rules: + - exists: [Dockerfile] + HEREDOC + end + + it 'returns the content as a hash' do + expect(to_hash).to eql( + include: [ + { local: 'another-file.yml', + rules: [{ exists: ['Dockerfile'] }] } + ] + ) + end + end + end end diff --git a/spec/lib/gitlab/ci/config/external/mapper_spec.rb b/spec/lib/gitlab/ci/config/external/mapper_spec.rb index e74fdc2071b..9eaba12f388 100644 --- a/spec/lib/gitlab/ci/config/external/mapper_spec.rb +++ b/spec/lib/gitlab/ci/config/external/mapper_spec.rb @@ -210,7 +210,7 @@ RSpec.describe Gitlab::Ci::Config::External::Mapper do { 'local' => local_file }, { 'local' => local_file } ], - image: 'image:1.0' } + image: 'image:1.0' } end it 'does not raise an exception' do @@ -427,7 +427,7 @@ RSpec.describe Gitlab::Ci::Config::External::Mapper do { 'local' => 'hello/secret-file1.yml' }, { 'local' => 'hello/secret-file2.yml' } ], - image: 'ruby:2.7' } + image: 'ruby:2.7' } end it 'has expanset with two' do diff --git a/spec/lib/gitlab/ci/config/external/processor_spec.rb b/spec/lib/gitlab/ci/config/external/processor_spec.rb index 841a46e197d..b1dff6f9723 100644 --- a/spec/lib/gitlab/ci/config/external/processor_spec.rb +++ b/spec/lib/gitlab/ci/config/external/processor_spec.rb @@ -94,6 +94,36 @@ RSpec.describe Gitlab::Ci::Config::External::Processor do end end + context 'when the remote file has `include` with rules:exists' do + let(:remote_file) { 'https://gitlab.com/gitlab-org/gitlab-foss/blob/1234/.gitlab-ci-1.yml' } + let(:values) { { include: remote_file, image: 'image:1.0' } } + let(:external_file_content) do + <<-HEREDOC + include: + - local: another-file.yml + rules: + - exists: [Dockerfile] + + rspec: + script: + - bundle exec rspec + HEREDOC + end + + before do + stub_full_request(remote_file).to_return(body: external_file_content) + end + + it 'evaluates the rule as false' do + output = processor.perform + expect(output.keys).to match_array([:image, :rspec]) + end + + it "removes the 'include' keyword" do + expect(processor.perform[:include]).to be_nil + end + end + context 'with a valid local external file is defined' do let(:values) { { include: '/lib/gitlab/ci/templates/template.yml', image: 'image:1.0' } } let(:local_file_content) do |