Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/lib/gitlab/ci/config/entry')
-rw-r--r--spec/lib/gitlab/ci/config/entry/job_spec.rb88
-rw-r--r--spec/lib/gitlab/ci/config/entry/processable_spec.rb86
-rw-r--r--spec/lib/gitlab/ci/config/entry/product/matrix_spec.rb188
-rw-r--r--spec/lib/gitlab/ci/config/entry/product/parallel_spec.rb94
-rw-r--r--spec/lib/gitlab/ci/config/entry/product/variables_spec.rb88
-rw-r--r--spec/lib/gitlab/ci/config/entry/service_spec.rb1
6 files changed, 516 insertions, 29 deletions
diff --git a/spec/lib/gitlab/ci/config/entry/job_spec.rb b/spec/lib/gitlab/ci/config/entry/job_spec.rb
index 180c52ee1ab..ca02eaee0a0 100644
--- a/spec/lib/gitlab/ci/config/entry/job_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/job_spec.rb
@@ -30,7 +30,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Job do
%i[before_script script stage type after_script cache
image services only except rules needs variables artifacts
environment coverage retry interruptible timeout release tags
- inherit]
+ inherit parallel]
end
it { is_expected.to include(*result) }
@@ -73,6 +73,45 @@ RSpec.describe Gitlab::Ci::Config::Entry::Job do
it { is_expected.to be_falsey }
end
+
+ context 'when config does not contain script' do
+ let(:name) { :build }
+
+ let(:config) do
+ { before_script: "cd ${PROJ_DIR} " }
+ end
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when using the default job without script' do
+ let(:name) { :default }
+ let(:config) do
+ { before_script: "cd ${PROJ_DIR} " }
+ end
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'when using the default job with script' do
+ let(:name) { :default }
+ let(:config) do
+ {
+ before_script: "cd ${PROJ_DIR} ",
+ script: "ls"
+ }
+ end
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'there are no shared keys between jobs and bridges' do
+ subject(:shared_values) do
+ described_class::ALLOWED_KEYS & Gitlab::Ci::Config::Entry::Bridge::ALLOWED_KEYS
+ end
+
+ it { is_expected.to be_empty }
+ end
end
describe 'validations' do
@@ -202,56 +241,47 @@ RSpec.describe Gitlab::Ci::Config::Entry::Job do
context 'when parallel value is not correct' do
context 'when it is not a numeric value' do
- let(:config) { { parallel: true } }
+ let(:config) { { script: 'echo', parallel: true } }
it 'returns error about invalid type' do
expect(entry).not_to be_valid
- expect(entry.errors).to include 'job parallel is not a number'
+ expect(entry.errors).to include 'parallel should be an integer or a hash'
end
end
context 'when it is lower than two' do
- let(:config) { { parallel: 1 } }
+ let(:config) { { script: 'echo', parallel: 1 } }
it 'returns error about value too low' do
expect(entry).not_to be_valid
expect(entry.errors)
- .to include 'job parallel must be greater than or equal to 2'
+ .to include 'parallel config must be greater than or equal to 2'
end
end
- context 'when it is bigger than 50' do
- let(:config) { { parallel: 51 } }
+ context 'when it is an empty hash' do
+ let(:config) { { script: 'echo', parallel: {} } }
- it 'returns error about value too high' do
+ it 'returns error about missing matrix' do
expect(entry).not_to be_valid
expect(entry.errors)
- .to include 'job parallel must be less than or equal to 50'
+ .to include 'parallel config missing required keys: matrix'
end
end
+ end
- context 'when it is not an integer' do
- let(:config) { { parallel: 1.5 } }
-
- it 'returns error about wrong value' do
- expect(entry).not_to be_valid
- expect(entry.errors).to include 'job parallel must be an integer'
- end
+ context 'when it uses both "when:" and "rules:"' do
+ let(:config) do
+ {
+ script: 'echo',
+ when: 'on_failure',
+ rules: [{ if: '$VARIABLE', when: 'on_success' }]
+ }
end
- context 'when it uses both "when:" and "rules:"' do
- let(:config) do
- {
- script: 'echo',
- when: 'on_failure',
- rules: [{ if: '$VARIABLE', when: 'on_success' }]
- }
- end
-
- it 'returns an error about when: being combined with rules' do
- expect(entry).not_to be_valid
- expect(entry.errors).to include 'job config key may not be used with `rules`: when'
- end
+ it 'returns an error about when: being combined with rules' do
+ expect(entry).not_to be_valid
+ expect(entry.errors).to include 'job config key may not be used with `rules`: when'
end
end
diff --git a/spec/lib/gitlab/ci/config/entry/processable_spec.rb b/spec/lib/gitlab/ci/config/entry/processable_spec.rb
index fdf6008f89f..ac8dd2a3267 100644
--- a/spec/lib/gitlab/ci/config/entry/processable_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/processable_spec.rb
@@ -230,6 +230,12 @@ RSpec.describe Gitlab::Ci::Config::Entry::Processable do
end
end
+ shared_examples 'has no warnings' do
+ it 'does not raise the warning' do
+ expect(entry.warnings).to be_empty
+ end
+ end
+
context 'when workflow rules is used' do
let(:workflow) { double('workflow', 'has_rules?' => true) }
@@ -254,6 +260,86 @@ RSpec.describe Gitlab::Ci::Config::Entry::Processable do
end
end
+ context 'when workflow rules is not used' do
+ let(:workflow) { double('workflow', 'has_rules?' => false) }
+ let(:feature_flag_value) { true }
+
+ before do
+ stub_feature_flags(ci_raise_job_rules_without_workflow_rules_warning: feature_flag_value)
+ entry.compose!(deps)
+ end
+
+ context 'when rules are valid' do
+ let(:config) do
+ {
+ script: 'ls',
+ rules: [
+ { if: '$CI_COMMIT_BRANCH', when: 'on_success' },
+ last_rule
+ ]
+ }
+ end
+
+ context 'when last rule contains only `when`' do
+ let(:last_rule) { { when: when_value } }
+
+ context 'and its value is not `never`' do
+ let(:when_value) { 'on_success' }
+
+ it 'raises a warning' do
+ expect(entry.warnings).to contain_exactly(/may allow multiple pipelines/)
+ end
+
+ context 'when feature flag is disabled' do
+ let(:feature_flag_value) { false }
+
+ it_behaves_like 'has no warnings'
+ end
+ end
+
+ context 'and its value is `never`' do
+ let(:when_value) { 'never' }
+
+ it_behaves_like 'has no warnings'
+ end
+ end
+
+ context 'when last rule does not contain only `when`' do
+ let(:last_rule) { { if: '$CI_MERGE_REQUEST_ID', when: 'always' } }
+
+ it_behaves_like 'has no warnings'
+ end
+ end
+
+ context 'when rules are invalid' do
+ let(:config) { { script: 'ls', rules: { when: 'always' } } }
+
+ it_behaves_like 'has no warnings'
+ end
+ end
+
+ context 'when workflow rules is used' do
+ let(:workflow) { double('workflow', 'has_rules?' => true) }
+
+ before do
+ entry.compose!(deps)
+ end
+
+ context 'when last rule contains only `when' do
+ let(:config) do
+ {
+ script: 'ls',
+ rules: [
+ { if: '$CI_COMMIT_BRANCH', when: 'on_success' },
+ { when: 'always' }
+ ]
+ }
+ end
+
+ it_behaves_like 'has no warnings'
+ end
+ end
+
context 'with inheritance' do
context 'of variables' do
let(:config) 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
new file mode 100644
index 00000000000..39697884e3b
--- /dev/null
+++ b/spec/lib/gitlab/ci/config/entry/product/matrix_spec.rb
@@ -0,0 +1,188 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require_dependency 'active_model'
+
+RSpec.describe ::Gitlab::Ci::Config::Entry::Product::Matrix do
+ subject(:matrix) { described_class.new(config) }
+
+ describe 'validations' do
+ before do
+ matrix.compose!
+ end
+
+ context 'when entry config value is correct' do
+ let(:config) do
+ [
+ { 'VAR_1' => [1, 2, 3], 'VAR_2' => [4, 5, 6] },
+ { 'VAR_3' => %w[a b], 'VAR_4' => %w[c d] }
+ ]
+ end
+
+ describe '#valid?' do
+ it { is_expected.to be_valid }
+ end
+ end
+
+ context 'when entry config generates too many jobs' do
+ let(:config) do
+ [
+ {
+ 'VAR_1' => (1..10).to_a,
+ 'VAR_2' => (11..20).to_a
+ }
+ ]
+ end
+
+ describe '#valid?' do
+ it { is_expected.not_to be_valid }
+ end
+
+ describe '#errors' do
+ it 'returns error about too many jobs' do
+ expect(matrix.errors)
+ .to include('matrix config generates too many jobs (maximum is 50)')
+ end
+ end
+ end
+
+ context 'when entry config has only one variable' do
+ let(:config) do
+ [
+ {
+ 'VAR_1' => %w[test]
+ }
+ ]
+ end
+
+ describe '#valid?' do
+ it { is_expected.not_to be_valid }
+ end
+
+ describe '#errors' do
+ it 'returns error about too many jobs' do
+ expect(matrix.errors)
+ .to include('variables config requires at least 2 items')
+ end
+ end
+
+ describe '#value' do
+ before do
+ matrix.compose!
+ end
+
+ it 'returns the value without raising an error' do
+ expect(matrix.value).to eq([{ 'VAR_1' => ['test'] }])
+ end
+ end
+ end
+
+ context 'when config value has wrong type' do
+ let(:config) { {} }
+
+ describe '#valid?' do
+ it { is_expected.not_to be_valid }
+ end
+
+ describe '#errors' do
+ it 'returns error about incorrect type' do
+ expect(matrix.errors)
+ .to include('matrix config should be an array of hashes')
+ end
+ end
+ end
+ end
+
+ describe '.compose!' do
+ context 'when valid job entries composed' do
+ let(:config) do
+ [
+ { PROVIDER: 'aws', STACK: %w[monitoring app1 app2] },
+ { STACK: %w[monitoring backup app], PROVIDER: 'ovh' },
+ { PROVIDER: 'gcp', STACK: %w[data processing], ARGS: 'normal' },
+ { PROVIDER: 'vultr', STACK: 'data', ARGS: 'store' }
+ ]
+ end
+
+ before do
+ matrix.compose!
+ end
+
+ describe '#value' do
+ it 'returns key value' do
+ expect(matrix.value).to match(
+ [
+ { 'PROVIDER' => %w[aws], 'STACK' => %w[monitoring app1 app2] },
+ { 'PROVIDER' => %w[ovh], 'STACK' => %w[monitoring backup app] },
+ { 'ARGS' => %w[normal], 'PROVIDER' => %w[gcp], 'STACK' => %w[data processing] },
+ { 'ARGS' => %w[store], 'PROVIDER' => %w[vultr], 'STACK' => %w[data] }
+ ]
+ )
+ end
+ end
+
+ describe '#descendants' do
+ it 'creates valid descendant nodes' do
+ expect(matrix.descendants.count).to eq(config.size)
+ expect(matrix.descendants)
+ .to all(be_an_instance_of(::Gitlab::Ci::Config::Entry::Product::Variables))
+ end
+ end
+ end
+
+ context 'with empty config' do
+ let(:config) { [] }
+
+ before do
+ matrix.compose!
+ end
+
+ describe '#value' do
+ it 'returns empty value' do
+ expect(matrix.value).to eq([])
+ end
+ end
+ end
+ end
+
+ describe '#number_of_generated_jobs' do
+ before do
+ matrix.compose!
+ end
+
+ subject { matrix.number_of_generated_jobs }
+
+ context 'with empty config' do
+ let(:config) { [] }
+
+ it { is_expected.to be_zero }
+ end
+
+ context 'with only one variable' do
+ let(:config) do
+ [{ 'VAR_1' => (1..10).to_a }]
+ end
+
+ it { is_expected.to eq(10) }
+ end
+
+ context 'with two variables' do
+ let(:config) do
+ [{ 'VAR_1' => (1..10).to_a, 'VAR_2' => (1..5).to_a }]
+ end
+
+ it { is_expected.to eq(50) }
+ end
+
+ context 'with two sets of variables' do
+ let(:config) do
+ [
+ { 'VAR_1' => (1..10).to_a, 'VAR_2' => (1..5).to_a },
+ { 'VAR_3' => (1..2).to_a, 'VAR_4' => (1..3).to_a }
+ ]
+ end
+
+ it { is_expected.to eq(56) }
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/config/entry/product/parallel_spec.rb b/spec/lib/gitlab/ci/config/entry/product/parallel_spec.rb
new file mode 100644
index 00000000000..bc09e20d748
--- /dev/null
+++ b/spec/lib/gitlab/ci/config/entry/product/parallel_spec.rb
@@ -0,0 +1,94 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require_dependency 'active_model'
+
+RSpec.describe ::Gitlab::Ci::Config::Entry::Product::Parallel do
+ subject(:parallel) { described_class.new(config) }
+
+ context 'with invalid config' do
+ shared_examples 'invalid config' do |error_message|
+ describe '#valid?' do
+ it { is_expected.not_to be_valid }
+ end
+
+ describe '#errors' do
+ it 'returns error about invalid type' do
+ expect(parallel.errors).to match(a_collection_including(error_message))
+ end
+ end
+ end
+
+ context 'when it is not a numeric value' do
+ let(:config) { true }
+
+ it_behaves_like 'invalid config', /should be an integer or a hash/
+ end
+
+ context 'when it is lower than two' do
+ let(:config) { 1 }
+
+ it_behaves_like 'invalid config', /must be greater than or equal to 2/
+ end
+
+ context 'when it is bigger than 50' do
+ let(:config) { 51 }
+
+ it_behaves_like 'invalid config', /must be less than or equal to 50/
+ end
+
+ context 'when it is not an integer' do
+ let(:config) { 1.5 }
+
+ it_behaves_like 'invalid config', /must be an integer/
+ end
+
+ context 'with empty hash config' do
+ let(:config) { {} }
+
+ it_behaves_like 'invalid config', /matrix builds config missing required keys: matrix/
+ end
+ end
+
+ context 'with numeric config' do
+ context 'when job is specified' do
+ let(:config) { 2 }
+
+ describe '#valid?' do
+ it { is_expected.to be_valid }
+ end
+
+ describe '#value' do
+ it 'returns job needs configuration' do
+ expect(parallel.value).to match(number: config)
+ end
+ end
+ end
+ end
+
+ context 'with matrix builds config' do
+ context 'when matrix is specified' do
+ let(:config) do
+ {
+ matrix: [
+ { PROVIDER: 'aws', STACK: %w[monitoring app1 app2] },
+ { PROVIDER: 'gcp', STACK: %w[data processing] }
+ ]
+ }
+ end
+
+ describe '#valid?' do
+ it { is_expected.to be_valid }
+ end
+
+ describe '#value' do
+ it 'returns job needs configuration' do
+ expect(parallel.value).to match(matrix: [
+ { PROVIDER: 'aws', STACK: %w[monitoring app1 app2] },
+ { PROVIDER: 'gcp', STACK: %w[data processing] }
+ ])
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/config/entry/product/variables_spec.rb b/spec/lib/gitlab/ci/config/entry/product/variables_spec.rb
new file mode 100644
index 00000000000..230b001d620
--- /dev/null
+++ b/spec/lib/gitlab/ci/config/entry/product/variables_spec.rb
@@ -0,0 +1,88 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require_dependency 'active_model'
+
+RSpec.describe Gitlab::Ci::Config::Entry::Product::Variables do
+ let(:entry) { described_class.new(config) }
+
+ describe 'validations' do
+ context 'when entry config value is correct' do
+ let(:config) do
+ {
+ 'VARIABLE_1' => 1,
+ 'VARIABLE_2' => 'value 2',
+ 'VARIABLE_3' => :value_3,
+ :VARIABLE_4 => 'value 4',
+ 5 => ['value 5'],
+ 'VARIABLE_6' => ['value 6']
+ }
+ end
+
+ describe '#value' do
+ it 'returns hash with key value strings' do
+ expect(entry.value).to match({
+ 'VARIABLE_1' => ['1'],
+ 'VARIABLE_2' => ['value 2'],
+ 'VARIABLE_3' => ['value_3'],
+ 'VARIABLE_4' => ['value 4'],
+ '5' => ['value 5'],
+ 'VARIABLE_6' => ['value 6']
+ })
+ 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
+
+ context 'when entry value is not correct' do
+ shared_examples 'invalid variables' do |message|
+ describe '#errors' do
+ it 'saves errors' do
+ expect(entry.errors).to include(message)
+ end
+ end
+
+ describe '#valid?' do
+ it 'is not valid' do
+ expect(entry).not_to be_valid
+ end
+ end
+ end
+
+ context 'with array' do
+ let(:config) { [:VAR, 'test'] }
+
+ it_behaves_like 'invalid variables', /should be a hash of key value pairs/
+ end
+
+ context 'with empty array' do
+ let(:config) { { VAR: 'test', VAR2: [] } }
+
+ it_behaves_like 'invalid variables', /should be a hash of key value pairs/
+ end
+
+ context 'with nested array' do
+ let(:config) { { VAR: 'test', VAR2: [1, [2]] } }
+
+ it_behaves_like 'invalid variables', /should be a hash of key value pairs/
+ end
+
+ context 'with only one variable' do
+ let(:config) { { VAR: 'test' } }
+
+ it_behaves_like 'invalid variables', /variables config requires at least 2 items/
+ 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 9fbc14c19b9..ec137ef2ae4 100644
--- a/spec/lib/gitlab/ci/config/entry/service_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/service_spec.rb
@@ -95,6 +95,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Service do
let(:config) do
{ name: 'postgresql:9.5', alias: 'db', command: %w(cmd run), entrypoint: %w(/bin/sh run), ports: ports }
end
+
let(:entry) { described_class.new(config, { with_image_ports: image_ports }) }
let(:image_ports) { false }