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')
-rw-r--r--spec/lib/gitlab/ci/ansi2json/parser_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/ansi2json/result_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/build/artifacts/adapters/zip_stream_spec.rb86
-rw-r--r--spec/lib/gitlab/ci/build/artifacts/path_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/build/policy/variables_spec.rb3
-rw-r--r--spec/lib/gitlab/ci/build/policy_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/build/port_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/build/rules/rule/clause/exists_spec.rb46
-rw-r--r--spec/lib/gitlab/ci/config/entry/environment_spec.rb10
-rw-r--r--spec/lib/gitlab/ci/config/entry/image_spec.rb27
-rw-r--r--spec/lib/gitlab/ci/config/entry/job_spec.rb3
-rw-r--r--spec/lib/gitlab/ci/config/entry/legacy_variables_spec.rb173
-rw-r--r--spec/lib/gitlab/ci/config/entry/port_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/config/entry/processable_spec.rb32
-rw-r--r--spec/lib/gitlab/ci/config/entry/product/matrix_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/config/entry/root_spec.rb149
-rw-r--r--spec/lib/gitlab/ci/config/entry/rules/rule_spec.rb18
-rw-r--r--spec/lib/gitlab/ci/config/entry/service_spec.rb25
-rw-r--r--spec/lib/gitlab/ci/config/entry/variable_spec.rb212
-rw-r--r--spec/lib/gitlab/ci/config/entry/variables_spec.rb82
-rw-r--r--spec/lib/gitlab/ci/config/external/file/remote_spec.rb39
-rw-r--r--spec/lib/gitlab/ci/config/external/mapper_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/config/external/processor_spec.rb30
-rw-r--r--spec/lib/gitlab/ci/lint_spec.rb6
-rw-r--r--spec/lib/gitlab/ci/mask_secret_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/parsers/sbom/cyclonedx_properties_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/parsers/sbom/cyclonedx_spec.rb6
-rw-r--r--spec/lib/gitlab/ci/parsers/sbom/source/dependency_scanning_spec.rb12
-rw-r--r--spec/lib/gitlab/ci/parsers/security/common_spec.rb24
-rw-r--r--spec/lib/gitlab/ci/parsers/security/validators/schema_validator_spec.rb273
-rw-r--r--spec/lib/gitlab/ci/parsers/test/junit_spec.rb8
-rw-r--r--spec/lib/gitlab/ci/parsers_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/assign_partition_spec.rb47
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/command_spec.rb38
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/config/content_spec.rb14
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/ensure_environments_spec.rb44
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb1
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/sequence_spec.rb39
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb64
-rw-r--r--spec/lib/gitlab/ci/pipeline/duration_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/pipeline/expression/lexeme/null_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/pipeline/expression/lexeme/string_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/pipeline/expression/lexeme/variable_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/pipeline/metrics_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/pipeline/seed/build_spec.rb68
-rw-r--r--spec/lib/gitlab/ci/pipeline/seed/deployment_spec.rb3
-rw-r--r--spec/lib/gitlab/ci/pipeline/seed/environment_spec.rb55
-rw-r--r--spec/lib/gitlab/ci/processable_object_hierarchy_spec.rb82
-rw-r--r--spec/lib/gitlab/ci/project_config/repository_spec.rb47
-rw-r--r--spec/lib/gitlab/ci/project_config/source_spec.rb23
-rw-r--r--spec/lib/gitlab/ci/project_config_spec.rb177
-rw-r--r--spec/lib/gitlab/ci/reports/accessibility_reports_comparer_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/reports/accessibility_reports_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/reports/coverage_report_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/reports/sbom/component_spec.rb16
-rw-r--r--spec/lib/gitlab/ci/reports/sbom/report_spec.rb26
-rw-r--r--spec/lib/gitlab/ci/reports/sbom/reports_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/reports/sbom/source_spec.rb16
-rw-r--r--spec/lib/gitlab/ci/reports/security/flag_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/reports/security/link_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/reports/security/scan_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/reports/security/scanned_resource_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/reports/terraform_reports_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/status/extended_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/status/group/factory_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/katalon_gitlab_ci_yaml_spec.rb52
-rw-r--r--spec/lib/gitlab/ci/trace/archive_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/trace_spec.rb1
-rw-r--r--spec/lib/gitlab/ci/variables/builder_spec.rb12
-rw-r--r--spec/lib/gitlab/ci/variables/collection/sort_spec.rb1
-rw-r--r--spec/lib/gitlab/ci/variables/helpers_spec.rb113
-rw-r--r--spec/lib/gitlab/ci/yaml_processor/dag_spec.rb1
-rw-r--r--spec/lib/gitlab/ci/yaml_processor/feature_flags_spec.rb30
-rw-r--r--spec/lib/gitlab/ci/yaml_processor/result_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/yaml_processor_spec.rb185
75 files changed, 1766 insertions, 715 deletions
diff --git a/spec/lib/gitlab/ci/ansi2json/parser_spec.rb b/spec/lib/gitlab/ci/ansi2json/parser_spec.rb
index cf93ebe0721..b11002e8e93 100644
--- a/spec/lib/gitlab/ci/ansi2json/parser_spec.rb
+++ b/spec/lib/gitlab/ci/ansi2json/parser_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'spec_helper'
+require 'fast_spec_helper'
# The rest of the specs for this class are covered in style_spec.rb
RSpec.describe Gitlab::Ci::Ansi2json::Parser do
diff --git a/spec/lib/gitlab/ci/ansi2json/result_spec.rb b/spec/lib/gitlab/ci/ansi2json/result_spec.rb
index b7b4d6de8b9..14e2a9625fe 100644
--- a/spec/lib/gitlab/ci/ansi2json/result_spec.rb
+++ b/spec/lib/gitlab/ci/ansi2json/result_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'spec_helper'
+require 'fast_spec_helper'
RSpec.describe Gitlab::Ci::Ansi2json::Result do
let(:stream) { StringIO.new('hello') }
diff --git a/spec/lib/gitlab/ci/build/artifacts/adapters/zip_stream_spec.rb b/spec/lib/gitlab/ci/build/artifacts/adapters/zip_stream_spec.rb
deleted file mode 100644
index 2c236ba3726..00000000000
--- a/spec/lib/gitlab/ci/build/artifacts/adapters/zip_stream_spec.rb
+++ /dev/null
@@ -1,86 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Ci::Build::Artifacts::Adapters::ZipStream do
- let(:file_name) { 'single_file.zip' }
- let(:fixture_path) { "lib/gitlab/ci/build/artifacts/adapters/zip_stream/#{file_name}" }
- let(:stream) { File.open(expand_fixture_path(fixture_path), 'rb') }
-
- describe '#initialize' do
- it 'initializes when stream is passed' do
- expect { described_class.new(stream) }.not_to raise_error
- end
-
- context 'when stream is not passed' do
- let(:stream) { nil }
-
- it 'raises an error' do
- expect { described_class.new(stream) }.to raise_error(described_class::InvalidStreamError)
- end
- end
- end
-
- describe '#each_blob' do
- let(:adapter) { described_class.new(stream) }
-
- context 'when stream is a zip file' do
- it 'iterates file content when zip file contains one file' do
- expect { |b| adapter.each_blob(&b) }
- .to yield_with_args("file 1 content\n")
- end
-
- context 'when zip file contains multiple files' do
- let(:file_name) { 'multiple_files.zip' }
-
- it 'iterates content of all files' do
- expect { |b| adapter.each_blob(&b) }
- .to yield_successive_args("file 1 content\n", "file 2 content\n")
- end
- end
-
- context 'when zip file includes files in a directory' do
- let(:file_name) { 'with_directory.zip' }
-
- it 'iterates contents from files only' do
- expect { |b| adapter.each_blob(&b) }
- .to yield_successive_args("file 1 content\n", "file 2 content\n")
- end
- end
-
- context 'when zip contains a file which decompresses beyond the size limit' do
- let(:file_name) { '200_mb_decompressed.zip' }
-
- it 'does not read the file' do
- expect { |b| adapter.each_blob(&b) }.not_to yield_control
- end
- end
-
- context 'when the zip contains too many files' do
- let(:file_name) { '100_files.zip' }
-
- it 'stops processing when the limit is reached' do
- expect { |b| adapter.each_blob(&b) }
- .to yield_control.exactly(described_class::MAX_FILES_PROCESSED).times
- end
- end
-
- context 'when stream is a zipbomb' do
- let(:file_name) { 'zipbomb.zip' }
-
- it 'does not read the file' do
- expect { |b| adapter.each_blob(&b) }.not_to yield_control
- end
- end
- end
-
- context 'when stream is not a zip file' do
- let(:stream) { File.open(expand_fixture_path('junit/junit.xml.gz'), 'rb') }
-
- it 'does not yield any data' do
- expect { |b| adapter.each_blob(&b) }.not_to yield_control
- expect { adapter.each_blob { |b| b } }.not_to raise_error
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/ci/build/artifacts/path_spec.rb b/spec/lib/gitlab/ci/build/artifacts/path_spec.rb
index 27b7dac2ae4..773eaf4b3fc 100644
--- a/spec/lib/gitlab/ci/build/artifacts/path_spec.rb
+++ b/spec/lib/gitlab/ci/build/artifacts/path_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'spec_helper'
+require 'fast_spec_helper'
RSpec.describe Gitlab::Ci::Build::Artifacts::Path do
describe '#valid?' do
diff --git a/spec/lib/gitlab/ci/build/policy/variables_spec.rb b/spec/lib/gitlab/ci/build/policy/variables_spec.rb
index 436ad59bdf7..e560f1c2b5a 100644
--- a/spec/lib/gitlab/ci/build/policy/variables_spec.rb
+++ b/spec/lib/gitlab/ci/build/policy/variables_spec.rb
@@ -108,7 +108,8 @@ RSpec.describe Gitlab::Ci::Build::Policy::Variables do
project: project,
ref: 'master',
stage: 'review',
- environment: 'test/$CI_JOB_STAGE/1')
+ environment: 'test/$CI_JOB_STAGE/1',
+ ci_stage: build(:ci_stage, name: 'review', project: project, pipeline: pipeline))
end
before do
diff --git a/spec/lib/gitlab/ci/build/policy_spec.rb b/spec/lib/gitlab/ci/build/policy_spec.rb
index b85b093fd03..4baf4a1b4c4 100644
--- a/spec/lib/gitlab/ci/build/policy_spec.rb
+++ b/spec/lib/gitlab/ci/build/policy_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'spec_helper'
+require 'fast_spec_helper'
RSpec.describe Gitlab::Ci::Build::Policy do
let(:policy) { spy('policy specification') }
diff --git a/spec/lib/gitlab/ci/build/port_spec.rb b/spec/lib/gitlab/ci/build/port_spec.rb
index 480418e0851..51820c1ab2c 100644
--- a/spec/lib/gitlab/ci/build/port_spec.rb
+++ b/spec/lib/gitlab/ci/build/port_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'spec_helper'
+require 'fast_spec_helper'
RSpec.describe Gitlab::Ci::Build::Port do
subject { described_class.new(port) }
diff --git a/spec/lib/gitlab/ci/build/rules/rule/clause/exists_spec.rb b/spec/lib/gitlab/ci/build/rules/rule/clause/exists_spec.rb
index f192862c1c4..f9ebab149a5 100644
--- a/spec/lib/gitlab/ci/build/rules/rule/clause/exists_spec.rb
+++ b/spec/lib/gitlab/ci/build/rules/rule/clause/exists_spec.rb
@@ -3,44 +3,54 @@
require 'spec_helper'
RSpec.describe Gitlab::Ci::Build::Rules::Rule::Clause::Exists do
- shared_examples 'an exists rule with a context' do
- subject { described_class.new(globs).satisfied_by?(pipeline, context) }
+ describe '#satisfied_by?' do
+ shared_examples 'an exists rule with a context' do
+ it_behaves_like 'a glob matching rule' do
+ let(:project) { create(:project, :custom_repo, files: files) }
+ end
- it_behaves_like 'a glob matching rule' do
- let(:project) { create(:project, :custom_repo, files: files) }
- end
+ context 'after pattern comparision limit is reached' do
+ let(:globs) { ['*definitely_not_a_matching_glob*'] }
+ let(:project) { create(:project, :repository) }
- context 'after pattern comparision limit is reached' do
- let(:globs) { ['*definitely_not_a_matching_glob*'] }
- let(:project) { create(:project, :repository) }
+ before do
+ stub_const('Gitlab::Ci::Build::Rules::Rule::Clause::Exists::MAX_PATTERN_COMPARISONS', 2)
+ expect(File).to receive(:fnmatch?).twice.and_call_original
+ end
- before do
- stub_const('Gitlab::Ci::Build::Rules::Rule::Clause::Exists::MAX_PATTERN_COMPARISONS', 2)
- expect(File).to receive(:fnmatch?).twice.and_call_original
+ it { is_expected.to be_truthy }
end
-
- it { is_expected.to be_truthy }
end
- end
- describe '#satisfied_by?' do
- let(:pipeline) { build(:ci_pipeline, project: project, sha: project.repository.head_commit.sha) }
+ subject(:satisfied_by?) { described_class.new(globs).satisfied_by?(nil, context) }
context 'when context is Build::Context::Build' do
it_behaves_like 'an exists rule with a context' do
- let(:context) { Gitlab::Ci::Build::Context::Build.new(pipeline, sha: 'abc1234') }
+ let(:pipeline) { build(:ci_pipeline, project: project, sha: project.repository.commit.sha) }
+ let(:context) { Gitlab::Ci::Build::Context::Build.new(pipeline, sha: project.repository.commit.sha) }
end
end
context 'when context is Build::Context::Global' do
it_behaves_like 'an exists rule with a context' do
+ let(:pipeline) { build(:ci_pipeline, project: project, sha: project.repository.commit.sha) }
let(:context) { Gitlab::Ci::Build::Context::Global.new(pipeline, yaml_variables: {}) }
end
end
context 'when context is Config::External::Context' do
+ let(:context) { Gitlab::Ci::Config::External::Context.new(project: project, sha: sha) }
+
it_behaves_like 'an exists rule with a context' do
- let(:context) { Gitlab::Ci::Config::External::Context.new(project: project, sha: project.repository.tree.sha) }
+ let(:sha) { project.repository.commit.sha }
+ end
+
+ context 'when context has no project' do
+ let(:globs) { ['Dockerfile'] }
+ let(:project) {}
+ let(:sha) { 'abc1234' }
+
+ it { is_expected.to eq(false) }
end
end
end
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
diff --git a/spec/lib/gitlab/ci/lint_spec.rb b/spec/lib/gitlab/ci/lint_spec.rb
index 7e0b2b5aa8e..3d46d266c13 100644
--- a/spec/lib/gitlab/ci/lint_spec.rb
+++ b/spec/lib/gitlab/ci/lint_spec.rb
@@ -341,9 +341,9 @@ RSpec.describe Gitlab::Ci::Lint do
let(:counters) do
{
'count' => a_kind_of(Numeric),
- 'avg' => a_kind_of(Numeric),
- 'max' => a_kind_of(Numeric),
- 'min' => a_kind_of(Numeric)
+ 'avg' => a_kind_of(Numeric),
+ 'max' => a_kind_of(Numeric),
+ 'min' => a_kind_of(Numeric)
}
end
diff --git a/spec/lib/gitlab/ci/mask_secret_spec.rb b/spec/lib/gitlab/ci/mask_secret_spec.rb
index 7d950c86700..ffe36e69a8f 100644
--- a/spec/lib/gitlab/ci/mask_secret_spec.rb
+++ b/spec/lib/gitlab/ci/mask_secret_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'spec_helper'
+require 'fast_spec_helper'
RSpec.describe Gitlab::Ci::MaskSecret do
subject { described_class }
diff --git a/spec/lib/gitlab/ci/parsers/sbom/cyclonedx_properties_spec.rb b/spec/lib/gitlab/ci/parsers/sbom/cyclonedx_properties_spec.rb
index c99cfa94aa6..38b229e0dd8 100644
--- a/spec/lib/gitlab/ci/parsers/sbom/cyclonedx_properties_spec.rb
+++ b/spec/lib/gitlab/ci/parsers/sbom/cyclonedx_properties_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'spec_helper'
+require 'fast_spec_helper'
RSpec.describe Gitlab::Ci::Parsers::Sbom::CyclonedxProperties do
subject(:parse_source) { described_class.parse_source(properties) }
diff --git a/spec/lib/gitlab/ci/parsers/sbom/cyclonedx_spec.rb b/spec/lib/gitlab/ci/parsers/sbom/cyclonedx_spec.rb
index 431fe9f3591..f3636106b98 100644
--- a/spec/lib/gitlab/ci/parsers/sbom/cyclonedx_spec.rb
+++ b/spec/lib/gitlab/ci/parsers/sbom/cyclonedx_spec.rb
@@ -102,11 +102,11 @@ RSpec.describe Gitlab::Ci::Parsers::Sbom::Cyclonedx do
it 'adds each component, ignoring unused attributes' do
expect(report).to receive(:add_component)
- .with({ "name" => "activesupport", "version" => "5.1.4", "type" => "library" })
+ .with(an_object_having_attributes(name: "activesupport", version: "5.1.4", component_type: "library"))
expect(report).to receive(:add_component)
- .with({ "name" => "byebug", "version" => "10.0.0", "type" => "library" })
+ .with(an_object_having_attributes(name: "byebug", version: "10.0.0", component_type: "library"))
expect(report).to receive(:add_component)
- .with({ "name" => "minimal-component", "type" => "library" })
+ .with(an_object_having_attributes(name: "minimal-component", version: nil, component_type: "library"))
parse!
end
diff --git a/spec/lib/gitlab/ci/parsers/sbom/source/dependency_scanning_spec.rb b/spec/lib/gitlab/ci/parsers/sbom/source/dependency_scanning_spec.rb
index 30114b17cac..7222ebc3cb8 100644
--- a/spec/lib/gitlab/ci/parsers/sbom/source/dependency_scanning_spec.rb
+++ b/spec/lib/gitlab/ci/parsers/sbom/source/dependency_scanning_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'spec_helper'
+require 'fast_spec_helper'
RSpec.describe Gitlab::Ci::Parsers::Sbom::Source::DependencyScanning do
subject { described_class.source(property_data) }
@@ -17,11 +17,11 @@ RSpec.describe Gitlab::Ci::Parsers::Sbom::Source::DependencyScanning do
end
it 'returns expected source data' do
- is_expected.to eq({
- 'type' => :dependency_scanning,
- 'data' => property_data,
- 'fingerprint' => '4dbcb747e6f0fb3ed4f48d96b777f1d64acdf43e459fdfefad404e55c004a188'
- })
+ is_expected.to have_attributes(
+ source_type: :dependency_scanning,
+ data: property_data,
+ fingerprint: '4dbcb747e6f0fb3ed4f48d96b777f1d64acdf43e459fdfefad404e55c004a188'
+ )
end
end
diff --git a/spec/lib/gitlab/ci/parsers/security/common_spec.rb b/spec/lib/gitlab/ci/parsers/security/common_spec.rb
index 6495d1f654b..297ef1f5bb9 100644
--- a/spec/lib/gitlab/ci/parsers/security/common_spec.rb
+++ b/spec/lib/gitlab/ci/parsers/security/common_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do
}
end
- where(vulnerability_finding_signatures_enabled: [true, false])
+ where(signatures_enabled: [true, false])
with_them do
let_it_be(:pipeline) { create(:ci_pipeline) }
@@ -44,7 +44,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do
let(:validator_class) { Gitlab::Ci::Parsers::Security::Validators::SchemaValidator }
let(:data) { {}.merge(scanner_data) }
let(:json_data) { data.to_json }
- let(:parser) { described_class.new(json_data, report, vulnerability_finding_signatures_enabled, validate: validate) }
+ let(:parser) { described_class.new(json_data, report, signatures_enabled: signatures_enabled, validate: validate) }
subject(:parse_report) { parser.parse! }
@@ -191,7 +191,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do
context 'report parsing' do
before do
- artifact.each_blob { |blob| described_class.parse!(blob, report, vulnerability_finding_signatures_enabled) }
+ artifact.each_blob { |blob| described_class.parse!(blob, report, signatures_enabled: signatures_enabled) }
end
describe 'parsing finding.name' do
@@ -262,7 +262,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do
describe 'top-level scanner' do
it 'is the primary scanner' do
expect(report.primary_scanner.external_id).to eq('gemnasium')
- expect(report.primary_scanner.name).to eq('Gemnasium')
+ expect(report.primary_scanner.name).to eq('Gemnasium top-level')
expect(report.primary_scanner.vendor).to eq('GitLab')
expect(report.primary_scanner.version).to eq('2.18.0')
end
@@ -278,9 +278,17 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do
describe 'parsing scanners' do
subject(:scanner) { report.findings.first.scanner }
- context 'when vendor is not missing in scanner' do
- it 'returns scanner with parsed vendor value' do
- expect(scanner.vendor).to eq('GitLab')
+ context 'when the report contains top-level scanner' do
+ it 'sets the scanner of finding as top-level scanner' do
+ expect(scanner.name).to eq('Gemnasium top-level')
+ end
+ end
+
+ context 'when the report does not contain top-level scanner' do
+ let(:artifact) { build(:ci_job_artifact, :common_security_report_without_top_level_scanner) }
+
+ it 'sets the scanner of finding as `vulnerabilities[].scanner`' do
+ expect(scanner.name).to eq('Gemnasium')
end
end
end
@@ -465,7 +473,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do
finding = report.findings.first
highest_signature = finding.signatures.max_by(&:priority)
- identifiers = if vulnerability_finding_signatures_enabled
+ identifiers = if signatures_enabled
"#{finding.report_type}-#{finding.primary_identifier.fingerprint}-#{highest_signature.signature_hex}-#{report.project_id}"
else
"#{finding.report_type}-#{finding.primary_identifier.fingerprint}-#{finding.location.fingerprint}-#{report.project_id}"
diff --git a/spec/lib/gitlab/ci/parsers/security/validators/schema_validator_spec.rb b/spec/lib/gitlab/ci/parsers/security/validators/schema_validator_spec.rb
index 7828aa99f6a..e730afc72b5 100644
--- a/spec/lib/gitlab/ci/parsers/security/validators/schema_validator_spec.rb
+++ b/spec/lib/gitlab/ci/parsers/security/validators/schema_validator_spec.rb
@@ -19,8 +19,72 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
}
end
+ let(:report_data) do
+ {
+ 'scan' => {
+ 'analyzer' => {
+ 'id' => 'my-dast-analyzer',
+ 'name' => 'My DAST analyzer',
+ 'version' => '0.1.0',
+ 'vendor' => { 'name' => 'A DAST analyzer' }
+ },
+ 'end_time' => '2020-01-28T03:26:02',
+ 'scanned_resources' => [],
+ 'scanner' => {
+ 'id' => 'my-dast-scanner',
+ 'name' => 'My DAST scanner',
+ 'version' => '0.2.0',
+ 'vendor' => { 'name' => 'A DAST scanner' }
+ },
+ 'start_time' => '2020-01-28T03:26:01',
+ 'status' => 'success',
+ 'type' => 'dast'
+ },
+ 'version' => report_version,
+ 'vulnerabilities' => []
+ }
+ end
+
let(:validator) { described_class.new(report_type, report_data, report_version, project: project, scanner: scanner) }
+ shared_examples 'report is valid' do
+ context 'and the report is valid' do
+ it { is_expected.to be_truthy }
+ end
+ end
+
+ shared_examples 'logs related information' do
+ it 'logs related information' do
+ expect(Gitlab::AppLogger).to receive(:info).with(
+ message: "security report schema validation problem",
+ security_report_type: report_type,
+ security_report_version: report_version,
+ project_id: project.id,
+ security_report_failure: security_report_failure,
+ security_report_scanner_id: 'gemnasium',
+ security_report_scanner_version: '2.1.0'
+ )
+
+ subject
+ end
+ end
+
+ shared_examples 'report is invalid' do
+ context 'and the report is invalid' do
+ let(:report_data) do
+ {
+ 'version' => report_version
+ }
+ end
+
+ let(:security_report_failure) { 'schema_validation_fails' }
+
+ it { is_expected.to be_falsey }
+
+ it_behaves_like 'logs related information'
+ end
+ end
+
describe 'SUPPORTED_VERSIONS' do
schema_path = Rails.root.join("lib", "gitlab", "ci", "parsers", "security", "validators", "schemas")
@@ -75,80 +139,16 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
(latest_vendored_version[0...2] << "34").join(".")
end
- context 'and the report is valid' do
- let(:report_data) do
- {
- 'version' => report_version,
- 'vulnerabilities' => []
- }
- end
-
- it { is_expected.to be_truthy }
- end
-
- context 'and the report is invalid' do
- let(:report_data) do
- {
- 'version' => report_version
- }
- end
-
- it { is_expected.to be_falsey }
-
- it 'logs related information' do
- expect(Gitlab::AppLogger).to receive(:info).with(
- message: "security report schema validation problem",
- security_report_type: report_type,
- security_report_version: report_version,
- project_id: project.id,
- security_report_failure: 'schema_validation_fails',
- security_report_scanner_id: 'gemnasium',
- security_report_scanner_version: '2.1.0'
- )
-
- subject
- end
- end
+ it_behaves_like 'report is valid'
+ it_behaves_like 'report is invalid'
end
context 'when given a supported schema version' do
let(:report_type) { :dast }
let(:report_version) { described_class::SUPPORTED_VERSIONS[report_type].last }
- context 'and the report is valid' do
- let(:report_data) do
- {
- 'version' => report_version,
- 'vulnerabilities' => []
- }
- end
-
- it { is_expected.to be_truthy }
- end
-
- context 'and the report is invalid' do
- let(:report_data) do
- {
- 'version' => report_version
- }
- end
-
- it { is_expected.to be_falsey }
-
- it 'logs related information' do
- expect(Gitlab::AppLogger).to receive(:info).with(
- message: "security report schema validation problem",
- security_report_type: report_type,
- security_report_version: report_version,
- project_id: project.id,
- security_report_failure: 'schema_validation_fails',
- security_report_scanner_id: 'gemnasium',
- security_report_scanner_version: '2.1.0'
- )
-
- subject
- end
- end
+ it_behaves_like 'report is valid'
+ it_behaves_like 'report is invalid'
end
context 'when given a deprecated schema version' do
@@ -173,21 +173,11 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
}
end
+ let(:security_report_failure) { 'using_deprecated_schema_version' }
+
it { is_expected.to be_truthy }
- it 'logs related information' do
- expect(Gitlab::AppLogger).to receive(:info).with(
- message: "security report schema validation problem",
- security_report_type: report_type,
- security_report_version: report_version,
- project_id: project.id,
- security_report_failure: 'using_deprecated_schema_version',
- security_report_scanner_id: 'gemnasium',
- security_report_scanner_version: '2.1.0'
- )
-
- subject
- end
+ it_behaves_like 'logs related information'
end
context 'and the report does not pass schema validation' do
@@ -213,21 +203,11 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
}
end
+ let(:security_report_failure) { 'using_unsupported_schema_version' }
+
it { is_expected.to be_falsey }
- it 'logs related information' do
- expect(Gitlab::AppLogger).to receive(:info).with(
- message: "security report schema validation problem",
- security_report_type: report_type,
- security_report_version: report_version,
- project_id: project.id,
- security_report_failure: 'using_unsupported_schema_version',
- security_report_scanner_id: 'gemnasium',
- security_report_scanner_version: '2.1.0'
- )
-
- subject
- end
+ it_behaves_like 'logs related information'
end
context 'and the report is invalid' do
@@ -282,6 +262,16 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
end
end
+ shared_examples 'report is valid with no error' do
+ context 'and the report is valid' do
+ it { is_expected.to be_empty }
+ end
+ end
+
+ shared_examples 'report with expected errors' do
+ it { is_expected.to match_array(expected_errors) }
+ end
+
describe '#errors' do
subject { validator.errors }
@@ -289,16 +279,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
let(:report_type) { :dast }
let(:report_version) { described_class::SUPPORTED_VERSIONS[report_type].last }
- context 'and the report is valid' do
- let(:report_data) do
- {
- 'version' => report_version,
- 'vulnerabilities' => []
- }
- end
-
- it { is_expected.to be_empty }
- end
+ it_behaves_like 'report is valid with no error'
context 'and the report is invalid' do
let(:report_data) do
@@ -309,11 +290,11 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
let(:expected_errors) do
[
- 'root is missing required keys: vulnerabilities'
+ 'root is missing required keys: scan, vulnerabilities'
]
end
- it { is_expected.to match_array(expected_errors) }
+ it_behaves_like 'report with expected errors'
end
end
@@ -331,16 +312,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
stub_const("#{described_class}::DEPRECATED_VERSIONS", deprecations_hash)
end
- context 'and the report passes schema validation' do
- let(:report_data) do
- {
- 'version' => '10.0.0',
- 'vulnerabilities' => []
- }
- end
-
- it { is_expected.to be_empty }
- end
+ it_behaves_like 'report is valid with no error'
context 'and the report does not pass schema validation' do
let(:report_data) do
@@ -356,7 +328,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
]
end
- it { is_expected.to match_array(expected_errors) }
+ it_behaves_like 'report with expected errors'
end
end
@@ -383,7 +355,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
]
end
- it { is_expected.to match_array(expected_errors) }
+ it_behaves_like 'report with expected errors'
end
context 'and the report is invalid' do
@@ -400,7 +372,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
]
end
- it { is_expected.to match_array(expected_errors) }
+ it_behaves_like 'report with expected errors'
end
end
@@ -426,10 +398,27 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
]
end
- it { is_expected.to match_array(expected_errors) }
+ it_behaves_like 'report with expected errors'
end
end
+ shared_examples 'report is valid with no warning' do
+ context 'and the report is valid' do
+ let(:report_data) do
+ {
+ 'version' => report_version,
+ 'vulnerabilities' => []
+ }
+ end
+
+ it { is_expected.to be_empty }
+ end
+ end
+
+ shared_examples 'report with expected warnings' do
+ it { is_expected.to match_array(expected_deprecation_warnings) }
+ end
+
describe '#deprecation_warnings' do
subject { validator.deprecation_warnings }
@@ -491,7 +480,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
}
end
- it { is_expected.to match_array(expected_deprecation_warnings) }
+ it_behaves_like 'report with expected warnings'
end
context 'and the report does not pass schema validation' do
@@ -501,7 +490,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
}
end
- it { is_expected.to match_array(expected_deprecation_warnings) }
+ it_behaves_like 'report with expected warnings'
end
end
@@ -516,7 +505,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
}
end
- it { is_expected.to match_array(expected_deprecation_warnings) }
+ it_behaves_like 'report with expected warnings'
end
end
@@ -561,21 +550,11 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
}
end
+ let(:security_report_failure) { 'schema_validation_fails' }
+
it { is_expected.to match_array([message]) }
- it 'logs related information' do
- expect(Gitlab::AppLogger).to receive(:info).with(
- message: "security report schema validation problem",
- security_report_type: report_type,
- security_report_version: report_version,
- project_id: project.id,
- security_report_failure: 'schema_validation_fails',
- security_report_scanner_id: 'gemnasium',
- security_report_scanner_version: '2.1.0'
- )
-
- subject
- end
+ it_behaves_like 'logs related information'
end
end
@@ -583,16 +562,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
let(:report_type) { :dast }
let(:report_version) { described_class::SUPPORTED_VERSIONS[report_type].last }
- context 'and the report is valid' do
- let(:report_data) do
- {
- 'version' => report_version,
- 'vulnerabilities' => []
- }
- end
-
- it { is_expected.to be_empty }
- end
+ it_behaves_like 'report is valid with no warning'
context 'and the report is invalid' do
let(:report_data) do
@@ -644,16 +614,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
let(:report_type) { :dast }
let(:report_version) { "12.37.0" }
- context 'and the report is valid' do
- let(:report_data) do
- {
- 'version' => report_version,
- 'vulnerabilities' => []
- }
- end
-
- it { is_expected.to be_empty }
- end
+ it_behaves_like 'report is valid with no warning'
context 'and the report is invalid' do
let(:report_data) do
diff --git a/spec/lib/gitlab/ci/parsers/test/junit_spec.rb b/spec/lib/gitlab/ci/parsers/test/junit_spec.rb
index 82fa11d5f98..821a5057d2e 100644
--- a/spec/lib/gitlab/ci/parsers/test/junit_spec.rb
+++ b/spec/lib/gitlab/ci/parsers/test/junit_spec.rb
@@ -4,11 +4,13 @@ require 'fast_spec_helper'
RSpec.describe Gitlab::Ci::Parsers::Test::Junit do
describe '#parse!' do
- subject { described_class.new.parse!(junit, test_suite, job: job) }
+ subject { described_class.new.parse!(junit, test_report, job: job) }
- let(:test_suite) { Gitlab::Ci::Reports::TestSuite.new('rspec') }
+ let(:job) { double(test_suite_name: 'rspec', max_test_cases_per_report: max_test_cases) }
+
+ let(:test_report) { Gitlab::Ci::Reports::TestReport.new }
+ let(:test_suite) { test_report.get_suite(job.test_suite_name) }
let(:test_cases) { flattened_test_cases(test_suite) }
- let(:job) { double(max_test_cases_per_report: max_test_cases) }
let(:max_test_cases) { 0 }
context 'when data is JUnit style XML' do
diff --git a/spec/lib/gitlab/ci/parsers_spec.rb b/spec/lib/gitlab/ci/parsers_spec.rb
index c9891c06507..a9adff4fce3 100644
--- a/spec/lib/gitlab/ci/parsers_spec.rb
+++ b/spec/lib/gitlab/ci/parsers_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'spec_helper'
+require 'fast_spec_helper'
RSpec.describe Gitlab::Ci::Parsers do
describe '.fabricate!' do
diff --git a/spec/lib/gitlab/ci/pipeline/chain/assign_partition_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/assign_partition_spec.rb
new file mode 100644
index 00000000000..15df5b2f68c
--- /dev/null
+++ b/spec/lib/gitlab/ci/pipeline/chain/assign_partition_spec.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Pipeline::Chain::AssignPartition do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { create(:user) }
+
+ let(:command) do
+ Gitlab::Ci::Pipeline::Chain::Command.new(project: project, current_user: user)
+ end
+
+ let(:pipeline) { build(:ci_pipeline, project: project) }
+ let(:step) { described_class.new(pipeline, command) }
+ let(:current_partition_id) { 123 }
+
+ describe '#perform!' do
+ before do
+ allow(Ci::Pipeline).to receive(:current_partition_value) { current_partition_id }
+ end
+
+ subject { step.perform! }
+
+ it 'assigns partition_id to pipeline' do
+ expect { subject }.to change(pipeline, :partition_id).to(current_partition_id)
+ end
+
+ context 'with parent-child pipelines' do
+ let(:bridge) do
+ instance_double(Ci::Bridge,
+ triggers_child_pipeline?: true,
+ parent_pipeline: instance_double(Ci::Pipeline, partition_id: 125))
+ end
+
+ let(:command) do
+ Gitlab::Ci::Pipeline::Chain::Command.new(
+ project: project,
+ current_user: user,
+ bridge: bridge)
+ end
+
+ it 'assigns partition_id to pipeline' do
+ expect { subject }.to change(pipeline, :partition_id).to(125)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/command_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/command_spec.rb
index de43e759193..6e8b6e40928 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/command_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/command_spec.rb
@@ -302,13 +302,13 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Command do
context 'when bridge is present' do
context 'when bridge triggers a child pipeline' do
- let(:bridge) { double(:bridge, triggers_child_pipeline?: true) }
+ let(:bridge) { instance_double(Ci::Bridge, triggers_child_pipeline?: true) }
it { is_expected.to be_truthy }
end
context 'when bridge triggers a multi-project pipeline' do
- let(:bridge) { double(:bridge, triggers_child_pipeline?: false) }
+ let(:bridge) { instance_double(Ci::Bridge, triggers_child_pipeline?: false) }
it { is_expected.to be_falsey }
end
@@ -321,6 +321,38 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Command do
end
end
+ describe '#parent_pipeline_partition_id' do
+ let(:command) { described_class.new(bridge: bridge) }
+
+ subject { command.parent_pipeline_partition_id }
+
+ context 'when bridge is present' do
+ context 'when bridge triggers a child pipeline' do
+ let(:pipeline) { instance_double(Ci::Pipeline, partition_id: 123) }
+
+ let(:bridge) do
+ instance_double(Ci::Bridge,
+ triggers_child_pipeline?: true,
+ parent_pipeline: pipeline)
+ end
+
+ it { is_expected.to eq(123) }
+ end
+
+ context 'when bridge triggers a multi-project pipeline' do
+ let(:bridge) { instance_double(Ci::Bridge, triggers_child_pipeline?: false) }
+
+ it { is_expected.to be_nil }
+ end
+ end
+
+ context 'when bridge is not present' do
+ let(:bridge) { nil }
+
+ it { is_expected.to be_nil }
+ end
+ end
+
describe '#increment_pipeline_failure_reason_counter' do
let(:command) { described_class.new }
let(:reason) { :size_limit_exceeded }
@@ -345,7 +377,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Command do
describe '#observe_step_duration' do
context 'when ci_pipeline_creation_step_duration_tracking is enabled' do
it 'adds the duration to the step duration histogram' do
- histogram = double(:histogram)
+ histogram = instance_double(Prometheus::Client::Histogram)
duration = 1.hour
expect(::Gitlab::Ci::Pipeline::Metrics).to receive(:pipeline_creation_step_duration_histogram)
diff --git a/spec/lib/gitlab/ci/pipeline/chain/config/content_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/config/content_spec.rb
index e0d656f456e..f451bd6bfef 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/config/content_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/config/content_spec.rb
@@ -11,7 +11,9 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Config::Content do
subject { described_class.new(pipeline, command) }
- describe '#perform!' do
+ # TODO: change this to `describe` and remove rubocop-disable
+ # when removing the FF ci_project_pipeline_config_refactoring
+ shared_context '#perform!' do # rubocop:disable RSpec/ContextWording
context 'when bridge job is passed in as parameter' do
let(:ci_config_path) { nil }
let(:bridge) { create(:ci_bridge) }
@@ -201,4 +203,14 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Config::Content do
end
end
end
+
+ it_behaves_like '#perform!'
+
+ context 'when the FF ci_project_pipeline_config_refactoring is disabled' do
+ before do
+ stub_feature_flags(ci_project_pipeline_config_refactoring: false)
+ end
+
+ it_behaves_like '#perform!'
+ end
end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/ensure_environments_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/ensure_environments_spec.rb
index e07a3ca9033..7fb5b0b4200 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/ensure_environments_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/ensure_environments_spec.rb
@@ -2,11 +2,13 @@
require 'spec_helper'
-RSpec.describe Gitlab::Ci::Pipeline::Chain::EnsureEnvironments do
+RSpec.describe Gitlab::Ci::Pipeline::Chain::EnsureEnvironments, :aggregate_failures do
let(:project) { create(:project) }
let(:user) { create(:user) }
let(:stage) { build(:ci_stage, project: project, statuses: [job]) }
let(:pipeline) { build(:ci_pipeline, project: project, stages: [stage]) }
+ let(:merge_request) { create(:merge_request, source_project: project) }
+ let(:environment) { project.environments.find_by_name('review/master') }
let(:command) do
Gitlab::Ci::Pipeline::Chain::Command.new(project: project, current_user: user)
@@ -24,12 +26,26 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::EnsureEnvironments do
context 'when a pipeline contains a deployment job' do
let!(:job) { build(:ci_build, :start_review_app, project: project) }
- it 'ensures environment existence for the job' do
- expect { subject }.to change { Environment.count }.by(1)
+ context 'and the environment does not exist' do
+ it 'creates the environment specified by the job' do
+ expect { subject }.to change { Environment.count }.by(1)
- expect(project.environments.find_by_name('review/master')).to be_present
- expect(job.persisted_environment.name).to eq('review/master')
- expect(job.metadata.expanded_environment_name).to eq('review/master')
+ expect(environment).to be_present
+ expect(job.persisted_environment.name).to eq('review/master')
+ expect(job.metadata.expanded_environment_name).to eq('review/master')
+ end
+
+ context 'and the pipeline is for a merge request' do
+ let(:command) do
+ Gitlab::Ci::Pipeline::Chain::Command.new(project: project, current_user: user, merge_request: merge_request)
+ end
+
+ it 'associates the environment with the merge request' do
+ expect { subject }.to change { Environment.count }.by(1)
+
+ expect(environment.merge_request).to eq(merge_request)
+ end
+ end
end
context 'when an environment has already been existed' do
@@ -40,10 +56,22 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::EnsureEnvironments do
it 'ensures environment existence for the job' do
expect { subject }.not_to change { Environment.count }
- expect(project.environments.find_by_name('review/master')).to be_present
+ expect(environment).to be_present
expect(job.persisted_environment.name).to eq('review/master')
expect(job.metadata.expanded_environment_name).to eq('review/master')
end
+
+ context 'and the pipeline is for a merge request' do
+ let(:command) do
+ Gitlab::Ci::Pipeline::Chain::Command.new(project: project, current_user: user, merge_request: merge_request)
+ end
+
+ it 'does not associate the environment with the merge request' do
+ expect { subject }.not_to change { Environment.count }
+
+ expect(environment.merge_request).to be_nil
+ end
+ end
end
context 'when an environment name contains an invalid character' do
@@ -65,7 +93,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::EnsureEnvironments do
it 'ensures environment existence for the job' do
expect { subject }.to change { Environment.count }.by(1)
- expect(project.environments.find_by_name('review/master')).to be_present
+ expect(environment).to be_present
expect(job.persisted_environment.name).to eq('review/master')
expect(job.metadata.expanded_environment_name).to eq('review/master')
end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb
index f7774e199fb..8c4f7af0ef4 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb
@@ -277,7 +277,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Seed do
non_handled_sql_queries = 2
# 1. Ci::InstanceVariable Load => `Ci::InstanceVariable#cached_data` => already cached with `fetch_memory_cache`
- # 2. Ci::Variable Load => `Project#ci_variables_for` => already cached with `Gitlab::SafeRequestStore`
extra_jobs * non_handled_sql_queries
end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/sequence_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/sequence_spec.rb
index e8eb3333b88..ee32661f267 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/sequence_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/sequence_spec.rb
@@ -83,19 +83,36 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Sequence do
.with({ source: 'push' }, 0)
end
- it 'records active jobs by pipeline plan in a histogram' do
- allow(command.metrics)
- .to receive(:active_jobs_histogram)
- .and_return(histogram)
+ describe 'active jobs by pipeline plan histogram' do
+ before do
+ allow(command.metrics)
+ .to receive(:active_jobs_histogram)
+ .and_return(histogram)
+
+ pipeline = create(:ci_pipeline, :running, project: project)
+ create_list(:ci_build, 3, pipeline: pipeline)
+ create(:ci_bridge, pipeline: pipeline)
+ end
- pipeline = create(:ci_pipeline, project: project, status: :running)
- create(:ci_build, :finished, project: project, pipeline: pipeline)
- create(:ci_build, :failed, project: project, pipeline: pipeline)
- create(:ci_build, :running, project: project, pipeline: pipeline)
- subject.build!
+ it 'counts all the active jobs' do
+ subject.build!
- expect(histogram).to have_received(:observe)
- .with(hash_including(plan: project.actual_plan_name), 3)
+ expect(histogram).to have_received(:observe)
+ .with(hash_including(plan: project.actual_plan_name), 4)
+ end
+
+ context 'when feature flag ci_limit_active_jobs_early is disabled' do
+ before do
+ stub_feature_flags(ci_limit_active_jobs_early: false)
+ end
+
+ it 'counts all the active builds' do
+ subject.build!
+
+ expect(histogram).to have_received(:observe)
+ .with(hash_including(plan: project.actual_plan_name), 3)
+ end
+ end
end
end
end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb
index fb1a360a4b7..52a00e0d501 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb
@@ -179,6 +179,70 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Validate::External do
perform!
end
end
+
+ describe 'credit_card' do
+ context 'with no registered credit_card' do
+ it 'returns the expected credit card counts' do
+ expect(::Gitlab::HTTP).to receive(:post) do |_url, params|
+ payload = Gitlab::Json.parse(params[:body])
+
+ expect(payload['credit_card']['similar_cards_count']).to eq(0)
+ expect(payload['credit_card']['similar_holder_names_count']).to eq(0)
+ end
+
+ perform!
+ end
+ end
+
+ context 'with a registered credit card' do
+ let!(:credit_card) { create(:credit_card_validation, last_digits: 10, holder_name: 'Alice', user: user) }
+
+ it 'returns the expected credit card counts' do
+ expect(::Gitlab::HTTP).to receive(:post) do |_url, params|
+ payload = Gitlab::Json.parse(params[:body])
+
+ expect(payload['credit_card']['similar_cards_count']).to eq(1)
+ expect(payload['credit_card']['similar_holder_names_count']).to eq(1)
+ end
+
+ perform!
+ end
+
+ context 'with similar credit cards registered by other users' do
+ before do
+ create(:credit_card_validation, last_digits: 10, holder_name: 'Bob')
+ end
+
+ it 'returns the expected credit card counts' do
+ expect(::Gitlab::HTTP).to receive(:post) do |_url, params|
+ payload = Gitlab::Json.parse(params[:body])
+
+ expect(payload['credit_card']['similar_cards_count']).to eq(2)
+ expect(payload['credit_card']['similar_holder_names_count']).to eq(1)
+ end
+
+ perform!
+ end
+ end
+
+ context 'with similar holder names registered by other users' do
+ before do
+ create(:credit_card_validation, last_digits: 11, holder_name: 'Alice')
+ end
+
+ it 'returns the expected credit card counts' do
+ expect(::Gitlab::HTTP).to receive(:post) do |_url, params|
+ payload = Gitlab::Json.parse(params[:body])
+
+ expect(payload['credit_card']['similar_cards_count']).to eq(1)
+ expect(payload['credit_card']['similar_holder_names_count']).to eq(2)
+ end
+
+ perform!
+ end
+ end
+ end
+ end
end
context 'when EXTERNAL_VALIDATION_SERVICE_TOKEN is set' do
diff --git a/spec/lib/gitlab/ci/pipeline/duration_spec.rb b/spec/lib/gitlab/ci/pipeline/duration_spec.rb
index e0b4928d7f7..46c7072ad8e 100644
--- a/spec/lib/gitlab/ci/pipeline/duration_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/duration_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'spec_helper'
+require 'fast_spec_helper'
RSpec.describe Gitlab::Ci::Pipeline::Duration do
let(:calculated_duration) { calculate(data) }
diff --git a/spec/lib/gitlab/ci/pipeline/expression/lexeme/null_spec.rb b/spec/lib/gitlab/ci/pipeline/expression/lexeme/null_spec.rb
index 49686d1a9bd..3ca6fd9143f 100644
--- a/spec/lib/gitlab/ci/pipeline/expression/lexeme/null_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/expression/lexeme/null_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'spec_helper'
+require 'fast_spec_helper'
RSpec.describe Gitlab::Ci::Pipeline::Expression::Lexeme::Null do
describe '.build' do
diff --git a/spec/lib/gitlab/ci/pipeline/expression/lexeme/string_spec.rb b/spec/lib/gitlab/ci/pipeline/expression/lexeme/string_spec.rb
index c6d0d2534a5..b224fca6011 100644
--- a/spec/lib/gitlab/ci/pipeline/expression/lexeme/string_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/expression/lexeme/string_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'spec_helper'
+require 'fast_spec_helper'
RSpec.describe Gitlab::Ci::Pipeline::Expression::Lexeme::String do
describe '.build' do
diff --git a/spec/lib/gitlab/ci/pipeline/expression/lexeme/variable_spec.rb b/spec/lib/gitlab/ci/pipeline/expression/lexeme/variable_spec.rb
index 3e10ca686ba..b030bd22aa1 100644
--- a/spec/lib/gitlab/ci/pipeline/expression/lexeme/variable_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/expression/lexeme/variable_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'spec_helper'
+require 'fast_spec_helper'
RSpec.describe Gitlab::Ci::Pipeline::Expression::Lexeme::Variable do
describe '.build' do
diff --git a/spec/lib/gitlab/ci/pipeline/metrics_spec.rb b/spec/lib/gitlab/ci/pipeline/metrics_spec.rb
index 83b969ff3c4..8df3c67beaa 100644
--- a/spec/lib/gitlab/ci/pipeline/metrics_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/metrics_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'spec_helper'
+require 'fast_spec_helper'
RSpec.describe ::Gitlab::Ci::Pipeline::Metrics do
describe '.pipeline_creation_step_duration_histogram' do
diff --git a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
index 890ba51157a..75f6a773c2d 100644
--- a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
@@ -97,15 +97,15 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
let(:attributes) do
{ name: 'rspec',
ref: 'master',
- job_variables: [{ key: 'VAR1', value: 'var 1', public: true },
- { key: 'VAR2', value: 'var 2', public: true }],
+ job_variables: [{ key: 'VAR1', value: 'var 1' },
+ { key: 'VAR2', value: 'var 2' }],
rules: [{ if: '$VAR == null', variables: { VAR1: 'new var 1', VAR3: 'var 3' } }] }
end
it do
- is_expected.to include(yaml_variables: [{ key: 'VAR1', value: 'new var 1', public: true },
- { key: 'VAR2', value: 'var 2', public: true },
- { key: 'VAR3', value: 'var 3', public: true }])
+ is_expected.to include(yaml_variables: [{ key: 'VAR1', value: 'new var 1' },
+ { key: 'VAR3', value: 'var 3' },
+ { key: 'VAR2', value: 'var 2' }])
end
end
@@ -114,13 +114,13 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
{
name: 'rspec',
ref: 'master',
- job_variables: [{ key: 'VARIABLE', value: 'value', public: true }],
+ job_variables: [{ key: 'VARIABLE', value: 'value' }],
tag_list: ['static-tag', '$VARIABLE', '$NO_VARIABLE']
}
end
it { is_expected.to include(tag_list: ['static-tag', 'value', '$NO_VARIABLE']) }
- it { is_expected.to include(yaml_variables: [{ key: 'VARIABLE', value: 'value', public: true }]) }
+ it { is_expected.to include(yaml_variables: [{ key: 'VARIABLE', value: 'value' }]) }
end
context 'with cache:key' do
@@ -257,19 +257,19 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
let(:attributes) do
{ name: 'rspec',
ref: 'master',
- yaml_variables: [{ key: 'VAR2', value: 'var 2', public: true },
- { key: 'VAR3', value: 'var 3', public: true }],
- job_variables: [{ key: 'VAR2', value: 'var 2', public: true },
- { key: 'VAR3', value: 'var 3', public: true }],
+ yaml_variables: [{ key: 'VAR2', value: 'var 2' },
+ { key: 'VAR3', value: 'var 3' }],
+ job_variables: [{ key: 'VAR2', value: 'var 2' },
+ { key: 'VAR3', value: 'var 3' }],
root_variables_inheritance: root_variables_inheritance }
end
context 'when the pipeline has variables' do
let(:root_variables) do
- [{ key: 'VAR1', value: 'var overridden pipeline 1', public: true },
- { key: 'VAR2', value: 'var pipeline 2', public: true },
- { key: 'VAR3', value: 'var pipeline 3', public: true },
- { key: 'VAR4', value: 'new var pipeline 4', public: true }]
+ [{ key: 'VAR1', value: 'var overridden pipeline 1' },
+ { key: 'VAR2', value: 'var pipeline 2' },
+ { key: 'VAR3', value: 'var pipeline 3' },
+ { key: 'VAR4', value: 'new var pipeline 4' }]
end
context 'when root_variables_inheritance is true' do
@@ -277,10 +277,10 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
it 'returns calculated yaml variables' do
expect(subject[:yaml_variables]).to match_array(
- [{ key: 'VAR1', value: 'var overridden pipeline 1', public: true },
- { key: 'VAR2', value: 'var 2', public: true },
- { key: 'VAR3', value: 'var 3', public: true },
- { key: 'VAR4', value: 'new var pipeline 4', public: true }]
+ [{ key: 'VAR1', value: 'var overridden pipeline 1' },
+ { key: 'VAR2', value: 'var 2' },
+ { key: 'VAR3', value: 'var 3' },
+ { key: 'VAR4', value: 'new var pipeline 4' }]
)
end
end
@@ -290,8 +290,8 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
it 'returns job variables' do
expect(subject[:yaml_variables]).to match_array(
- [{ key: 'VAR2', value: 'var 2', public: true },
- { key: 'VAR3', value: 'var 3', public: true }]
+ [{ key: 'VAR2', value: 'var 2' },
+ { key: 'VAR3', value: 'var 3' }]
)
end
end
@@ -301,9 +301,9 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
it 'returns calculated yaml variables' do
expect(subject[:yaml_variables]).to match_array(
- [{ key: 'VAR1', value: 'var overridden pipeline 1', public: true },
- { key: 'VAR2', value: 'var 2', public: true },
- { key: 'VAR3', value: 'var 3', public: true }]
+ [{ key: 'VAR1', value: 'var overridden pipeline 1' },
+ { key: 'VAR2', value: 'var 2' },
+ { key: 'VAR3', value: 'var 3' }]
)
end
end
@@ -314,8 +314,8 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
it 'returns seed yaml variables' do
expect(subject[:yaml_variables]).to match_array(
- [{ key: 'VAR2', value: 'var 2', public: true },
- { key: 'VAR3', value: 'var 3', public: true }])
+ [{ key: 'VAR2', value: 'var 2' },
+ { key: 'VAR3', value: 'var 3' }])
end
end
end
@@ -324,8 +324,8 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
let(:attributes) do
{ name: 'rspec',
ref: 'master',
- yaml_variables: [{ key: 'VAR1', value: 'var 1', public: true }],
- job_variables: [{ key: 'VAR1', value: 'var 1', public: true }],
+ yaml_variables: [{ key: 'VAR1', value: 'var 1' }],
+ job_variables: [{ key: 'VAR1', value: 'var 1' }],
root_variables_inheritance: root_variables_inheritance,
rules: rules }
end
@@ -338,14 +338,14 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
end
it 'recalculates the variables' do
- expect(subject[:yaml_variables]).to contain_exactly({ key: 'VAR1', value: 'overridden var 1', public: true },
- { key: 'VAR2', value: 'new var 2', public: true })
+ expect(subject[:yaml_variables]).to contain_exactly({ key: 'VAR1', value: 'overridden var 1' },
+ { key: 'VAR2', value: 'new var 2' })
end
end
context 'when the rules use root variables' do
let(:root_variables) do
- [{ key: 'VAR2', value: 'var pipeline 2', public: true }]
+ [{ key: 'VAR2', value: 'var pipeline 2' }]
end
let(:rules) do
@@ -353,15 +353,15 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
end
it 'recalculates the variables' do
- expect(subject[:yaml_variables]).to contain_exactly({ key: 'VAR1', value: 'overridden var 1', public: true },
- { key: 'VAR2', value: 'overridden var 2', public: true })
+ expect(subject[:yaml_variables]).to contain_exactly({ key: 'VAR1', value: 'overridden var 1' },
+ { key: 'VAR2', value: 'overridden var 2' })
end
context 'when the root_variables_inheritance is false' do
let(:root_variables_inheritance) { false }
it 'does not recalculate the variables' do
- expect(subject[:yaml_variables]).to contain_exactly({ key: 'VAR1', value: 'var 1', public: true })
+ expect(subject[:yaml_variables]).to contain_exactly({ key: 'VAR1', value: 'var 1' })
end
end
end
diff --git a/spec/lib/gitlab/ci/pipeline/seed/deployment_spec.rb b/spec/lib/gitlab/ci/pipeline/seed/deployment_spec.rb
index 51185be3e74..6569ce937ac 100644
--- a/spec/lib/gitlab/ci/pipeline/seed/deployment_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/seed/deployment_spec.rb
@@ -6,8 +6,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Deployment do
let_it_be(:project, refind: true) { create(:project, :repository) }
let(:pipeline) do
- create(:ci_pipeline, project: project,
- sha: 'b83d6e391c22777fca1ed3012fce84f633d7fed0')
+ create(:ci_pipeline, project: project, sha: 'b83d6e391c22777fca1ed3012fce84f633d7fed0')
end
let(:job) { build(:ci_build, project: project, pipeline: pipeline) }
diff --git a/spec/lib/gitlab/ci/pipeline/seed/environment_spec.rb b/spec/lib/gitlab/ci/pipeline/seed/environment_spec.rb
index ad89f1f5cda..2b9d8127886 100644
--- a/spec/lib/gitlab/ci/pipeline/seed/environment_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/seed/environment_spec.rb
@@ -5,7 +5,9 @@ require 'spec_helper'
RSpec.describe Gitlab::Ci::Pipeline::Seed::Environment do
let_it_be(:project) { create(:project) }
- let(:job) { build(:ci_build, project: project) }
+ let!(:pipeline) { create(:ci_pipeline, project: project) }
+
+ let(:job) { build(:ci_build, project: project, pipeline: pipeline) }
let(:seed) { described_class.new(job) }
let(:attributes) { {} }
@@ -87,6 +89,28 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Environment do
it_behaves_like 'returning a correct environment'
end
+
+ context 'and job environment has an auto_stop_in variable attribute' do
+ let(:environment_auto_stop_in) { '10 minutes' }
+ let(:expected_auto_stop_in) { '10 minutes' }
+
+ let(:attributes) do
+ {
+ environment: environment_name,
+ options: {
+ environment: {
+ name: environment_name,
+ auto_stop_in: '$TTL'
+ }
+ },
+ yaml_variables: [
+ { key: "TTL", value: environment_auto_stop_in, public: true }
+ ]
+ }
+ end
+
+ it_behaves_like 'returning a correct environment'
+ end
end
context 'when job has deployment tier attribute' do
@@ -167,5 +191,34 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Environment do
it_behaves_like 'returning a correct environment'
end
+
+ context 'when merge_request is provided' do
+ let(:environment_name) { 'development' }
+ let(:attributes) { { environment: environment_name, options: { environment: { name: environment_name } } } }
+ let(:merge_request) { create(:merge_request, source_project: project) }
+ let(:seed) { described_class.new(job, merge_request: merge_request) }
+
+ context 'and environment does not exist' do
+ let(:environment_name) { 'review/$CI_COMMIT_REF_NAME' }
+
+ it 'creates an environment associated with the merge request' do
+ expect { subject }.to change { Environment.count }.by(1)
+
+ expect(subject.merge_request).to eq(merge_request)
+ end
+ end
+
+ context 'and environment already exists' do
+ before do
+ create(:environment, project: project, name: environment_name)
+ end
+
+ it 'does not change the merge request associated with the environment' do
+ expect { subject }.not_to change { Environment.count }
+
+ expect(subject.merge_request).to be_nil
+ end
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/ci/processable_object_hierarchy_spec.rb b/spec/lib/gitlab/ci/processable_object_hierarchy_spec.rb
new file mode 100644
index 00000000000..a844ce6486b
--- /dev/null
+++ b/spec/lib/gitlab/ci/processable_object_hierarchy_spec.rb
@@ -0,0 +1,82 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::ProcessableObjectHierarchy do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { project.owner }
+
+ let_it_be(:pipeline) { create(:ci_empty_pipeline, project: project, ref: 'master') }
+
+ let_it_be(:job1) { create(:ci_build, :created, pipeline: pipeline, name: 'job1') }
+ let_it_be(:job2) { create(:ci_build, :created, :dependent, pipeline: pipeline, name: 'job2', needed: job1) }
+ let_it_be(:job3) { create(:ci_build, :created, :dependent, pipeline: pipeline, name: 'job3', needed: job1) }
+ let_it_be(:job4) { create(:ci_build, :created, :dependent, pipeline: pipeline, name: 'job4', needed: job2) }
+ let_it_be(:job5) { create(:ci_build, :created, :dependent, pipeline: pipeline, name: 'job5', needed: job3) }
+ let_it_be(:job6) { create(:ci_build, :created, :dependent, pipeline: pipeline, name: 'job6', needed: job4) }
+
+ describe '#base_and_ancestors' do
+ it 'includes the base and its ancestors' do
+ relation = described_class.new(::Ci::Processable.where(id: job2.id)).base_and_ancestors
+
+ expect(relation).to eq([job2, job1])
+ end
+
+ it 'can find ancestors upto a certain level' do
+ relation = described_class.new(::Ci::Processable.where(id: job4.id)).base_and_ancestors(upto: job1.name)
+
+ expect(relation).to eq([job4, job2])
+ end
+
+ describe 'hierarchy_order option' do
+ let(:relation) do
+ described_class.new(::Ci::Processable.where(id: job4.id)).base_and_ancestors(hierarchy_order: hierarchy_order)
+ end
+
+ context 'for :asc' do
+ let(:hierarchy_order) { :asc }
+
+ it 'orders by child to ancestor' do
+ expect(relation).to eq([job4, job2, job1])
+ end
+ end
+
+ context 'for :desc' do
+ let(:hierarchy_order) { :desc }
+
+ it 'orders by ancestor to child' do
+ expect(relation).to eq([job1, job2, job4])
+ end
+ end
+ end
+ end
+
+ describe '#base_and_descendants' do
+ it 'includes the base and its descendants' do
+ relation = described_class.new(::Ci::Processable.where(id: job2.id)).base_and_descendants
+
+ expect(relation).to contain_exactly(job2, job4, job6)
+ end
+
+ context 'when with_depth is true' do
+ let(:relation) do
+ described_class.new(::Ci::Processable.where(id: job1.id)).base_and_descendants(with_depth: true)
+ end
+
+ it 'includes depth in the results' do
+ object_depths = {
+ job1.id => 1,
+ job2.id => 2,
+ job3.id => 2,
+ job4.id => 3,
+ job5.id => 3,
+ job6.id => 4
+ }
+
+ relation.each do |object|
+ expect(object.depth).to eq(object_depths[object.id])
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/project_config/repository_spec.rb b/spec/lib/gitlab/ci/project_config/repository_spec.rb
new file mode 100644
index 00000000000..2105b691d9e
--- /dev/null
+++ b/spec/lib/gitlab/ci/project_config/repository_spec.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::ProjectConfig::Repository do
+ let(:project) { create(:project, :custom_repo, files: files) }
+ let(:sha) { project.repository.head_commit.sha }
+ let(:files) { { 'README.md' => 'hello' } }
+
+ subject(:config) { described_class.new(project, sha, nil, nil, nil) }
+
+ describe '#content' do
+ subject(:content) { config.content }
+
+ context 'when file is in repository' do
+ let(:config_content_result) do
+ <<~CICONFIG
+ ---
+ include:
+ - local: ".gitlab-ci.yml"
+ CICONFIG
+ end
+
+ let(:files) { { '.gitlab-ci.yml' => 'content' } }
+
+ it { is_expected.to eq(config_content_result) }
+ end
+
+ context 'when file is not in repository' do
+ it { is_expected.to be_nil }
+ end
+
+ context 'when Gitaly raises error' do
+ before do
+ allow(project.repository).to receive(:gitlab_ci_yml_for).and_raise(GRPC::Internal)
+ end
+
+ it { is_expected.to be_nil }
+ end
+ end
+
+ describe '#source' do
+ subject { config.source }
+
+ it { is_expected.to eq(:repository_source) }
+ end
+end
diff --git a/spec/lib/gitlab/ci/project_config/source_spec.rb b/spec/lib/gitlab/ci/project_config/source_spec.rb
new file mode 100644
index 00000000000..dda5c7cdce8
--- /dev/null
+++ b/spec/lib/gitlab/ci/project_config/source_spec.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::ProjectConfig::Source do
+ let_it_be(:custom_config_class) { Class.new(described_class) }
+ let_it_be(:project) { build_stubbed(:project) }
+ let_it_be(:sha) { '123456' }
+
+ subject(:custom_config) { custom_config_class.new(project, sha, nil, nil, nil) }
+
+ describe '#content' do
+ subject(:content) { custom_config.content }
+
+ it { expect { content }.to raise_error(NotImplementedError) }
+ end
+
+ describe '#source' do
+ subject(:source) { custom_config.source }
+
+ it { expect { source }.to raise_error(NotImplementedError) }
+ end
+end
diff --git a/spec/lib/gitlab/ci/project_config_spec.rb b/spec/lib/gitlab/ci/project_config_spec.rb
new file mode 100644
index 00000000000..c4b179c9ef5
--- /dev/null
+++ b/spec/lib/gitlab/ci/project_config_spec.rb
@@ -0,0 +1,177 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::ProjectConfig do
+ let(:project) { create(:project, :empty_repo, ci_config_path: ci_config_path) }
+ let(:sha) { '123456' }
+ let(:content) { nil }
+ let(:source) { :push }
+ let(:bridge) { nil }
+
+ subject(:config) do
+ described_class.new(project: project, sha: sha,
+ custom_content: content, pipeline_source: source, pipeline_source_bridge: bridge)
+ end
+
+ context 'when bridge job is passed in as parameter' do
+ let(:ci_config_path) { nil }
+ let(:bridge) { create(:ci_bridge) }
+
+ before do
+ allow(bridge).to receive(:yaml_for_downstream).and_return('the-yaml')
+ end
+
+ it 'returns the content already available in command' do
+ expect(config.source).to eq(:bridge_source)
+ expect(config.content).to eq('the-yaml')
+ end
+ end
+
+ context 'when config is defined in a custom path in the repository' do
+ let(:ci_config_path) { 'path/to/config.yml' }
+ let(:config_content_result) do
+ <<~CICONFIG
+ ---
+ include:
+ - local: #{ci_config_path}
+ CICONFIG
+ end
+
+ before do
+ allow(project.repository)
+ .to receive(:gitlab_ci_yml_for)
+ .with(sha, ci_config_path)
+ .and_return('the-content')
+ end
+
+ it 'returns root config including the local custom file' do
+ expect(config.source).to eq(:repository_source)
+ expect(config.content).to eq(config_content_result)
+ end
+ end
+
+ context 'when config is defined remotely' do
+ let(:ci_config_path) { 'http://example.com/path/to/ci/config.yml' }
+ let(:config_content_result) do
+ <<~CICONFIG
+ ---
+ include:
+ - remote: #{ci_config_path}
+ CICONFIG
+ end
+
+ it 'returns root config including the remote config' do
+ expect(config.source).to eq(:remote_source)
+ expect(config.content).to eq(config_content_result)
+ end
+ end
+
+ context 'when config is defined in a separate repository' do
+ let(:ci_config_path) { 'path/to/.gitlab-ci.yml@another-group/another-repo' }
+ let(:config_content_result) do
+ <<~CICONFIG
+ ---
+ include:
+ - project: another-group/another-repo
+ file: path/to/.gitlab-ci.yml
+ CICONFIG
+ end
+
+ it 'returns root config including the path to another repository' do
+ expect(config.source).to eq(:external_project_source)
+ expect(config.content).to eq(config_content_result)
+ end
+
+ context 'when path specifies a refname' do
+ let(:ci_config_path) { 'path/to/.gitlab-ci.yml@another-group/another-repo:refname' }
+ let(:config_content_result) do
+ <<~CICONFIG
+ ---
+ include:
+ - project: another-group/another-repo
+ file: path/to/.gitlab-ci.yml
+ ref: refname
+ CICONFIG
+ end
+
+ it 'returns root config including the path and refname to another repository' do
+ expect(config.source).to eq(:external_project_source)
+ expect(config.content).to eq(config_content_result)
+ end
+ end
+ end
+
+ context 'when config is defined in the default .gitlab-ci.yml' do
+ let(:ci_config_path) { nil }
+ let(:config_content_result) do
+ <<~CICONFIG
+ ---
+ include:
+ - local: ".gitlab-ci.yml"
+ CICONFIG
+ end
+
+ before do
+ allow(project.repository)
+ .to receive(:gitlab_ci_yml_for)
+ .with(sha, '.gitlab-ci.yml')
+ .and_return('the-content')
+ end
+
+ it 'returns root config including the canonical CI config file' do
+ expect(config.source).to eq(:repository_source)
+ expect(config.content).to eq(config_content_result)
+ end
+ end
+
+ context 'when config is the Auto-Devops template' do
+ let(:ci_config_path) { nil }
+ let(:config_content_result) do
+ <<~CICONFIG
+ ---
+ include:
+ - template: Auto-DevOps.gitlab-ci.yml
+ CICONFIG
+ end
+
+ before do
+ allow(project).to receive(:auto_devops_enabled?).and_return(true)
+ end
+
+ it 'returns root config including the auto-devops template' do
+ expect(config.source).to eq(:auto_devops_source)
+ expect(config.content).to eq(config_content_result)
+ end
+ end
+
+ context 'when config is passed as a parameter' do
+ let(:source) { :ondemand_dast_scan }
+ let(:ci_config_path) { nil }
+ let(:content) do
+ <<~CICONFIG
+ ---
+ stages:
+ - dast
+ CICONFIG
+ end
+
+ it 'returns the parameter content' do
+ expect(config.source).to eq(:parameter_source)
+ expect(config.content).to eq(content)
+ end
+ end
+
+ context 'when config is not defined anywhere' do
+ let(:ci_config_path) { nil }
+
+ before do
+ allow(project).to receive(:auto_devops_enabled?).and_return(false)
+ end
+
+ it 'returns nil' do
+ expect(config.source).to be_nil
+ expect(config.content).to be_nil
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/reports/accessibility_reports_comparer_spec.rb b/spec/lib/gitlab/ci/reports/accessibility_reports_comparer_spec.rb
index ade0e36cf1e..ad8f1dc11f8 100644
--- a/spec/lib/gitlab/ci/reports/accessibility_reports_comparer_spec.rb
+++ b/spec/lib/gitlab/ci/reports/accessibility_reports_comparer_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'spec_helper'
+require 'fast_spec_helper'
RSpec.describe Gitlab::Ci::Reports::AccessibilityReportsComparer do
let(:comparer) { described_class.new(base_report, head_report) }
diff --git a/spec/lib/gitlab/ci/reports/accessibility_reports_spec.rb b/spec/lib/gitlab/ci/reports/accessibility_reports_spec.rb
index 8c35b2a34cf..af6844491ca 100644
--- a/spec/lib/gitlab/ci/reports/accessibility_reports_spec.rb
+++ b/spec/lib/gitlab/ci/reports/accessibility_reports_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'spec_helper'
+require 'fast_spec_helper'
RSpec.describe Gitlab::Ci::Reports::AccessibilityReports do
let(:accessibility_report) { described_class.new }
diff --git a/spec/lib/gitlab/ci/reports/coverage_report_spec.rb b/spec/lib/gitlab/ci/reports/coverage_report_spec.rb
index 53646f7dfc0..23361a0c768 100644
--- a/spec/lib/gitlab/ci/reports/coverage_report_spec.rb
+++ b/spec/lib/gitlab/ci/reports/coverage_report_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'spec_helper'
+require 'fast_spec_helper'
RSpec.describe Gitlab::Ci::Reports::CoverageReport do
let(:coverage_report) { described_class.new }
diff --git a/spec/lib/gitlab/ci/reports/sbom/component_spec.rb b/spec/lib/gitlab/ci/reports/sbom/component_spec.rb
index 672117c311f..06ea3433ef0 100644
--- a/spec/lib/gitlab/ci/reports/sbom/component_spec.rb
+++ b/spec/lib/gitlab/ci/reports/sbom/component_spec.rb
@@ -1,23 +1,23 @@
# frozen_string_literal: true
-require 'spec_helper'
+require 'fast_spec_helper'
RSpec.describe Gitlab::Ci::Reports::Sbom::Component do
let(:attributes) do
{
- 'type' => 'library',
- 'name' => 'component-name',
- 'version' => 'v0.0.1'
+ type: 'library',
+ name: 'component-name',
+ version: 'v0.0.1'
}
end
- subject { described_class.new(attributes) }
+ subject { described_class.new(**attributes) }
it 'has correct attributes' do
expect(subject).to have_attributes(
- component_type: 'library',
- name: 'component-name',
- version: 'v0.0.1'
+ component_type: attributes[:type],
+ name: attributes[:name],
+ version: attributes[:version]
)
end
end
diff --git a/spec/lib/gitlab/ci/reports/sbom/report_spec.rb b/spec/lib/gitlab/ci/reports/sbom/report_spec.rb
index d7a285ab13c..6ffa93e5fc8 100644
--- a/spec/lib/gitlab/ci/reports/sbom/report_spec.rb
+++ b/spec/lib/gitlab/ci/reports/sbom/report_spec.rb
@@ -15,40 +15,22 @@ RSpec.describe Gitlab::Ci::Reports::Sbom::Report do
end
describe '#set_source' do
- let_it_be(:source) do
- {
- 'type' => :dependency_scanning,
- 'data' => {
- 'input_file' => { 'path' => 'package-lock.json' },
- 'source_file' => { 'path' => 'package.json' },
- 'package_manager' => { 'name' => 'npm' },
- 'language' => { 'name' => 'JavaScript' }
- },
- 'fingerprint' => 'c01df1dc736c1148717e053edbde56cb3a55d3e31f87cea955945b6f67c17d42'
- }
- end
+ let_it_be(:source) { create(:ci_reports_sbom_source) }
it 'stores the source' do
report.set_source(source)
- expect(report.source).to be_a(Gitlab::Ci::Reports::Sbom::Source)
+ expect(report.source).to eq(source)
end
end
describe '#add_component' do
- let_it_be(:components) do
- [
- { 'type' => 'library', 'name' => 'component1', 'version' => 'v0.0.1' },
- { 'type' => 'library', 'name' => 'component2', 'version' => 'v0.0.2' },
- { 'type' => 'library', 'name' => 'component2' }
- ]
- end
+ let_it_be(:components) { create_list(:ci_reports_sbom_component, 3) }
it 'appends components to a list' do
components.each { |component| report.add_component(component) }
- expect(report.components.size).to eq(3)
- expect(report.components).to all(be_a(Gitlab::Ci::Reports::Sbom::Component))
+ expect(report.components).to match_array(components)
end
end
end
diff --git a/spec/lib/gitlab/ci/reports/sbom/reports_spec.rb b/spec/lib/gitlab/ci/reports/sbom/reports_spec.rb
index 97d8d7abb33..75ea91251eb 100644
--- a/spec/lib/gitlab/ci/reports/sbom/reports_spec.rb
+++ b/spec/lib/gitlab/ci/reports/sbom/reports_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'spec_helper'
+require 'fast_spec_helper'
RSpec.describe Gitlab::Ci::Reports::Sbom::Reports do
subject(:reports_list) { described_class.new }
diff --git a/spec/lib/gitlab/ci/reports/sbom/source_spec.rb b/spec/lib/gitlab/ci/reports/sbom/source_spec.rb
index 2d6434534a0..cb30bd721dd 100644
--- a/spec/lib/gitlab/ci/reports/sbom/source_spec.rb
+++ b/spec/lib/gitlab/ci/reports/sbom/source_spec.rb
@@ -1,29 +1,29 @@
# frozen_string_literal: true
-require 'spec_helper'
+require 'fast_spec_helper'
RSpec.describe Gitlab::Ci::Reports::Sbom::Source do
let(:attributes) do
{
- 'type' => :dependency_scanning,
- 'data' => {
+ type: :dependency_scanning,
+ data: {
'category' => 'development',
'input_file' => { 'path' => 'package-lock.json' },
'source_file' => { 'path' => 'package.json' },
'package_manager' => { 'name' => 'npm' },
'language' => { 'name' => 'JavaScript' }
},
- 'fingerprint' => '4dbcb747e6f0fb3ed4f48d96b777f1d64acdf43e459fdfefad404e55c004a188'
+ fingerprint: '4dbcb747e6f0fb3ed4f48d96b777f1d64acdf43e459fdfefad404e55c004a188'
}
end
- subject { described_class.new(attributes) }
+ subject { described_class.new(**attributes) }
it 'has correct attributes' do
expect(subject).to have_attributes(
- source_type: attributes['type'],
- data: attributes['data'],
- fingerprint: attributes['fingerprint']
+ source_type: attributes[:type],
+ data: attributes[:data],
+ fingerprint: attributes[:fingerprint]
)
end
end
diff --git a/spec/lib/gitlab/ci/reports/security/flag_spec.rb b/spec/lib/gitlab/ci/reports/security/flag_spec.rb
index d677425a8da..6ee074f7aeb 100644
--- a/spec/lib/gitlab/ci/reports/security/flag_spec.rb
+++ b/spec/lib/gitlab/ci/reports/security/flag_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'spec_helper'
+require 'fast_spec_helper'
RSpec.describe Gitlab::Ci::Reports::Security::Flag do
subject(:security_flag) { described_class.new(type: 'flagged-as-likely-false-positive', origin: 'post analyzer X', description: 'static string to sink') }
diff --git a/spec/lib/gitlab/ci/reports/security/link_spec.rb b/spec/lib/gitlab/ci/reports/security/link_spec.rb
index 7b55af27f4d..0e1cdc93f6c 100644
--- a/spec/lib/gitlab/ci/reports/security/link_spec.rb
+++ b/spec/lib/gitlab/ci/reports/security/link_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'spec_helper'
+require 'fast_spec_helper'
RSpec.describe Gitlab::Ci::Reports::Security::Link do
subject(:security_link) { described_class.new(name: 'CVE-2020-0202', url: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-0202') }
diff --git a/spec/lib/gitlab/ci/reports/security/scan_spec.rb b/spec/lib/gitlab/ci/reports/security/scan_spec.rb
index b4968ff3a6e..23427e8608c 100644
--- a/spec/lib/gitlab/ci/reports/security/scan_spec.rb
+++ b/spec/lib/gitlab/ci/reports/security/scan_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'spec_helper'
+require 'fast_spec_helper'
RSpec.describe Gitlab::Ci::Reports::Security::Scan do
describe '#initialize' do
diff --git a/spec/lib/gitlab/ci/reports/security/scanned_resource_spec.rb b/spec/lib/gitlab/ci/reports/security/scanned_resource_spec.rb
index e9daa05e8b9..74a5344f79e 100644
--- a/spec/lib/gitlab/ci/reports/security/scanned_resource_spec.rb
+++ b/spec/lib/gitlab/ci/reports/security/scanned_resource_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'spec_helper'
+require 'fast_spec_helper'
RSpec.describe Gitlab::Ci::Reports::Security::ScannedResource do
let(:url) { 'http://example.com:3001/1?foo=bar' }
diff --git a/spec/lib/gitlab/ci/reports/terraform_reports_spec.rb b/spec/lib/gitlab/ci/reports/terraform_reports_spec.rb
index 5e94fe2bb3d..f754786d071 100644
--- a/spec/lib/gitlab/ci/reports/terraform_reports_spec.rb
+++ b/spec/lib/gitlab/ci/reports/terraform_reports_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'spec_helper'
+require 'fast_spec_helper'
RSpec.describe Gitlab::Ci::Reports::TerraformReports do
it 'initializes plans with and empty hash' do
diff --git a/spec/lib/gitlab/ci/status/extended_spec.rb b/spec/lib/gitlab/ci/status/extended_spec.rb
index 3e1004754ba..e81c7b0f6be 100644
--- a/spec/lib/gitlab/ci/status/extended_spec.rb
+++ b/spec/lib/gitlab/ci/status/extended_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'spec_helper'
+require 'fast_spec_helper'
RSpec.describe Gitlab::Ci::Status::Extended do
it 'requires subclass to implement matcher' do
diff --git a/spec/lib/gitlab/ci/status/group/factory_spec.rb b/spec/lib/gitlab/ci/status/group/factory_spec.rb
index c67c7ff8271..38aa1ba4ebb 100644
--- a/spec/lib/gitlab/ci/status/group/factory_spec.rb
+++ b/spec/lib/gitlab/ci/status/group/factory_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'spec_helper'
+require 'fast_spec_helper'
RSpec.describe Gitlab::Ci::Status::Group::Factory do
it 'inherits from the core factory' do
diff --git a/spec/lib/gitlab/ci/templates/katalon_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/katalon_gitlab_ci_yaml_spec.rb
new file mode 100644
index 00000000000..5a62324da74
--- /dev/null
+++ b/spec/lib/gitlab/ci/templates/katalon_gitlab_ci_yaml_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Katalon.gitlab-ci.yml' do
+ subject(:template) do
+ <<~YAML
+ include:
+ - template: 'Katalon.gitlab-ci.yml'
+
+ katalon_tests_placeholder:
+ extends: .katalon_tests
+ stage: test
+ script:
+ - echo "katalon tests"
+
+ katalon_tests_with_artifacts_placeholder:
+ extends: .katalon_tests_with_artifacts
+ stage: test
+ script:
+ - echo "katalon tests with artifacts"
+ YAML
+ end
+
+ describe 'the created pipeline' do
+ let(:project) { create(:project, :custom_repo, files: { 'README.md' => '' }) }
+ let(:user) { project.first_owner }
+
+ let(:service) { Ci::CreatePipelineService.new(project, user, ref: 'master' ) }
+ let(:pipeline) { service.execute!(:push).payload }
+ let(:build_names) { pipeline.builds.pluck(:name) }
+
+ before do
+ stub_ci_pipeline_yaml_file(template)
+ end
+
+ it 'create katalon tests jobs' do
+ expect(build_names).to match_array(%w[katalon_tests_placeholder katalon_tests_with_artifacts_placeholder])
+
+ expect(pipeline.builds.find_by(name: 'katalon_tests_placeholder').options).to include(
+ image: { name: 'katalonstudio/katalon' },
+ services: [{ name: 'docker:dind' }]
+ )
+
+ expect(pipeline.builds.find_by(name: 'katalon_tests_with_artifacts_placeholder').options).to include(
+ image: { name: 'katalonstudio/katalon' },
+ services: [{ name: 'docker:dind' }],
+ artifacts: { when: 'always', paths: ['Reports/'], reports: { junit: ['Reports/*/*/*/*.xml'] } }
+ )
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/trace/archive_spec.rb b/spec/lib/gitlab/ci/trace/archive_spec.rb
index 3ae0e5d1f0e..f91cb03883a 100644
--- a/spec/lib/gitlab/ci/trace/archive_spec.rb
+++ b/spec/lib/gitlab/ci/trace/archive_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Ci::Trace::Archive do
context 'with transactional fixtures' do
- let_it_be(:job) { create(:ci_build, :success, :trace_live) }
+ let_it_be_with_reload(:job) { create(:ci_build, :success, :trace_live) }
let_it_be_with_reload(:trace_metadata) { create(:ci_build_trace_metadata, build: job) }
let_it_be(:src_checksum) do
job.trace.read { |stream| Digest::MD5.hexdigest(stream.raw) }
diff --git a/spec/lib/gitlab/ci/trace_spec.rb b/spec/lib/gitlab/ci/trace_spec.rb
index 888ceb7ff9a..3043c8c5467 100644
--- a/spec/lib/gitlab/ci/trace_spec.rb
+++ b/spec/lib/gitlab/ci/trace_spec.rb
@@ -10,7 +10,6 @@ RSpec.describe Gitlab::Ci::Trace, :clean_gitlab_redis_shared_state, factory_defa
describe "associations" do
it { expect(trace).to respond_to(:job) }
- it { expect(trace).to delegate_method(:old_trace).to(:job) }
end
context 'when trace is migrated to object storage' do
diff --git a/spec/lib/gitlab/ci/variables/builder_spec.rb b/spec/lib/gitlab/ci/variables/builder_spec.rb
index 6ab2089cce8..4833ccf9093 100644
--- a/spec/lib/gitlab/ci/variables/builder_spec.rb
+++ b/spec/lib/gitlab/ci/variables/builder_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::Ci::Variables::Builder do
+RSpec.describe Gitlab::Ci::Variables::Builder, :clean_gitlab_redis_cache do
include Ci::TemplateHelpers
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, :repository, namespace: group) }
@@ -26,13 +26,13 @@ RSpec.describe Gitlab::Ci::Variables::Builder do
{ key: 'CI_JOB_NAME',
value: job.name },
{ key: 'CI_JOB_STAGE',
- value: job.stage },
+ value: job.stage_name },
{ key: 'CI_NODE_TOTAL',
value: '1' },
{ key: 'CI_BUILD_NAME',
value: job.name },
{ key: 'CI_BUILD_STAGE',
- value: job.stage },
+ value: job.stage_name },
{ key: 'CI',
value: 'true' },
{ key: 'GITLAB_CI',
@@ -138,11 +138,11 @@ RSpec.describe Gitlab::Ci::Variables::Builder do
{ key: 'GITLAB_USER_ID',
value: user.id.to_s },
{ key: 'GITLAB_USER_EMAIL',
- value: user.email },
+ value: user.email },
{ key: 'GITLAB_USER_LOGIN',
- value: user.username },
+ value: user.username },
{ key: 'GITLAB_USER_NAME',
- value: user.name }
+ value: user.name }
].map { |var| var.merge(public: true, masked: false) }
end
diff --git a/spec/lib/gitlab/ci/variables/collection/sort_spec.rb b/spec/lib/gitlab/ci/variables/collection/sort_spec.rb
index 7e4e9602a92..57171e5be69 100644
--- a/spec/lib/gitlab/ci/variables/collection/sort_spec.rb
+++ b/spec/lib/gitlab/ci/variables/collection/sort_spec.rb
@@ -2,6 +2,7 @@
require 'fast_spec_helper'
require 'rspec-parameterized'
+require 'tsort'
RSpec.describe Gitlab::Ci::Variables::Collection::Sort do
describe '#initialize with non-Collection value' do
diff --git a/spec/lib/gitlab/ci/variables/helpers_spec.rb b/spec/lib/gitlab/ci/variables/helpers_spec.rb
index fc1055751bd..fb1e66bd605 100644
--- a/spec/lib/gitlab/ci/variables/helpers_spec.rb
+++ b/spec/lib/gitlab/ci/variables/helpers_spec.rb
@@ -15,21 +15,21 @@ RSpec.describe Gitlab::Ci::Variables::Helpers do
end
let(:result) do
- [{ key: 'key1', value: 'value1', public: true },
- { key: 'key2', value: 'value22', public: true },
- { key: 'key3', value: 'value3', public: true }]
+ [{ key: 'key1', value: 'value1' },
+ { key: 'key2', value: 'value22' },
+ { key: 'key3', value: 'value3' }]
end
subject { described_class.merge_variables(current_variables, new_variables) }
- it { is_expected.to eq(result) }
+ it { is_expected.to match_array(result) }
context 'when new variables is a hash' do
let(:new_variables) do
{ 'key2' => 'value22', 'key3' => 'value3' }
end
- it { is_expected.to eq(result) }
+ it { is_expected.to match_array(result) }
end
context 'when new variables is a hash with symbol keys' do
@@ -37,79 +37,68 @@ RSpec.describe Gitlab::Ci::Variables::Helpers do
{ key2: 'value22', key3: 'value3' }
end
- it { is_expected.to eq(result) }
+ it { is_expected.to match_array(result) }
end
context 'when new variables is nil' do
let(:new_variables) {}
let(:result) do
- [{ key: 'key1', value: 'value1', public: true },
- { key: 'key2', value: 'value2', public: true }]
+ [{ key: 'key1', value: 'value1' },
+ { key: 'key2', value: 'value2' }]
end
- it { is_expected.to eq(result) }
+ it { is_expected.to match_array(result) }
end
end
- describe '.transform_to_yaml_variables' do
- let(:variables) do
- { 'key1' => 'value1', 'key2' => 'value2' }
- end
-
- let(:result) do
- [{ key: 'key1', value: 'value1', public: true },
- { key: 'key2', value: 'value2', public: true }]
- end
-
- subject { described_class.transform_to_yaml_variables(variables) }
-
- it { is_expected.to eq(result) }
+ describe '.transform_to_array' do
+ subject { described_class.transform_to_array(variables) }
- context 'when variables is nil' do
- let(:variables) {}
-
- it { is_expected.to eq([]) }
- end
- end
+ context 'when values are strings' do
+ let(:variables) do
+ { 'key1' => 'value1', 'key2' => 'value2' }
+ end
- describe '.transform_from_yaml_variables' do
- let(:variables) do
- [{ key: 'key1', value: 'value1', public: true },
- { key: 'key2', value: 'value2', public: true }]
- end
+ let(:result) do
+ [{ key: 'key1', value: 'value1' },
+ { key: 'key2', value: 'value2' }]
+ end
- let(:result) do
- { 'key1' => 'value1', 'key2' => 'value2' }
+ it { is_expected.to match_array(result) }
end
- subject { described_class.transform_from_yaml_variables(variables) }
-
- it { is_expected.to eq(result) }
-
context 'when variables is nil' do
let(:variables) {}
- it { is_expected.to eq({}) }
+ it { is_expected.to match_array([]) }
end
- context 'when variables is a hash' do
+ context 'when values are hashes' do
let(:variables) do
- { key1: 'value1', 'key2' => 'value2' }
+ { 'key1' => { value: 'value1', description: 'var 1' }, 'key2' => { value: 'value2' } }
end
- it { is_expected.to eq(result) }
- end
-
- context 'when variables contain integers and symbols' do
- let(:variables) do
- { key1: 1, key2: :value2 }
+ let(:result) do
+ [{ key: 'key1', value: 'value1', description: 'var 1' },
+ { key: 'key2', value: 'value2' }]
end
- let(:result1) do
- { 'key1' => '1', 'key2' => 'value2' }
- end
+ it { is_expected.to match_array(result) }
+
+ context 'when a value data has `key` as a key' do
+ let(:variables) do
+ { 'key1' => { value: 'value1', key: 'new_key1' }, 'key2' => { value: 'value2' } }
+ end
+
+ let(:result) do
+ [{ key: 'key1', value: 'value1' },
+ { key: 'key2', value: 'value2' }]
+ end
- it { is_expected.to eq(result1) }
+ it 'ignores the key set with "key"' do
+ is_expected.to match_array(result)
+ end
+ end
end
end
@@ -127,35 +116,35 @@ RSpec.describe Gitlab::Ci::Variables::Helpers do
let(:inheritance) { true }
let(:result) do
- [{ key: 'key1', value: 'value1', public: true },
- { key: 'key2', value: 'value22', public: true },
- { key: 'key3', value: 'value3', public: true }]
+ [{ key: 'key1', value: 'value1' },
+ { key: 'key2', value: 'value22' },
+ { key: 'key3', value: 'value3' }]
end
subject { described_class.inherit_yaml_variables(from: from, to: to, inheritance: inheritance) }
- it { is_expected.to eq(result) }
+ it { is_expected.to match_array(result) }
context 'when inheritance is false' do
let(:inheritance) { false }
let(:result) do
- [{ key: 'key2', value: 'value22', public: true },
- { key: 'key3', value: 'value3', public: true }]
+ [{ key: 'key2', value: 'value22' },
+ { key: 'key3', value: 'value3' }]
end
- it { is_expected.to eq(result) }
+ it { is_expected.to match_array(result) }
end
context 'when inheritance is array' do
let(:inheritance) { ['key2'] }
let(:result) do
- [{ key: 'key2', value: 'value22', public: true },
- { key: 'key3', value: 'value3', public: true }]
+ [{ key: 'key2', value: 'value22' },
+ { key: 'key3', value: 'value3' }]
end
- it { is_expected.to eq(result) }
+ it { is_expected.to match_array(result) }
end
end
end
diff --git a/spec/lib/gitlab/ci/yaml_processor/dag_spec.rb b/spec/lib/gitlab/ci/yaml_processor/dag_spec.rb
index f815f56543c..082febacbd7 100644
--- a/spec/lib/gitlab/ci/yaml_processor/dag_spec.rb
+++ b/spec/lib/gitlab/ci/yaml_processor/dag_spec.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
require 'fast_spec_helper'
+require 'tsort'
RSpec.describe Gitlab::Ci::YamlProcessor::Dag do
let(:nodes) { {} }
diff --git a/spec/lib/gitlab/ci/yaml_processor/feature_flags_spec.rb b/spec/lib/gitlab/ci/yaml_processor/feature_flags_spec.rb
index 0bd9563d191..77346f328ca 100644
--- a/spec/lib/gitlab/ci/yaml_processor/feature_flags_spec.rb
+++ b/spec/lib/gitlab/ci/yaml_processor/feature_flags_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'fast_spec_helper'
+require 'spec_helper'
RSpec.describe Gitlab::Ci::YamlProcessor::FeatureFlags do
let(:feature_flag) { :my_feature_flag }
@@ -48,20 +48,32 @@ RSpec.describe Gitlab::Ci::YamlProcessor::FeatureFlags do
end
context 'when feature flag is checked outside the "with_actor" block' do
- it 'raises an error on dev/test environment' do
- expect { described_class.enabled?(feature_flag) }.to raise_error(described_class::NoActorError)
- end
+ context 'when yaml_processor_feature_flag_corectness is used', :yaml_processor_feature_flag_corectness do
+ it 'raises an error on dev/test environment' do
+ expect { described_class.enabled?(feature_flag) }.to raise_error(described_class::NoActorError)
+ end
+
+ context 'when on production' do
+ before do
+ allow(Gitlab::ErrorTracking).to receive(:should_raise_for_dev?).and_return(false)
+ end
- context 'when on production' do
- before do
- allow(Gitlab::ErrorTracking).to receive(:should_raise_for_dev?).and_return(false)
+ it 'checks the feature flag without actor' do
+ expect(Feature).to receive(:enabled?).with(feature_flag, nil)
+ expect(Gitlab::ErrorTracking)
+ .to receive(:track_and_raise_for_dev_exception)
+ .and_call_original
+
+ described_class.enabled?(feature_flag)
+ end
end
+ end
+ context 'when yaml_processor_feature_flag_corectness is not used' do
it 'checks the feature flag without actor' do
expect(Feature).to receive(:enabled?).with(feature_flag, nil)
expect(Gitlab::ErrorTracking)
- .to receive(:track_and_raise_for_dev_exception)
- .and_call_original
+ .to receive(:track_exception)
described_class.enabled?(feature_flag)
end
diff --git a/spec/lib/gitlab/ci/yaml_processor/result_spec.rb b/spec/lib/gitlab/ci/yaml_processor/result_spec.rb
index 8416501e949..f7a0905d9da 100644
--- a/spec/lib/gitlab/ci/yaml_processor/result_spec.rb
+++ b/spec/lib/gitlab/ci/yaml_processor/result_spec.rb
@@ -72,8 +72,8 @@ module Gitlab
it 'returns calculated variables with root and job variables' do
is_expected.to match_array([
- { key: 'VAR1', value: 'value 11', public: true },
- { key: 'VAR2', value: 'value 2', public: true }
+ { key: 'VAR1', value: 'value 11' },
+ { key: 'VAR2', value: 'value 2' }
])
end
diff --git a/spec/lib/gitlab/ci/yaml_processor_spec.rb b/spec/lib/gitlab/ci/yaml_processor_spec.rb
index 35af9ae6201..cc327f5b5f1 100644
--- a/spec/lib/gitlab/ci/yaml_processor_spec.rb
+++ b/spec/lib/gitlab/ci/yaml_processor_spec.rb
@@ -298,8 +298,8 @@ module Gitlab
context 'when delayed is defined' do
let(:config) do
YAML.dump(rspec: {
- script: 'rollout 10%',
- when: 'delayed',
+ script: 'rollout 10%',
+ when: 'delayed',
start_in: '1 day'
})
end
@@ -315,7 +315,7 @@ module Gitlab
context 'when resource group is defined' do
let(:config) do
YAML.dump(rspec: {
- script: 'test',
+ script: 'test',
resource_group: 'iOS'
})
end
@@ -448,7 +448,7 @@ module Gitlab
it 'parses the root:variables as #root_variables' do
expect(subject.root_variables)
- .to contain_exactly({ key: 'SUPPORTED', value: 'parsed', public: true })
+ .to contain_exactly({ key: 'SUPPORTED', value: 'parsed' })
end
end
@@ -490,7 +490,7 @@ module Gitlab
it 'parses the root:variables as #root_variables' do
expect(subject.root_variables)
- .to contain_exactly({ key: 'SUPPORTED', value: 'parsed', public: true })
+ .to contain_exactly({ key: 'SUPPORTED', value: 'parsed' })
end
end
@@ -997,18 +997,6 @@ module Gitlab
scheduling_type: :stage
})
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_expected.not_to be_valid }
-
- it "returns no job" do
- expect(processor.jobs).to eq({})
- end
- end
end
context 'when a service has pull_policy' do
@@ -1042,39 +1030,29 @@ module Gitlab
scheduling_type: :stage
})
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_expected.not_to be_valid }
-
- it "returns no job" do
- expect(processor.jobs).to eq({})
- end
- end
end
end
- describe 'Variables' do
- subject { Gitlab::Ci::YamlProcessor.new(YAML.dump(config)).execute }
+ # Change this to a `describe` block when removing the FF ci_variables_refactoring_to_variable
+ shared_examples 'Variables' do
+ subject(:execute) { described_class.new(config).execute }
- let(:build) { subject.builds.first }
+ let(:build) { execute.builds.first }
let(:job_variables) { build[:job_variables] }
let(:root_variables_inheritance) { build[:root_variables_inheritance] }
context 'when global variables are defined' do
- let(:variables) do
- { 'VAR1' => 'value1', 'VAR2' => 'value2' }
- end
-
let(:config) do
- {
- variables: variables,
- before_script: ['pwd'],
- rspec: { script: 'rspec' }
- }
+ <<~YAML
+ variables:
+ VAR1: value1
+ VAR2: value2
+
+ before_script: [pwd]
+
+ rspec:
+ script: rspec
+ YAML
end
it 'returns global variables' do
@@ -1084,22 +1062,23 @@ module Gitlab
end
context 'when job variables are defined' do
- let(:config) do
- {
- before_script: ['pwd'],
- rspec: { script: 'rspec', variables: variables }
- }
- end
-
context 'when syntax is correct' do
- let(:variables) do
- { 'VAR1' => 'value1', 'VAR2' => 'value2' }
+ let(:config) do
+ <<~YAML
+ before_script: [pwd]
+
+ rspec:
+ script: rspec
+ variables:
+ VAR1: value1
+ VAR2: value2
+ YAML
end
it 'returns job variables' do
expect(job_variables).to contain_exactly(
- { key: 'VAR1', value: 'value1', public: true },
- { key: 'VAR2', value: 'value2', public: true }
+ { key: 'VAR1', value: 'value1' },
+ { key: 'VAR2', value: 'value2' }
)
expect(root_variables_inheritance).to eq(true)
end
@@ -1107,16 +1086,28 @@ module Gitlab
context 'when syntax is incorrect' do
context 'when variables defined but invalid' do
- let(:variables) do
- %w(VAR1 value1 VAR2 value2)
+ let(:config) do
+ <<~YAML
+ before_script: [pwd]
+
+ rspec:
+ script: rspec
+ variables: [VAR1 value1 VAR2 value2]
+ YAML
end
- it_behaves_like 'returns errors', /jobs:rspec:variables config should be a hash of key value pairs/
+ it_behaves_like 'returns errors', /jobs:rspec:variables config should be a hash/
end
context 'when variables key defined but value not specified' do
- let(:variables) do
- nil
+ let(:config) do
+ <<~YAML
+ before_script: [pwd]
+
+ rspec:
+ script: rspec
+ variables: null
+ YAML
end
it 'returns empty array' do
@@ -1133,10 +1124,12 @@ module Gitlab
context 'when job variables are not defined' do
let(:config) do
- {
- before_script: ['pwd'],
- rspec: { script: 'rspec' }
- }
+ <<~YAML
+ before_script: ['pwd']
+
+ rspec:
+ script: rspec
+ YAML
end
it 'returns empty array' do
@@ -1144,6 +1137,42 @@ module Gitlab
expect(root_variables_inheritance).to eq(true)
end
end
+
+ context 'when variables have different type of values' do
+ let(:config) do
+ <<~YAML
+ before_script: [pwd]
+
+ rspec:
+ variables:
+ VAR1: value1
+ VAR2: :value2
+ VAR3: 123
+ script: rspec
+ YAML
+ end
+
+ it 'returns job variables' do
+ expect(job_variables).to contain_exactly(
+ { key: 'VAR1', value: 'value1' },
+ { key: 'VAR2', value: 'value2' },
+ { key: 'VAR3', value: '123' }
+ )
+ expect(root_variables_inheritance).to eq(true)
+ end
+ end
+ end
+
+ context 'when ci_variables_refactoring_to_variable is enabled' do
+ it_behaves_like 'Variables'
+ end
+
+ context 'when ci_variables_refactoring_to_variable is disabled' do
+ before do
+ stub_feature_flags(ci_variables_refactoring_to_variable: false)
+ end
+
+ it_behaves_like 'Variables'
end
context 'when using `extends`' do
@@ -1203,21 +1232,21 @@ module Gitlab
expect(config_processor.builds[0]).to include(
name: 'test1',
options: { script: ['test'] },
- job_variables: [{ key: 'VAR1', value: 'test1 var 1', public: true },
- { key: 'VAR2', value: 'test2 var 2', public: true }]
+ job_variables: [{ key: 'VAR1', value: 'test1 var 1' },
+ { key: 'VAR2', value: 'test2 var 2' }]
)
expect(config_processor.builds[1]).to include(
name: 'test2',
options: { script: ['test'] },
- job_variables: [{ key: 'VAR1', value: 'base var 1', public: true },
- { key: 'VAR2', value: 'test2 var 2', public: true }]
+ job_variables: [{ key: 'VAR1', value: 'base var 1' },
+ { key: 'VAR2', value: 'test2 var 2' }]
)
expect(config_processor.builds[2]).to include(
name: 'test3',
options: { script: ['test'] },
- job_variables: [{ key: 'VAR1', value: 'base var 1', public: true }]
+ job_variables: [{ key: 'VAR1', value: 'base var 1' }]
)
expect(config_processor.builds[3]).to include(
@@ -1647,10 +1676,10 @@ module Gitlab
describe "Artifacts" do
it "returns artifacts when defined" do
config = YAML.dump({
- image: "image:1.0",
- services: ["mysql"],
+ image: "image:1.0",
+ services: ["mysql"],
before_script: ["pwd"],
- rspec: {
+ rspec: {
artifacts: {
paths: ["logs/", "binaries/"],
expose_as: "Exposed artifacts",
@@ -1906,7 +1935,7 @@ module Gitlab
let(:config) do
{
deploy_to_production: {
- stage: 'deploy',
+ stage: 'deploy',
script: 'test'
}
}
@@ -2275,15 +2304,15 @@ module Gitlab
let(:config) do
{
- var_default: { stage: 'build', script: 'test', rules: [{ if: '$VAR == null' }] },
- var_when: { stage: 'build', script: 'test', rules: [{ if: '$VAR == null', when: 'always' }] },
+ var_default: { stage: 'build', script: 'test', rules: [{ if: '$VAR == null' }] },
+ var_when: { stage: 'build', script: 'test', rules: [{ if: '$VAR == null', when: 'always' }] },
var_and_changes: { stage: 'build', script: 'test', rules: [{ if: '$VAR == null', changes: %w[README], when: 'always' }] },
changes_not_var: { stage: 'test', script: 'test', rules: [{ if: '$VAR != null', changes: %w[README] }] },
var_not_changes: { stage: 'test', script: 'test', rules: [{ if: '$VAR == null', changes: %w[other/file.rb], when: 'always' }] },
- nothing: { stage: 'test', script: 'test', rules: [{ when: 'manual' }] },
- var_never: { stage: 'deploy', script: 'test', rules: [{ if: '$VAR == null', when: 'never' }] },
- var_delayed: { stage: 'deploy', script: 'test', rules: [{ if: '$VAR == null', when: 'delayed', start_in: '3 hours' }] },
- two_rules: { stage: 'deploy', script: 'test', rules: [{ if: '$VAR == null', when: 'on_success' }, { changes: %w[README], when: 'manual' }] }
+ nothing: { stage: 'test', script: 'test', rules: [{ when: 'manual' }] },
+ var_never: { stage: 'deploy', script: 'test', rules: [{ if: '$VAR == null', when: 'never' }] },
+ var_delayed: { stage: 'deploy', script: 'test', rules: [{ if: '$VAR == null', when: 'delayed', start_in: '3 hours' }] },
+ two_rules: { stage: 'deploy', script: 'test', rules: [{ if: '$VAR == null', when: 'on_success' }, { changes: %w[README], when: 'manual' }] }
}
end
@@ -2729,13 +2758,13 @@ module Gitlab
context 'returns errors if variables is not a map' do
let(:config) { YAML.dump({ variables: "test", rspec: { script: "test" } }) }
- it_behaves_like 'returns errors', 'variables config should be a hash of key value pairs, value can be a hash'
+ it_behaves_like 'returns errors', 'variables config should be a hash'
end
context 'returns errors if variables is not a map of key-value strings' do
let(:config) { YAML.dump({ variables: { test: false }, rspec: { script: "test" } }) }
- it_behaves_like 'returns errors', 'variables config should be a hash of key value pairs, value can be a hash'
+ it_behaves_like 'returns errors', 'variable definition must be either a string or a hash'
end
context 'returns errors if job when is not on_success, on_failure or always' do