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/build/rules/rule/clause/exists_spec.rb42
-rw-r--r--spec/lib/gitlab/ci/config/entry/bridge_spec.rb36
-rw-r--r--spec/lib/gitlab/ci/config/entry/job_spec.rb22
-rw-r--r--spec/lib/gitlab/ci/config/entry/processable_spec.rb27
-rw-r--r--spec/lib/gitlab/ci/config/entry/root_spec.rb29
-rw-r--r--spec/lib/gitlab/ci/config/entry/variable_spec.rb118
-rw-r--r--spec/lib/gitlab/ci/config/entry/variables_spec.rb34
-rw-r--r--spec/lib/gitlab/ci/config/external/file/base_spec.rb22
-rw-r--r--spec/lib/gitlab/ci/config/external/mapper_spec.rb16
-rw-r--r--spec/lib/gitlab/ci/config_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/parsers/codequality/code_climate_spec.rb62
-rw-r--r--spec/lib/gitlab/ci/parsers/coverage/sax_document_spec.rb31
-rw-r--r--spec/lib/gitlab/ci/parsers/sbom/cyclonedx_properties_spec.rb8
-rw-r--r--spec/lib/gitlab/ci/parsers/sbom/cyclonedx_spec.rb41
-rw-r--r--spec/lib/gitlab/ci/parsers/security/common_spec.rb37
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/command_spec.rb17
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/limit/active_jobs_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/populate_metadata_spec.rb136
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb43
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/sequence_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/pipeline/seed/deployment_spec.rb119
-rw-r--r--spec/lib/gitlab/ci/pipeline/seed/environment_spec.rb224
-rw-r--r--spec/lib/gitlab/ci/pipeline/seed/pipeline_spec.rb12
-rw-r--r--spec/lib/gitlab/ci/reports/sbom/component_spec.rb70
-rw-r--r--spec/lib/gitlab/ci/reports/sbom/report_spec.rb15
-rw-r--r--spec/lib/gitlab/ci/reports/security/flag_spec.rb6
-rw-r--r--spec/lib/gitlab/ci/reports/security/reports_spec.rb26
-rw-r--r--spec/lib/gitlab/ci/reports/test_suite_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/5_minute_production_app_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/AWS/deploy_ecs_gitlab_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/Jobs/build_gitlab_ci_yaml_spec.rb14
-rw-r--r--spec/lib/gitlab/ci/templates/Jobs/code_quality_gitlab_ci_yaml_spec.rb11
-rw-r--r--spec/lib/gitlab/ci/templates/Jobs/deploy_gitlab_ci_yaml_spec.rb15
-rw-r--r--spec/lib/gitlab/ci/templates/Jobs/sast_iac_gitlab_ci_yaml_spec.rb10
-rw-r--r--spec/lib/gitlab/ci/templates/Jobs/sast_iac_latest_gitlab_ci_yaml_spec.rb10
-rw-r--r--spec/lib/gitlab/ci/templates/Jobs/test_gitlab_ci_yaml_spec.rb11
-rw-r--r--spec/lib/gitlab/ci/templates/MATLAB_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/Terraform/base_gitlab_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/Terraform/base_latest_gitlab_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/Verify/load_performance_testing_gitlab_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/flutter_gitlab_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/kaniko_gitlab_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/katalon_gitlab_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/npm_spec.rb5
-rw-r--r--spec/lib/gitlab/ci/templates/terraform_gitlab_ci_yaml_spec.rb23
-rw-r--r--spec/lib/gitlab/ci/templates/terraform_latest_gitlab_ci_yaml_spec.rb38
-rw-r--r--spec/lib/gitlab/ci/templates/themekit_gitlab_ci_yaml_spec.rb7
-rw-r--r--spec/lib/gitlab/ci/variables/collection/item_spec.rb6
-rw-r--r--spec/lib/gitlab/ci/variables/collection_spec.rb53
-rw-r--r--spec/lib/gitlab/ci/yaml_processor_spec.rb77
51 files changed, 982 insertions, 523 deletions
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 f9ebab149a5..647653f8e9e 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
@@ -4,11 +4,37 @@ require 'spec_helper'
RSpec.describe Gitlab::Ci::Build::Rules::Rule::Clause::Exists do
describe '#satisfied_by?' do
- shared_examples 'an exists rule with a context' do
+ subject(:satisfied_by?) { described_class.new(globs).satisfied_by?(nil, context) }
+
+ shared_examples 'a rules:exists with a context' do
it_behaves_like 'a glob matching rule' do
let(:project) { create(:project, :custom_repo, files: files) }
end
+ context 'when the rules:exists has a variable' do
+ let_it_be(:project) { create(:project, :custom_repo, files: { 'helm/helm_file.txt' => '' }) }
+
+ let(:globs) { ['$HELM_DIR/**/*'] }
+
+ let(:variables_hash) do
+ { 'HELM_DIR' => 'helm' }
+ end
+
+ before do
+ allow(context).to receive(:variables_hash).and_return(variables_hash)
+ end
+
+ context 'when the context has the specified variables' do
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when variable expansion does not match' do
+ let(:variables_hash) { {} }
+
+ it { is_expected.to be_falsey }
+ end
+ end
+
context 'after pattern comparision limit is reached' do
let(:globs) { ['*definitely_not_a_matching_glob*'] }
let(:project) { create(:project, :repository) }
@@ -22,26 +48,24 @@ RSpec.describe Gitlab::Ci::Build::Rules::Rule::Clause::Exists do
end
end
- 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
+ context 'when the rules are being evaluated at job level' do
+ it_behaves_like 'a rules:exists with a context' do
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
+ context 'when the rules are being evaluated for an entire pipeline' do
+ it_behaves_like 'a rules:exists 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
+ context 'when rules are being evaluated with `include`' do
let(:context) { Gitlab::Ci::Config::External::Context.new(project: project, sha: sha) }
- it_behaves_like 'an exists rule with a context' do
+ it_behaves_like 'a rules:exists with a context' do
let(:sha) { project.repository.commit.sha }
end
diff --git a/spec/lib/gitlab/ci/config/entry/bridge_spec.rb b/spec/lib/gitlab/ci/config/entry/bridge_spec.rb
index c56f2d25074..8da46561b73 100644
--- a/spec/lib/gitlab/ci/config/entry/bridge_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/bridge_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Ci::Config::Entry::Bridge do
- subject { described_class.new(config, name: :my_bridge) }
+ subject(:entry) { described_class.new(config, name: :my_bridge) }
it_behaves_like 'with inheritable CI config' do
let(:inheritable_key) { 'default' }
@@ -380,4 +380,38 @@ RSpec.describe Gitlab::Ci::Config::Entry::Bridge do
end
end
end
+
+ describe '#when' do
+ context 'when bridge is a manual action' do
+ let(:config) { { script: 'deploy', when: 'manual' } }
+
+ it { expect(entry.when).to eq('manual') }
+ end
+
+ context 'when bridge has no `when` attribute' do
+ let(:config) { { script: 'deploy' } }
+
+ it { expect(entry.when).to be_nil }
+ end
+
+ context 'when the `when` keyword is not a string' do
+ context 'when it is an array' do
+ let(:config) { { script: 'exit 0', when: ['always'] } }
+
+ it 'returns error' do
+ expect(entry).not_to be_valid
+ expect(entry.errors).to include 'bridge when should be a string'
+ end
+ end
+
+ context 'when it is a boolean' do
+ let(:config) { { script: 'exit 0', when: true } }
+
+ it 'returns error' do
+ expect(entry).not_to be_valid
+ expect(entry.errors).to include 'bridge when should be a string'
+ 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 75ac2ca87ab..acf60a6cdda 100644
--- a/spec/lib/gitlab/ci/config/entry/job_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/job_spec.rb
@@ -317,6 +317,26 @@ RSpec.describe Gitlab::Ci::Config::Entry::Job do
end
end
+ context 'when the `when` keyword is not a string' do
+ context 'when it is an array' do
+ let(:config) { { script: 'exit 0', when: ['always'] } }
+
+ it 'returns error' do
+ expect(entry).not_to be_valid
+ expect(entry.errors).to include 'job when should be a string'
+ end
+ end
+
+ context 'when it is a boolean' do
+ let(:config) { { script: 'exit 0', when: true } }
+
+ it 'returns error' do
+ expect(entry).not_to be_valid
+ expect(entry.errors).to include 'job when should be a string'
+ end
+ end
+ end
+
context 'when only: is used with rules:' do
let(:config) { { only: ['merge_requests'], rules: [{ if: '$THIS' }] } }
@@ -653,7 +673,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Job do
with_them do
let(:config) { { script: 'ls', rules: rules, only: only }.compact }
- it "#{name}" do
+ it name.to_s do
expect(workflow).to receive(:has_rules?) { has_workflow_rules? }
entry.compose!(deps)
diff --git a/spec/lib/gitlab/ci/config/entry/processable_spec.rb b/spec/lib/gitlab/ci/config/entry/processable_spec.rb
index ad90dd59585..f1578a068b9 100644
--- a/spec/lib/gitlab/ci/config/entry/processable_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/processable_spec.rb
@@ -208,7 +208,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Processable do
it 'reports error about variable' do
expect(entry.errors)
- .to include 'variables:var2 config must be a string'
+ .to include 'variables:var2 config uses invalid data keys: description'
end
end
end
@@ -248,7 +248,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Processable do
with_them do
let(:config) { { script: 'ls', rules: rules, only: only }.compact }
- it "#{name}" do
+ it name.to_s do
expect(workflow).to receive(:has_rules?) { has_workflow_rules? }
entry.compose!(deps)
@@ -447,6 +447,29 @@ RSpec.describe Gitlab::Ci::Config::Entry::Processable do
)
end
end
+
+ context 'when variables have "expand" data' do
+ let(:config) do
+ {
+ script: 'echo',
+ variables: { 'VAR1' => 'val 1',
+ 'VAR2' => { value: 'val 2', expand: false },
+ 'VAR3' => { value: 'val 3', expand: true } }
+ }
+ end
+
+ it 'returns correct value' do
+ expect(entry.value).to eq(
+ name: :rspec,
+ stage: 'test',
+ only: { refs: %w[branches tags] },
+ job_variables: { 'VAR1' => { value: 'val 1' },
+ 'VAR2' => { value: 'val 2', raw: true },
+ 'VAR3' => { value: 'val 3', raw: false } },
+ root_variables_inheritance: true
+ )
+ end
+ end
end
end
end
diff --git a/spec/lib/gitlab/ci/config/entry/root_spec.rb b/spec/lib/gitlab/ci/config/entry/root_spec.rb
index a55e13e7c2d..085293d7368 100644
--- a/spec/lib/gitlab/ci/config/entry/root_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/root_spec.rb
@@ -316,6 +316,35 @@ RSpec.describe Gitlab::Ci::Config::Entry::Root do
end
end
end
+
+ context 'when variables have "expand" data' do
+ let(:hash) do
+ {
+ variables: { 'VAR1' => 'val 1',
+ 'VAR2' => { value: 'val 2', expand: false },
+ 'VAR3' => { value: 'val 3', expand: true } },
+ rspec: { script: 'rspec' }
+ }
+ end
+
+ before do
+ root.compose!
+ end
+
+ it 'returns correct value' do
+ expect(root.variables_entry.value_with_data).to eq(
+ 'VAR1' => { value: 'val 1' },
+ 'VAR2' => { value: 'val 2', raw: true },
+ 'VAR3' => { value: 'val 3', raw: false }
+ )
+
+ expect(root.variables_value).to eq(
+ 'VAR1' => 'val 1',
+ 'VAR2' => 'val 2',
+ 'VAR3' => 'val 3'
+ )
+ end
+ end
end
context 'when configuration is not valid' do
diff --git a/spec/lib/gitlab/ci/config/entry/variable_spec.rb b/spec/lib/gitlab/ci/config/entry/variable_spec.rb
index 076a5b32e92..d7023072312 100644
--- a/spec/lib/gitlab/ci/config/entry/variable_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/variable_spec.rb
@@ -92,6 +92,12 @@ RSpec.describe Gitlab::Ci::Config::Entry::Variable do
describe '#value_with_data' do
subject(:value_with_data) { entry.value_with_data }
+ it { is_expected.to eq(value: 'value') }
+ end
+
+ describe '#value_with_prefill_data' do
+ subject(:value_with_prefill_data) { entry.value_with_prefill_data }
+
it { is_expected.to eq(value: 'value', description: 'description') }
end
@@ -107,6 +113,12 @@ RSpec.describe Gitlab::Ci::Config::Entry::Variable do
describe '#value_with_data' do
subject(:value_with_data) { entry.value_with_data }
+ it { is_expected.to eq(value: 'value') }
+ end
+
+ describe '#value_with_prefill_data' do
+ subject(:value_with_prefill_data) { entry.value_with_prefill_data }
+
it { is_expected.to eq(value: 'value', description: 'description') }
end
end
@@ -123,6 +135,12 @@ RSpec.describe Gitlab::Ci::Config::Entry::Variable do
describe '#value_with_data' do
subject(:value_with_data) { entry.value_with_data }
+ it { is_expected.to eq(value: '123') }
+ end
+
+ describe '#value_with_prefill_data' do
+ subject(:value_with_prefill_data) { entry.value_with_prefill_data }
+
it { is_expected.to eq(value: '123', description: 'description') }
end
end
@@ -139,6 +157,12 @@ RSpec.describe Gitlab::Ci::Config::Entry::Variable do
describe '#value_with_data' do
subject(:value_with_data) { entry.value_with_data }
+ it { is_expected.to eq(value: 'value') }
+ end
+
+ describe '#value_with_prefill_data' do
+ subject(:value_with_prefill_data) { entry.value_with_prefill_data }
+
it { is_expected.to eq(value: 'value', description: :description) }
end
end
@@ -192,6 +216,94 @@ RSpec.describe Gitlab::Ci::Config::Entry::Variable do
it { is_expected.to eq(value: 'value') }
end
+
+ describe '#value_with_prefill_data' do
+ subject(:value_with_prefill_data) { entry.value_with_prefill_data }
+
+ it { is_expected.to eq(value: 'value') }
+ end
+ end
+ end
+
+ context 'when config is a hash with expand' do
+ let(:config) { { value: 'value', expand: false } }
+
+ 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, expand)' do
+ let(:metadata) { { allowed_value_data: %i[value expand] } }
+
+ 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', raw: true) }
+
+ context 'when the FF ci_raw_variables_in_yaml_config is disabled' do
+ before do
+ stub_feature_flags(ci_raw_variables_in_yaml_config: false)
+ end
+
+ it { is_expected.to eq(value: 'value') }
+ end
+ end
+
+ context 'when config expand is true' do
+ let(:config) { { value: 'value', expand: true } }
+
+ describe '#value_with_data' do
+ subject(:value_with_data) { entry.value_with_data }
+
+ it { is_expected.to eq(value: 'value', raw: false) }
+ end
+ end
+
+ context 'when config expand is a string' do
+ let(:config) { { value: 'value', expand: "true" } }
+
+ 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 expand should be a boolean value' }
+ 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: expand' }
+ end
end
end
end
@@ -229,6 +341,12 @@ RSpec.describe Gitlab::Ci::Config::Entry::Variable do
describe '#value_with_data' do
subject(:value_with_data) { entry.value_with_data }
+ it { is_expected.to eq(value: 'value') }
+ end
+
+ describe '#value_with_prefill_data' do
+ subject(:value_with_prefill_data) { entry.value_with_prefill_data }
+
it { is_expected.to eq(value: 'value', description: 'description', value_options: %w[value value2]) }
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 085f304094e..609e4422d5c 100644
--- a/spec/lib/gitlab/ci/config/entry/variables_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/variables_spec.rb
@@ -66,6 +66,15 @@ RSpec.describe Gitlab::Ci::Config::Entry::Variables do
)
end
end
+
+ describe '#value_with_prefill_data' do
+ it 'returns variable with prefill data' do
+ expect(entry.value_with_prefill_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
@@ -119,6 +128,14 @@ RSpec.describe Gitlab::Ci::Config::Entry::Variables do
describe '#value_with_data' do
it 'returns variable with data' do
expect(entry.value_with_data).to eq(
+ 'VARIABLE_1' => { value: 'value' }
+ )
+ end
+ end
+
+ describe '#value_with_prefill_data' do
+ it 'returns variable with prefill data' do
+ expect(entry.value_with_prefill_data).to eq(
'VARIABLE_1' => { value: 'value', description: 'variable 1' }
)
end
@@ -147,6 +164,14 @@ RSpec.describe Gitlab::Ci::Config::Entry::Variables do
describe '#value_with_data' do
it 'returns variable with data' do
expect(entry.value_with_data).to eq(
+ 'VARIABLE_1' => { value: 'value1' }
+ )
+ end
+ end
+
+ describe '#value_with_prefill_data' do
+ it 'returns variable with prefill data' do
+ expect(entry.value_with_prefill_data).to eq(
'VARIABLE_1' => { value: 'value1', value_options: %w[value1 value2], description: 'variable 1' }
)
end
@@ -174,6 +199,15 @@ RSpec.describe Gitlab::Ci::Config::Entry::Variables do
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
+
+ describe '#value_with_prefill_data' do
+ it 'returns variable with prefill data' do
+ expect(entry.value_with_prefill_data).to eq(
'VARIABLE_1' => { value: 'value 1', description: 'variable 1' },
'VARIABLE_2' => { value: 'value 2' }
)
diff --git a/spec/lib/gitlab/ci/config/external/file/base_spec.rb b/spec/lib/gitlab/ci/config/external/file/base_spec.rb
index 1306d61d99c..8475c3a8b19 100644
--- a/spec/lib/gitlab/ci/config/external/file/base_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/file/base_spec.rb
@@ -14,6 +14,10 @@ RSpec.describe Gitlab::Ci::Config::External::File::Base do
super
end
+
+ def validate_context!
+ # no-op
+ end
end
end
@@ -95,6 +99,24 @@ RSpec.describe Gitlab::Ci::Config::External::File::Base do
expect(file.error_message).to eq('Included file `some/file/xxxxxxxxxxxxxxxx.yml` does not have valid YAML syntax!')
end
end
+
+ context 'when the class has no validate_context!' do
+ let(:test_class) do
+ Class.new(described_class) do
+ def initialize(params, context)
+ @location = params
+
+ super
+ end
+ end
+ end
+
+ let(:location) { 'some/file/config.yaml' }
+
+ it 'raises an error' do
+ expect { valid? }.to raise_error(NotImplementedError)
+ end
+ end
end
describe '#to_hash' do
diff --git a/spec/lib/gitlab/ci/config/external/mapper_spec.rb b/spec/lib/gitlab/ci/config/external/mapper_spec.rb
index e12f5dcee0a..d905568f01e 100644
--- a/spec/lib/gitlab/ci/config/external/mapper_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/mapper_spec.rb
@@ -113,7 +113,19 @@ RSpec.describe Gitlab::Ci::Config::External::Mapper do
it_behaves_like 'logging config file fetch', 'config_file_fetch_template_content_duration_s', 1
end
- context 'when the key is a hash of file and remote' do
+ context 'when the key is not valid' do
+ let(:local_file) { 'secret-file.yml' }
+ let(:values) do
+ { include: { invalid: local_file },
+ image: 'image:1.0' }
+ end
+
+ it 'returns ambigious specification error' do
+ expect { subject }.to raise_error(described_class::AmbigiousSpecificationError, '`{"invalid":"secret-file.yml"}` does not have a valid subkey for include. Valid subkeys are: `local`, `project`, `remote`, `template`, `artifact`')
+ end
+ end
+
+ context 'when the key is a hash of local and remote' do
let(:variables) { Gitlab::Ci::Variables::Collection.new([{ 'key' => 'GITLAB_TOKEN', 'value' => 'secret-file', 'masked' => true }]) }
let(:local_file) { 'secret-file.yml' }
let(:remote_url) { 'https://gitlab.com/secret-file.yml' }
@@ -123,7 +135,7 @@ RSpec.describe Gitlab::Ci::Config::External::Mapper do
end
it 'returns ambigious specification error' do
- expect { subject }.to raise_error(described_class::AmbigiousSpecificationError, 'Include `{"local":"xxxxxxxxxxx.yml","remote":"https://gitlab.com/xxxxxxxxxxx.yml"}` needs to match exactly one accessor!')
+ expect { subject }.to raise_error(described_class::AmbigiousSpecificationError, 'Each include must use only one of: `local`, `project`, `remote`, `template`, `artifact`')
end
end
diff --git a/spec/lib/gitlab/ci/config_spec.rb b/spec/lib/gitlab/ci/config_spec.rb
index 475503de7da..c4a6641ff6b 100644
--- a/spec/lib/gitlab/ci/config_spec.rb
+++ b/spec/lib/gitlab/ci/config_spec.rb
@@ -484,7 +484,7 @@ RSpec.describe Gitlab::Ci::Config do
it 'raises ConfigError' do
expect { config }.to raise_error(
described_class::ConfigError,
- 'Include `{"remote":"http://url","local":"/local/file.yml"}` needs to match exactly one accessor!'
+ /Each include must use only one of/
)
end
end
@@ -714,7 +714,7 @@ RSpec.describe Gitlab::Ci::Config do
it 'raises an error' do
expect { config }.to raise_error(
described_class::ConfigError,
- /needs to match exactly one accessor!/
+ /does not have a valid subkey for include/
)
end
end
diff --git a/spec/lib/gitlab/ci/parsers/codequality/code_climate_spec.rb b/spec/lib/gitlab/ci/parsers/codequality/code_climate_spec.rb
index 6a08e8f0b7f..1ef341ff863 100644
--- a/spec/lib/gitlab/ci/parsers/codequality/code_climate_spec.rb
+++ b/spec/lib/gitlab/ci/parsers/codequality/code_climate_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Ci::Parsers::Codequality::CodeClimate do
describe '#parse!' do
- subject(:parse) { described_class.new.parse!(code_climate, codequality_report) }
+ subject(:parse) { described_class.new.parse!(code_climate, codequality_report, metadata) }
let(:codequality_report) { Gitlab::Ci::Reports::CodequalityReports.new }
let(:code_climate) do
@@ -35,6 +35,15 @@ RSpec.describe Gitlab::Ci::Parsers::Codequality::CodeClimate do
].to_json
end
+ let_it_be(:group) { create(:group, name: 'test-group') }
+ let_it_be(:project) { create(:project, path: 'test-project', group: group) }
+ let(:metadata) do
+ {
+ project: project,
+ commit_sha: 'f0cc5229e2aa5e9429f1b17a3b3b102f21d7fe31'
+ }
+ end
+
context "when data is code_climate style JSON" do
context "when there are no degradations" do
let(:code_climate) { [].to_json }
@@ -133,5 +142,56 @@ RSpec.describe Gitlab::Ci::Parsers::Codequality::CodeClimate do
expect(codequality_report.degradations_count).to eq(0)
end
end
+
+ context 'for web_url' do
+ let(:code_climate) do
+ [
+ {
+ "categories": [
+ "Complexity"
+ ],
+ "check_name": "argument_count",
+ "content": {
+ "body": ""
+ },
+ "description": "Method `new_array` has 12 arguments (exceeds 4 allowed). Consider refactoring.",
+ "fingerprint": "15cdb5c53afd42bc22f8ca366a08d547",
+ "location": {
+ "path": "foo.rb",
+ "lines": {
+ "begin": 10,
+ "end": 10
+ }
+ },
+ "other_locations": [],
+ "remediation_points": 900000,
+ "severity": "major",
+ "type": "issue",
+ "engine_name": "structure"
+ }
+ ].to_json
+ end
+
+ context 'when metadata has project and commit_sha' do
+ it 'adds a non nil url' do
+ want = 'http://localhost/test-group/test-project/-/blob/f0cc5229e2aa5e9429f1b17a3b3b102f21d7fe31/foo.rb#L10'
+ expect { parse }.not_to raise_error
+
+ expect(codequality_report.degradations_count).to eq(1)
+ expect(codequality_report.all_degradations[0]['web_url']).to eq(want)
+ end
+ end
+
+ context 'when metadata does not have project and commit_sha' do
+ let(:metadata) { {} }
+
+ it 'adds a nil url' do
+ expect { parse }.not_to raise_error
+
+ expect(codequality_report.degradations_count).to eq(1)
+ expect(codequality_report.all_degradations[0]['web_url']).to be_nil
+ end
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/ci/parsers/coverage/sax_document_spec.rb b/spec/lib/gitlab/ci/parsers/coverage/sax_document_spec.rb
index a9851d78f48..e4ae6b25362 100644
--- a/spec/lib/gitlab/ci/parsers/coverage/sax_document_spec.rb
+++ b/spec/lib/gitlab/ci/parsers/coverage/sax_document_spec.rb
@@ -8,6 +8,7 @@ RSpec.describe Gitlab::Ci::Parsers::Coverage::SaxDocument do
describe '#parse!' do
let(:coverage_report) { Gitlab::Ci::Reports::CoverageReport.new }
let(:project_path) { 'foo/bar' }
+ let(:windows_path) { 'foo\bar' }
let(:paths) { ['app/user.rb'] }
let(:cobertura) do
@@ -269,6 +270,36 @@ RSpec.describe Gitlab::Ci::Parsers::Coverage::SaxDocument do
it_behaves_like 'ignoring sources, project_path, and worktree_paths'
end
+ context 'and has Windows-style paths' do
+ let(:sources_xml) do
+ <<~EOF_WIN
+ <sources>
+ <source>D:\\builds\\#{windows_path}\\app</source>
+ </sources>
+ EOF_WIN
+ end
+
+ context 'when there is a single <class>' do
+ context 'with a single line' do
+ let(:classes_xml) do
+ <<~EOF
+ <packages><package name="app"><classes>
+ <class filename="user.rb"><lines>
+ <line number="1" hits="2"/>
+ </lines></class>
+ </classes></package></packages>
+ EOF
+ end
+
+ it 'parses XML and returns a single file with the filename relative to project root' do
+ expect { parse_report }.not_to raise_error
+
+ expect(coverage_report.files).to eq({ 'app/user.rb' => { 1 => 2 } })
+ end
+ end
+ end
+ end
+
context 'and has multiple sources with a pattern for Go projects' do
let(:project_path) { 'local/go' } # Make sure we're not making false positives
let(:sources_xml) do
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 38b229e0dd8..f09b85aa2c7 100644
--- a/spec/lib/gitlab/ci/parsers/sbom/cyclonedx_properties_spec.rb
+++ b/spec/lib/gitlab/ci/parsers/sbom/cyclonedx_properties_spec.rb
@@ -3,7 +3,7 @@
require 'fast_spec_helper'
RSpec.describe Gitlab::Ci::Parsers::Sbom::CyclonedxProperties do
- subject(:parse_source) { described_class.parse_source(properties) }
+ subject(:parse_source_from_properties) { described_class.parse_source(properties) }
context 'when properties are nil' do
let(:properties) { nil }
@@ -50,9 +50,9 @@ RSpec.describe Gitlab::Ci::Parsers::Sbom::CyclonedxProperties do
end
it 'does not call dependency_scanning parser' do
- expect(Gitlab::Ci::Parsers::Sbom::Source::DependencyScanning).not_to receive(:parse_source)
+ expect(Gitlab::Ci::Parsers::Sbom::Source::DependencyScanning).not_to receive(:source)
- parse_source
+ parse_source_from_properties
end
end
@@ -82,7 +82,7 @@ RSpec.describe Gitlab::Ci::Parsers::Sbom::CyclonedxProperties do
it 'passes only supported properties to the dependency scanning parser' do
expect(Gitlab::Ci::Parsers::Sbom::Source::DependencyScanning).to receive(:source).with(expected_input)
- parse_source
+ parse_source_from_properties
end
end
end
diff --git a/spec/lib/gitlab/ci/parsers/sbom/cyclonedx_spec.rb b/spec/lib/gitlab/ci/parsers/sbom/cyclonedx_spec.rb
index f3636106b98..0b094880f69 100644
--- a/spec/lib/gitlab/ci/parsers/sbom/cyclonedx_spec.rb
+++ b/spec/lib/gitlab/ci/parsers/sbom/cyclonedx_spec.rb
@@ -100,16 +100,53 @@ RSpec.describe Gitlab::Ci::Parsers::Sbom::Cyclonedx do
]
end
+ before do
+ allow(report).to receive(:add_component)
+ end
+
it 'adds each component, ignoring unused attributes' do
expect(report).to receive(:add_component)
- .with(an_object_having_attributes(name: "activesupport", version: "5.1.4", component_type: "library"))
+ .with(
+ an_object_having_attributes(
+ name: "activesupport",
+ version: "5.1.4",
+ component_type: "library",
+ purl: an_object_having_attributes(type: "gem")
+ )
+ )
expect(report).to receive(:add_component)
- .with(an_object_having_attributes(name: "byebug", version: "10.0.0", component_type: "library"))
+ .with(
+ an_object_having_attributes(
+ name: "byebug",
+ version: "10.0.0",
+ component_type: "library",
+ purl: an_object_having_attributes(type: "gem")
+ )
+ )
expect(report).to receive(:add_component)
.with(an_object_having_attributes(name: "minimal-component", version: nil, component_type: "library"))
parse!
end
+
+ context 'when a component has an invalid purl' do
+ before do
+ components.push(
+ {
+ "name" => "invalid-component",
+ "version" => "v0.0.1",
+ "purl" => "pkg:nil",
+ "type" => "library"
+ }
+ )
+ end
+
+ it 'adds an error to the report' do
+ expect(report).to receive(:add_error).with("/components/#{components.size - 1}/purl is invalid")
+
+ parse!
+ end
+ end
end
context 'when report has metadata properties' do
diff --git a/spec/lib/gitlab/ci/parsers/security/common_spec.rb b/spec/lib/gitlab/ci/parsers/security/common_spec.rb
index 7dbad354e4c..03cab021c17 100644
--- a/spec/lib/gitlab/ci/parsers/security/common_spec.rb
+++ b/spec/lib/gitlab/ci/parsers/security/common_spec.rb
@@ -400,26 +400,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do
end
describe 'parsing tracking' do
- let(:tracking_data) do
- {
- 'type' => 'source',
- 'items' => [
- 'signatures' => [
- { 'algorithm' => 'hash', 'value' => 'hash_value' },
- { 'algorithm' => 'location', 'value' => 'location_value' },
- { 'algorithm' => 'scope_offset', 'value' => 'scope_offset_value' }
- ]
- ]
- }
- end
-
- context 'with valid tracking information' do
- it 'creates signatures for each algorithm' do
- finding = report.findings.first
- expect(finding.signatures.size).to eq(3)
- expect(finding.signatures.map(&:algorithm_type).to_set).to eq(Set['hash', 'location', 'scope_offset'])
- end
- end
+ let(:finding) { report.findings.first }
context 'with invalid tracking information' do
let(:tracking_data) do
@@ -436,15 +417,26 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do
end
it 'ignores invalid algorithm types' do
- finding = report.findings.first
expect(finding.signatures.size).to eq(2)
expect(finding.signatures.map(&:algorithm_type).to_set).to eq(Set['hash', 'location'])
end
end
context 'with valid tracking information' do
+ let(:tracking_data) do
+ {
+ 'type' => 'source',
+ 'items' => [
+ 'signatures' => [
+ { 'algorithm' => 'hash', 'value' => 'hash_value' },
+ { 'algorithm' => 'location', 'value' => 'location_value' },
+ { 'algorithm' => 'scope_offset', 'value' => 'scope_offset_value' }
+ ]
+ ]
+ }
+ end
+
it 'creates signatures for each signature algorithm' do
- finding = report.findings.first
expect(finding.signatures.size).to eq(3)
expect(finding.signatures.map(&:algorithm_type)).to eq(%w[hash location scope_offset])
@@ -456,7 +448,6 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do
end
it 'sets the uuid according to the higest priority signature' do
- finding = report.findings.first
highest_signature = finding.signatures.max_by(&:priority)
identifiers = if signatures_enabled
diff --git a/spec/lib/gitlab/ci/pipeline/chain/command_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/command_spec.rb
index 6e8b6e40928..9126c6dab21 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/command_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/command_spec.rb
@@ -409,4 +409,21 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Command do
end
end
end
+
+ describe '#observe_pipeline_size' do
+ let(:command) { described_class.new(project: project) }
+
+ let(:pipeline) { instance_double(Ci::Pipeline, total_size: 5, project: project, source: "schedule") }
+
+ it 'logs the pipeline total size to histogram' do
+ histogram = instance_double(Prometheus::Client::Histogram)
+
+ expect(::Gitlab::Ci::Pipeline::Metrics).to receive(:pipeline_size_histogram)
+ .and_return(histogram)
+ expect(histogram).to receive(:observe)
+ .with({ source: pipeline.source, plan: project.actual_plan_name }, pipeline.total_size)
+
+ command.observe_pipeline_size(pipeline)
+ end
+ end
end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/limit/active_jobs_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/limit/active_jobs_spec.rb
index bc453f1502b..c5a5e905d17 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/limit/active_jobs_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/limit/active_jobs_spec.rb
@@ -69,7 +69,9 @@ RSpec.describe ::Gitlab::Ci::Pipeline::Chain::Limit::ActiveJobs do
class: described_class.name,
message: described_class::MESSAGE,
project_id: project.id,
- plan: default_plan.name
+ plan: default_plan.name,
+ project_path: project.path,
+ jobs_in_alive_pipelines_count: step.send(:count_jobs_in_alive_pipelines)
)
end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/populate_metadata_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/populate_metadata_spec.rb
new file mode 100644
index 00000000000..ce1ee2fcda0
--- /dev/null
+++ b/spec/lib/gitlab/ci/pipeline/chain/populate_metadata_spec.rb
@@ -0,0 +1,136 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Pipeline::Chain::PopulateMetadata do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { create(:user) }
+
+ let(:pipeline) do
+ build(:ci_pipeline, project: project, ref: 'master', user: user)
+ end
+
+ let(:command) do
+ Gitlab::Ci::Pipeline::Chain::Command.new(
+ project: project,
+ current_user: user,
+ origin_ref: 'master')
+ end
+
+ let(:dependencies) do
+ [
+ Gitlab::Ci::Pipeline::Chain::Config::Content.new(pipeline, command),
+ Gitlab::Ci::Pipeline::Chain::Config::Process.new(pipeline, command),
+ Gitlab::Ci::Pipeline::Chain::EvaluateWorkflowRules.new(pipeline, command),
+ Gitlab::Ci::Pipeline::Chain::SeedBlock.new(pipeline, command),
+ Gitlab::Ci::Pipeline::Chain::Seed.new(pipeline, command),
+ Gitlab::Ci::Pipeline::Chain::Populate.new(pipeline, command)
+ ]
+ end
+
+ let(:step) { described_class.new(pipeline, command) }
+
+ let(:config) do
+ { rspec: { script: 'rspec' } }
+ end
+
+ def run_chain
+ dependencies.map(&:perform!)
+ step.perform!
+ end
+
+ before do
+ stub_ci_pipeline_yaml_file(YAML.dump(config))
+ end
+
+ context 'with pipeline name' do
+ let(:config) do
+ { workflow: { name: ' Pipeline name ' }, rspec: { script: 'rspec' } }
+ end
+
+ it 'does not break the chain' do
+ run_chain
+
+ expect(step.break?).to be false
+ end
+
+ context 'with feature flag disabled' do
+ before do
+ stub_feature_flags(pipeline_name: false)
+ end
+
+ it 'does not build pipeline_metadata' do
+ run_chain
+
+ expect(pipeline.pipeline_metadata).to be_nil
+ end
+ end
+
+ context 'with feature flag enabled' do
+ before do
+ stub_feature_flags(pipeline_name: true)
+ end
+
+ it 'builds pipeline_metadata' do
+ run_chain
+
+ expect(pipeline.pipeline_metadata.name).to eq('Pipeline name')
+ expect(pipeline.pipeline_metadata.project).to eq(pipeline.project)
+ expect(pipeline.pipeline_metadata).not_to be_persisted
+ end
+
+ context 'with empty name' do
+ let(:config) do
+ { workflow: { name: ' ' }, rspec: { script: 'rspec' } }
+ end
+
+ it 'strips whitespace from name' do
+ run_chain
+
+ expect(pipeline.pipeline_metadata).to be_nil
+ end
+ end
+
+ context 'with variables' do
+ let(:config) do
+ {
+ variables: { ROOT_VAR: 'value $WORKFLOW_VAR1' },
+ workflow: {
+ name: 'Pipeline $ROOT_VAR $WORKFLOW_VAR2 $UNKNOWN_VAR',
+ rules: [{ variables: { WORKFLOW_VAR1: 'value1', WORKFLOW_VAR2: 'value2' } }]
+ },
+ rspec: { script: 'rspec' }
+ }
+ end
+
+ it 'substitutes variables' do
+ run_chain
+
+ expect(pipeline.pipeline_metadata.name).to eq('Pipeline value value1 value2 ')
+ end
+ end
+
+ context 'with invalid name' do
+ let(:config) do
+ {
+ variables: { ROOT_VAR: 'a' * 256 },
+ workflow: {
+ name: 'Pipeline $ROOT_VAR'
+ },
+ rspec: { script: 'rspec' }
+ }
+ end
+
+ it 'returns error and breaks chain' do
+ ret = run_chain
+
+ expect(ret)
+ .to match_array(["Failed to build pipeline metadata! Name is too long (maximum is 255 characters)"])
+ expect(pipeline.pipeline_metadata.errors.full_messages)
+ .to match_array(['Name is too long (maximum is 255 characters)'])
+ expect(step.break?).to be true
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb
index 51d1661b586..62de4d2e96d 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb
@@ -236,47 +236,4 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Populate do
end
end
end
-
- context 'with pipeline name' do
- let(:config) do
- { workflow: { name: ' Pipeline name ' }, rspec: { script: 'rspec' } }
- end
-
- context 'with feature flag disabled' do
- before do
- stub_feature_flags(pipeline_name: false)
- end
-
- it 'does not build pipeline_metadata' do
- run_chain
-
- expect(pipeline.pipeline_metadata).to be_nil
- end
- end
-
- context 'with feature flag enabled' do
- before do
- stub_feature_flags(pipeline_name: true)
- end
-
- it 'builds pipeline_metadata' do
- run_chain
-
- expect(pipeline.pipeline_metadata.title).to eq('Pipeline name')
- expect(pipeline.pipeline_metadata.project).to eq(pipeline.project)
- end
-
- context 'with empty name' do
- let(:config) do
- { workflow: { name: ' ' }, rspec: { script: 'rspec' } }
- end
-
- it 'strips whitespace from name' do
- run_chain
-
- expect(pipeline.pipeline_metadata).to be_nil
- end
- end
- end
- end
end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/sequence_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/sequence_spec.rb
index c69aa661b05..31086f6ae4a 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/sequence_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/sequence_spec.rb
@@ -80,7 +80,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Sequence do
subject.build!
expect(histogram).to have_received(:observe)
- .with({ source: 'push' }, 0)
+ .with({ source: 'push', plan: project.actual_plan_name }, 0)
end
describe 'active jobs by pipeline plan histogram' do
diff --git a/spec/lib/gitlab/ci/pipeline/seed/deployment_spec.rb b/spec/lib/gitlab/ci/pipeline/seed/deployment_spec.rb
deleted file mode 100644
index 6569ce937ac..00000000000
--- a/spec/lib/gitlab/ci/pipeline/seed/deployment_spec.rb
+++ /dev/null
@@ -1,119 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-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')
- end
-
- let(:job) { build(:ci_build, project: project, pipeline: pipeline) }
- let(:environment) { Gitlab::Ci::Pipeline::Seed::Environment.new(job).to_resource }
- let(:seed) { described_class.new(job, environment) }
- let(:attributes) { {} }
-
- before do
- job.assign_attributes(**attributes)
- end
-
- describe '#to_resource' do
- subject { seed.to_resource }
-
- context 'when job has environment attribute' do
- let(:attributes) do
- {
- environment: 'production',
- options: { environment: { name: 'production', **kubernetes_options } }
- }
- end
-
- let(:kubernetes_options) { {} }
-
- it 'returns a deployment object with environment' do
- expect(subject).to be_a(Deployment)
- expect(subject.iid).to be_present
- expect(subject.environment.name).to eq('production')
- expect(subject.cluster).to be_nil
- expect(subject.deployment_cluster).to be_nil
- end
-
- context 'when environment has deployment platform' do
- let!(:cluster) { create(:cluster, :provided_by_gcp, projects: [project], managed: managed_cluster) }
- let(:managed_cluster) { true }
-
- it 'sets the cluster and deployment_cluster' do
- expect(subject.cluster).to eq(cluster) # until we stop double writing in 12.9: https://gitlab.com/gitlab-org/gitlab/issues/202628
- expect(subject.deployment_cluster.cluster).to eq(cluster)
- end
-
- context 'when a custom namespace is given' do
- let(:kubernetes_options) { { kubernetes: { namespace: 'the-custom-namespace' } } }
-
- context 'when cluster is managed' do
- it 'does not set the custom namespace' do
- expect(subject.deployment_cluster.kubernetes_namespace).not_to eq('the-custom-namespace')
- end
- end
-
- context 'when cluster is not managed' do
- let(:managed_cluster) { false }
-
- it 'sets the custom namespace' do
- expect(subject.deployment_cluster.kubernetes_namespace).to eq('the-custom-namespace')
- end
- end
- end
- end
-
- context 'when environment has an invalid URL' do
- let(:attributes) do
- {
- environment: '!!!',
- options: { environment: { name: '!!!' } }
- }
- end
-
- it 'returns nothing' do
- is_expected.to be_nil
- end
- end
-
- context 'when job has already deployment' do
- let(:job) { build(:ci_build, :with_deployment, project: project, environment: 'production') }
-
- it 'returns the persisted deployment' do
- is_expected.to eq(job.deployment)
- end
- end
- end
-
- context 'when job does not start environment' do
- where(:action) do
- %w(stop prepare verify access)
- end
-
- with_them do
- let(:attributes) do
- {
- environment: 'production',
- options: { environment: { name: 'production', action: action } }
- }
- end
-
- it 'returns nothing' do
- is_expected.to be_nil
- end
- end
- end
-
- context 'when job does not have environment attribute' do
- let(:attributes) { { name: 'test' } }
-
- it 'returns nothing' do
- is_expected.to be_nil
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/ci/pipeline/seed/environment_spec.rb b/spec/lib/gitlab/ci/pipeline/seed/environment_spec.rb
deleted file mode 100644
index 2b9d8127886..00000000000
--- a/spec/lib/gitlab/ci/pipeline/seed/environment_spec.rb
+++ /dev/null
@@ -1,224 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Ci::Pipeline::Seed::Environment do
- let_it_be(:project) { create(: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) { {} }
-
- before do
- job.assign_attributes(**attributes)
- end
-
- describe '#to_resource' do
- subject { seed.to_resource }
-
- shared_examples_for 'returning a correct environment' do
- let(:expected_auto_stop_in_seconds) do
- if expected_auto_stop_in
- ChronicDuration.parse(expected_auto_stop_in).seconds
- end
- end
-
- it 'returns a persisted environment object' do
- freeze_time do
- expect { subject }.to change { Environment.count }.by(1)
-
- expect(subject).to be_a(Environment)
- expect(subject).to be_persisted
- expect(subject.project).to eq(project)
- expect(subject.name).to eq(expected_environment_name)
- expect(subject.auto_stop_in).to eq(expected_auto_stop_in_seconds)
- end
- end
-
- context 'when environment has already existed' do
- let!(:environment) do
- create(:environment,
- project: project,
- name: expected_environment_name
- ).tap do |env|
- env.auto_stop_in = expected_auto_stop_in
- end
- end
-
- it 'returns the existing environment object' do
- expect { subject }.not_to change { Environment.count }
- expect { subject }.not_to change { environment.auto_stop_at }
-
- expect(subject).to be_persisted
- expect(subject).to eq(environment)
- end
- end
- end
-
- context 'when job has environment name attribute' do
- let(:environment_name) { 'production' }
- let(:expected_environment_name) { 'production' }
- let(:expected_auto_stop_in) { nil }
-
- let(:attributes) do
- {
- environment: environment_name,
- options: { environment: { name: environment_name } }
- }
- end
-
- it_behaves_like 'returning a correct environment'
-
- context 'and job environment also has an auto_stop_in attribute' do
- let(:environment_auto_stop_in) { '5 minutes' }
- let(:expected_auto_stop_in) { '5 minutes' }
-
- let(:attributes) do
- {
- environment: environment_name,
- options: {
- environment: {
- name: environment_name,
- auto_stop_in: environment_auto_stop_in
- }
- }
- }
- end
-
- 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
- let(:attributes) do
- {
- environment: 'customer-portal',
- options: {
- environment: {
- name: 'customer-portal',
- deployment_tier: deployment_tier
- }
- }
- }
- end
-
- let(:deployment_tier) { 'production' }
-
- context 'when environment has not been created yet' do
- it 'sets the specified deployment tier' do
- is_expected.to be_production
- end
-
- context 'when deployment tier is staging' do
- let(:deployment_tier) { 'staging' }
-
- it 'sets the specified deployment tier' do
- is_expected.to be_staging
- end
- end
-
- context 'when deployment tier is unknown' do
- let(:deployment_tier) { 'unknown' }
-
- it 'raises an error' do
- expect { subject }.to raise_error(ArgumentError, "'unknown' is not a valid tier")
- end
- end
- end
-
- context 'when environment has already been created' do
- before do
- create(:environment, project: project, name: 'customer-portal', tier: :staging)
- end
-
- it 'does not overwrite the specified deployment tier' do
- # This is to be updated when a deployment succeeded i.e. Deployments::UpdateEnvironmentService.
- is_expected.to be_staging
- end
- end
- end
-
- context 'when job starts a review app' do
- let(:environment_name) { 'review/$CI_COMMIT_REF_NAME' }
- let(:expected_environment_name) { "review/#{job.ref}" }
- let(:expected_auto_stop_in) { nil }
-
- let(:attributes) do
- {
- environment: environment_name,
- options: { environment: { name: environment_name } }
- }
- end
-
- it_behaves_like 'returning a correct environment'
- end
-
- context 'when job stops a review app' do
- let(:environment_name) { 'review/$CI_COMMIT_REF_NAME' }
- let(:expected_environment_name) { "review/#{job.ref}" }
- let(:expected_auto_stop_in) { nil }
-
- let(:attributes) do
- {
- environment: environment_name,
- options: { environment: { name: environment_name, action: 'stop' } }
- }
- end
-
- 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/pipeline/seed/pipeline_spec.rb b/spec/lib/gitlab/ci/pipeline/seed/pipeline_spec.rb
index a76b4874eca..55980ae72a0 100644
--- a/spec/lib/gitlab/ci/pipeline/seed/pipeline_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/seed/pipeline_spec.rb
@@ -6,7 +6,9 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Pipeline do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:pipeline) { create(:ci_pipeline, project: project) }
- let(:seed_context) { Gitlab::Ci::Pipeline::Seed::Context.new(pipeline, root_variables: []) }
+ let(:root_variables) { [] }
+
+ let(:seed_context) { Gitlab::Ci::Pipeline::Seed::Context.new(pipeline, root_variables: root_variables) }
let(:stages_attributes) do
[
@@ -75,4 +77,12 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Pipeline do
expect(seed.deployments_count).to eq(2)
end
end
+
+ describe '#root_variables' do
+ let(:root_variables) { %w[var1 value1] }
+
+ it 'returns root_variables' do
+ expect(seed.root_variables).to eq(root_variables)
+ end
+ end
end
diff --git a/spec/lib/gitlab/ci/reports/sbom/component_spec.rb b/spec/lib/gitlab/ci/reports/sbom/component_spec.rb
index 06ea3433ef0..cdaf9354104 100644
--- a/spec/lib/gitlab/ci/reports/sbom/component_spec.rb
+++ b/spec/lib/gitlab/ci/reports/sbom/component_spec.rb
@@ -1,23 +1,67 @@
# frozen_string_literal: true
-require 'fast_spec_helper'
+require 'spec_helper'
RSpec.describe Gitlab::Ci::Reports::Sbom::Component do
- let(:attributes) do
- {
- type: 'library',
- name: 'component-name',
- version: 'v0.0.1'
- }
- end
+ let(:component_type) { 'library' }
+ let(:name) { 'component-name' }
+ let(:purl_type) { 'npm' }
+ let(:purl) { Sbom::PackageUrl.new(type: purl_type, name: name, version: version).to_s }
+ let(:version) { 'v0.0.1' }
- subject { described_class.new(**attributes) }
+ subject(:component) do
+ described_class.new(
+ type: component_type,
+ name: name,
+ purl: purl,
+ version: version
+ )
+ end
it 'has correct attributes' do
- expect(subject).to have_attributes(
- component_type: attributes[:type],
- name: attributes[:name],
- version: attributes[:version]
+ expect(component).to have_attributes(
+ component_type: component_type,
+ name: name,
+ purl: an_object_having_attributes(type: purl_type),
+ version: version
)
end
+
+ describe '#ingestible?' do
+ subject { component.ingestible? }
+
+ context 'when component_type is invalid' do
+ let(:component_type) { 'invalid' }
+
+ it { is_expected.to be(false) }
+ end
+
+ context 'when purl_type is invalid' do
+ let(:purl_type) { 'invalid' }
+
+ it { is_expected.to be(false) }
+ end
+
+ context 'when component_type is valid' do
+ where(:component_type) { ::Enums::Sbom.component_types.keys.map(&:to_s) }
+
+ with_them do
+ it { is_expected.to be(true) }
+ end
+ end
+
+ context 'when purl_type is valid' do
+ where(:purl_type) { ::Enums::Sbom.purl_types.keys.map(&:to_s) }
+
+ with_them do
+ it { is_expected.to be(true) }
+ end
+ end
+
+ context 'when there is no purl' do
+ let(:purl) { nil }
+
+ it { is_expected.to be(true) }
+ end
+ 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 6ffa93e5fc8..f9a83378f46 100644
--- a/spec/lib/gitlab/ci/reports/sbom/report_spec.rb
+++ b/spec/lib/gitlab/ci/reports/sbom/report_spec.rb
@@ -5,6 +5,21 @@ require 'spec_helper'
RSpec.describe Gitlab::Ci::Reports::Sbom::Report do
subject(:report) { described_class.new }
+ describe '#valid?' do
+ context 'when there are no errors' do
+ it { is_expected.to be_valid }
+ end
+
+ context 'when report contains errors' do
+ before do
+ report.add_error('error1')
+ report.add_error('error2')
+ end
+
+ it { is_expected.not_to be_valid }
+ end
+ end
+
describe '#add_error' do
it 'appends errors to a list' do
report.add_error('error1')
diff --git a/spec/lib/gitlab/ci/reports/security/flag_spec.rb b/spec/lib/gitlab/ci/reports/security/flag_spec.rb
index 6ee074f7aeb..0ef8f6c75a0 100644
--- a/spec/lib/gitlab/ci/reports/security/flag_spec.rb
+++ b/spec/lib/gitlab/ci/reports/security/flag_spec.rb
@@ -29,5 +29,11 @@ RSpec.describe Gitlab::Ci::Reports::Security::Flag do
)
end
end
+
+ describe '#false_positive?' do
+ subject { security_flag.false_positive? }
+
+ it { is_expected.to be_truthy }
+ end
end
end
diff --git a/spec/lib/gitlab/ci/reports/security/reports_spec.rb b/spec/lib/gitlab/ci/reports/security/reports_spec.rb
index e240edc4a12..33f3317c655 100644
--- a/spec/lib/gitlab/ci/reports/security/reports_spec.rb
+++ b/spec/lib/gitlab/ci/reports/security/reports_spec.rb
@@ -125,6 +125,32 @@ RSpec.describe Gitlab::Ci::Reports::Security::Reports do
it { is_expected.to be(false) }
end
+
+ context 'when target_reports is not nil and reports is empty' do
+ let(:without_reports) { described_class.new(pipeline) }
+
+ subject { without_reports.violates_default_policy_against?(target_reports, vulnerabilities_allowed, severity_levels, vulnerability_states) }
+
+ before do
+ target_reports.get_report('sast', artifact).add_finding(high_severity_dast)
+ end
+
+ context 'when require_approval_on_scan_removal feature is enabled' do
+ before do
+ stub_feature_flags(require_approval_on_scan_removal: true)
+ end
+
+ it { is_expected.to be(true) }
+ end
+
+ context 'when require_approval_on_scan_removal feature is disabled' do
+ before do
+ stub_feature_flags(require_approval_on_scan_removal: false)
+ end
+
+ it { is_expected.to be(false) }
+ end
+ end
end
end
end
diff --git a/spec/lib/gitlab/ci/reports/test_suite_spec.rb b/spec/lib/gitlab/ci/reports/test_suite_spec.rb
index 4a1f77bed65..05f6a8a8cb6 100644
--- a/spec/lib/gitlab/ci/reports/test_suite_spec.rb
+++ b/spec/lib/gitlab/ci/reports/test_suite_spec.rb
@@ -209,7 +209,7 @@ RSpec.describe Gitlab::Ci::Reports::TestSuite do
Gitlab::Ci::Reports::TestCase::STATUS_TYPES.each do |status_type|
describe "##{status_type}" do
- subject { test_suite.public_send("#{status_type}") }
+ subject { test_suite.public_send(status_type.to_s) }
context "when #{status_type} test case exists" do
before do
diff --git a/spec/lib/gitlab/ci/templates/5_minute_production_app_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/5_minute_production_app_ci_yaml_spec.rb
index 8204b104832..43deb465025 100644
--- a/spec/lib/gitlab/ci/templates/5_minute_production_app_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/5_minute_production_app_ci_yaml_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe '5-Minute-Production-App.gitlab-ci.yml' do
let(:default_branch) { 'master' }
let(:pipeline_branch) { default_branch }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
- let(:pipeline) { service.execute!(:push).payload }
+ let(:pipeline) { service.execute(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before do
diff --git a/spec/lib/gitlab/ci/templates/AWS/deploy_ecs_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/AWS/deploy_ecs_gitlab_ci_yaml_spec.rb
index 65fd2b016ac..f2bff5ff3e0 100644
--- a/spec/lib/gitlab/ci/templates/AWS/deploy_ecs_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/AWS/deploy_ecs_gitlab_ci_yaml_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe 'Deploy-ECS.gitlab-ci.yml' do
let(:project) { create(:project, :auto_devops, :custom_repo, files: { 'README.md' => '' }) }
let(:user) { project.first_owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
- let(:pipeline) { service.execute!(:push).payload }
+ let(:pipeline) { service.execute(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
let(:platform_target) { 'ECS' }
diff --git a/spec/lib/gitlab/ci/templates/Jobs/build_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/Jobs/build_gitlab_ci_yaml_spec.rb
index 21052f03cb8..07cfa939623 100644
--- a/spec/lib/gitlab/ci/templates/Jobs/build_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/Jobs/build_gitlab_ci_yaml_spec.rb
@@ -3,8 +3,20 @@
require 'spec_helper'
RSpec.describe 'Jobs/Build.gitlab-ci.yml' do
+ include Ci::TemplateHelpers
+
subject(:template) { Gitlab::Template::GitlabCiYmlTemplate.find('Jobs/Build') }
+ describe 'AUTO_BUILD_IMAGE_VERSION' do
+ it 'corresponds to a published image in the registry' do
+ registry = "https://#{template_registry_host}"
+ repository = "gitlab-org/cluster-integration/auto-build-image"
+ reference = YAML.safe_load(template.content).dig('variables', 'AUTO_BUILD_IMAGE_VERSION')
+
+ expect(public_image_exist?(registry, repository, reference)).to be true
+ end
+ end
+
describe 'the created pipeline' do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:user) { project.first_owner }
@@ -12,7 +24,7 @@ RSpec.describe 'Jobs/Build.gitlab-ci.yml' do
let(:default_branch) { 'master' }
let(:pipeline_ref) { default_branch }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_ref) }
- let(:pipeline) { service.execute!(:push).payload }
+ let(:pipeline) { service.execute(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before do
diff --git a/spec/lib/gitlab/ci/templates/Jobs/code_quality_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/Jobs/code_quality_gitlab_ci_yaml_spec.rb
index d88d9782021..16c5d7a4b6d 100644
--- a/spec/lib/gitlab/ci/templates/Jobs/code_quality_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/Jobs/code_quality_gitlab_ci_yaml_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe 'Jobs/Code-Quality.gitlab-ci.yml' do
let(:default_branch) { 'master' }
let(:pipeline_ref) { default_branch }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_ref) }
- let(:pipeline) { service.execute!(:push).payload }
+ let(:pipeline) { service.execute(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before do
@@ -62,7 +62,8 @@ RSpec.describe 'Jobs/Code-Quality.gitlab-ci.yml' do
context 'on master' do
it 'has no jobs' do
- expect { pipeline }.to raise_error(Ci::CreatePipelineService::CreateError)
+ expect(build_names).to be_empty
+ expect(pipeline.errors.full_messages).to match_array(["No stages / jobs for this pipeline."])
end
end
@@ -70,7 +71,8 @@ RSpec.describe 'Jobs/Code-Quality.gitlab-ci.yml' do
let(:pipeline_ref) { 'feature' }
it 'has no jobs' do
- expect { pipeline }.to raise_error(Ci::CreatePipelineService::CreateError)
+ expect(build_names).to be_empty
+ expect(pipeline.errors.full_messages).to match_array(["No stages / jobs for this pipeline."])
end
end
@@ -78,7 +80,8 @@ RSpec.describe 'Jobs/Code-Quality.gitlab-ci.yml' do
let(:pipeline_ref) { 'v1.0.0' }
it 'has no jobs' do
- expect { pipeline }.to raise_error(Ci::CreatePipelineService::CreateError)
+ expect(build_names).to be_empty
+ expect(pipeline.errors.full_messages).to match_array(["No stages / jobs for this pipeline."])
end
end
end
diff --git a/spec/lib/gitlab/ci/templates/Jobs/deploy_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/Jobs/deploy_gitlab_ci_yaml_spec.rb
index b657f73fa77..acb296082b8 100644
--- a/spec/lib/gitlab/ci/templates/Jobs/deploy_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/Jobs/deploy_gitlab_ci_yaml_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe 'Jobs/Deploy.gitlab-ci.yml' do
+ include Ci::TemplateHelpers
+
subject(:template) do
<<~YAML
stages:
@@ -26,6 +28,17 @@ RSpec.describe 'Jobs/Deploy.gitlab-ci.yml' do
YAML
end
+ describe 'AUTO_DEPLOY_IMAGE_VERSION' do
+ it 'corresponds to a published image in the registry' do
+ template = Gitlab::Template::GitlabCiYmlTemplate.find('Jobs/Deploy')
+ registry = "https://#{template_registry_host}"
+ repository = "gitlab-org/cluster-integration/auto-deploy-image"
+ reference = YAML.safe_load(template.content, aliases: true).dig('variables', 'AUTO_DEPLOY_IMAGE_VERSION')
+
+ expect(public_image_exist?(registry, repository, reference)).to be true
+ end
+ end
+
describe 'the created pipeline' do
let_it_be(:project, refind: true) { create(:project, :repository) }
@@ -33,7 +46,7 @@ RSpec.describe 'Jobs/Deploy.gitlab-ci.yml' do
let(:default_branch) { 'master' }
let(:pipeline_ref) { default_branch }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_ref) }
- let(:pipeline) { service.execute!(:push).payload }
+ let(:pipeline) { service.execute(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before do
diff --git a/spec/lib/gitlab/ci/templates/Jobs/sast_iac_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/Jobs/sast_iac_gitlab_ci_yaml_spec.rb
index 85516d0bbb0..8a5aea7c0f0 100644
--- a/spec/lib/gitlab/ci/templates/Jobs/sast_iac_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/Jobs/sast_iac_gitlab_ci_yaml_spec.rb
@@ -9,10 +9,10 @@ RSpec.describe 'Jobs/SAST-IaC.gitlab-ci.yml' do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:user) { project.first_owner }
- let(:default_branch) { 'main' }
+ let(:default_branch) { "master" }
let(:pipeline_ref) { default_branch }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_ref) }
- let(:pipeline) { service.execute!(:push).payload }
+ let(:pipeline) { service.execute(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before do
@@ -49,7 +49,8 @@ RSpec.describe 'Jobs/SAST-IaC.gitlab-ci.yml' do
context 'on default branch' do
it 'has no jobs' do
- expect { pipeline }.to raise_error(Ci::CreatePipelineService::CreateError)
+ expect(build_names).to be_empty
+ expect(pipeline.errors.full_messages).to match_array(["No stages / jobs for this pipeline."])
end
end
@@ -57,7 +58,8 @@ RSpec.describe 'Jobs/SAST-IaC.gitlab-ci.yml' do
let(:pipeline_ref) { 'feature' }
it 'has no jobs' do
- expect { pipeline }.to raise_error(Ci::CreatePipelineService::CreateError)
+ expect(build_names).to be_empty
+ expect(pipeline.errors.full_messages).to match_array(["No stages / jobs for this pipeline."])
end
end
end
diff --git a/spec/lib/gitlab/ci/templates/Jobs/sast_iac_latest_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/Jobs/sast_iac_latest_gitlab_ci_yaml_spec.rb
index 5ff179b6fee..d540b035f81 100644
--- a/spec/lib/gitlab/ci/templates/Jobs/sast_iac_latest_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/Jobs/sast_iac_latest_gitlab_ci_yaml_spec.rb
@@ -9,10 +9,10 @@ RSpec.describe 'Jobs/SAST-IaC.latest.gitlab-ci.yml' do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:user) { project.first_owner }
- let(:default_branch) { 'main' }
+ let(:default_branch) { "master" }
let(:pipeline_ref) { default_branch }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_ref) }
- let(:pipeline) { service.execute!(:push).payload }
+ let(:pipeline) { service.execute(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before do
@@ -50,7 +50,8 @@ RSpec.describe 'Jobs/SAST-IaC.latest.gitlab-ci.yml' do
context 'on default branch' do
it 'has no jobs' do
- expect { pipeline }.to raise_error(Ci::CreatePipelineService::CreateError)
+ expect(build_names).to be_empty
+ expect(pipeline.errors.full_messages).to match_array(["No stages / jobs for this pipeline."])
end
end
@@ -58,7 +59,8 @@ RSpec.describe 'Jobs/SAST-IaC.latest.gitlab-ci.yml' do
let(:pipeline_ref) { 'feature' }
it 'has no jobs' do
- expect { pipeline }.to raise_error(Ci::CreatePipelineService::CreateError)
+ expect(build_names).to be_empty
+ expect(pipeline.errors.full_messages).to match_array(["No stages / jobs for this pipeline."])
end
end
end
diff --git a/spec/lib/gitlab/ci/templates/Jobs/test_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/Jobs/test_gitlab_ci_yaml_spec.rb
index a92a8397e96..7cf0cf3ed33 100644
--- a/spec/lib/gitlab/ci/templates/Jobs/test_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/Jobs/test_gitlab_ci_yaml_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe 'Jobs/Test.gitlab-ci.yml' do
let(:default_branch) { 'master' }
let(:pipeline_ref) { default_branch }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_ref) }
- let(:pipeline) { service.execute!(:push).payload }
+ let(:pipeline) { service.execute(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before do
@@ -62,7 +62,8 @@ RSpec.describe 'Jobs/Test.gitlab-ci.yml' do
context 'on master' do
it 'has no jobs' do
- expect { pipeline }.to raise_error(Ci::CreatePipelineService::CreateError)
+ expect(build_names).to be_empty
+ expect(pipeline.errors.full_messages).to match_array(["No stages / jobs for this pipeline."])
end
end
@@ -70,7 +71,8 @@ RSpec.describe 'Jobs/Test.gitlab-ci.yml' do
let(:pipeline_ref) { 'feature' }
it 'has no jobs' do
- expect { pipeline }.to raise_error(Ci::CreatePipelineService::CreateError)
+ expect(build_names).to be_empty
+ expect(pipeline.errors.full_messages).to match_array(["No stages / jobs for this pipeline."])
end
end
@@ -78,7 +80,8 @@ RSpec.describe 'Jobs/Test.gitlab-ci.yml' do
let(:pipeline_ref) { 'v1.0.0' }
it 'has no jobs' do
- expect { pipeline }.to raise_error(Ci::CreatePipelineService::CreateError)
+ expect(build_names).to be_empty
+ expect(pipeline.errors.full_messages).to match_array(["No stages / jobs for this pipeline."])
end
end
end
diff --git a/spec/lib/gitlab/ci/templates/MATLAB_spec.rb b/spec/lib/gitlab/ci/templates/MATLAB_spec.rb
index 432040c4a14..3889d1fc8c9 100644
--- a/spec/lib/gitlab/ci/templates/MATLAB_spec.rb
+++ b/spec/lib/gitlab/ci/templates/MATLAB_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe 'MATLAB.gitlab-ci.yml' do
let(:default_branch) { 'master' }
let(:pipeline_branch) { default_branch }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
- let(:pipeline) { service.execute!(:push).payload }
+ let(:pipeline) { service.execute(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before do
diff --git a/spec/lib/gitlab/ci/templates/Terraform/base_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/Terraform/base_gitlab_ci_yaml_spec.rb
index eca79f37779..42df924f8fd 100644
--- a/spec/lib/gitlab/ci/templates/Terraform/base_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/Terraform/base_gitlab_ci_yaml_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe 'Terraform/Base.gitlab-ci.yml' do
let(:project) { create(:project, :custom_repo, files: { 'README.md' => '' }) }
let(:user) { project.first_owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
- let(:pipeline) { service.execute!(:push).payload }
+ let(:pipeline) { service.execute(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before do
diff --git a/spec/lib/gitlab/ci/templates/Terraform/base_latest_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/Terraform/base_latest_gitlab_ci_yaml_spec.rb
index 0ab81f97f20..332708ffa13 100644
--- a/spec/lib/gitlab/ci/templates/Terraform/base_latest_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/Terraform/base_latest_gitlab_ci_yaml_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe 'Terraform/Base.latest.gitlab-ci.yml' do
let(:project) { create(:project, :custom_repo, files: { 'README.md' => '' }) }
let(:user) { project.first_owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
- let(:pipeline) { service.execute!(:push).payload }
+ let(:pipeline) { service.execute(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before do
diff --git a/spec/lib/gitlab/ci/templates/Verify/load_performance_testing_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/Verify/load_performance_testing_gitlab_ci_yaml_spec.rb
index d6c7cd32f79..0f0192ad38f 100644
--- a/spec/lib/gitlab/ci/templates/Verify/load_performance_testing_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/Verify/load_performance_testing_gitlab_ci_yaml_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe 'Verify/Load-Performance-Testing.gitlab-ci.yml' do
let(:default_branch) { 'master' }
let(:pipeline_ref) { default_branch }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_ref) }
- let(:pipeline) { service.execute!(:push).payload }
+ let(:pipeline) { service.execute(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before do
diff --git a/spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb
index 1a909f52ec3..b2ca906e172 100644
--- a/spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe 'Auto-DevOps.gitlab-ci.yml' do
let(:project) { create(:project, :auto_devops, :custom_repo, files: { 'README.md' => '' }) }
let(:user) { project.first_owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
- let(:pipeline) { service.execute!(:push).payload }
+ let(:pipeline) { service.execute(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before do
diff --git a/spec/lib/gitlab/ci/templates/flutter_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/flutter_gitlab_ci_yaml_spec.rb
index de94eec09fe..afb7773ad7a 100644
--- a/spec/lib/gitlab/ci/templates/flutter_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/flutter_gitlab_ci_yaml_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe 'Flutter.gitlab-ci.yml' do
let(:project) { create(:project, :custom_repo, files: { 'README.md' => '' }) }
let(:user) { project.first_owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
- let(:pipeline) { service.execute!(:push).payload }
+ let(:pipeline) { service.execute(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before do
diff --git a/spec/lib/gitlab/ci/templates/kaniko_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/kaniko_gitlab_ci_yaml_spec.rb
index ebf52e6d65a..62e4188f59b 100644
--- a/spec/lib/gitlab/ci/templates/kaniko_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/kaniko_gitlab_ci_yaml_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe 'Kaniko.gitlab-ci.yml' do
let(:project) { create(:project, :custom_repo, files: { 'Dockerfile' => 'FROM alpine:latest' }) }
let(:user) { project.first_owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
- let(:pipeline) { service.execute!(:push).payload }
+ let(:pipeline) { service.execute(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before 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
index 5a62324da74..a44833b0c01 100644
--- a/spec/lib/gitlab/ci/templates/katalon_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/katalon_gitlab_ci_yaml_spec.rb
@@ -27,7 +27,7 @@ RSpec.describe 'Katalon.gitlab-ci.yml' do
let(:user) { project.first_owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: 'master' ) }
- let(:pipeline) { service.execute!(:push).payload }
+ let(:pipeline) { service.execute(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before do
diff --git a/spec/lib/gitlab/ci/templates/npm_spec.rb b/spec/lib/gitlab/ci/templates/npm_spec.rb
index d86a3a67823..55fd4675f11 100644
--- a/spec/lib/gitlab/ci/templates/npm_spec.rb
+++ b/spec/lib/gitlab/ci/templates/npm_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe 'npm.gitlab-ci.yml' do
let(:pipeline_tag) { 'v1.2.1' }
let(:pipeline_ref) { pipeline_branch }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_ref ) }
- let(:pipeline) { service.execute!(:push).payload }
+ let(:pipeline) { service.execute(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
def create_branch(name:)
@@ -42,7 +42,8 @@ RSpec.describe 'npm.gitlab-ci.yml' do
shared_examples 'no pipeline created' do
it 'does not create a pipeline because the only job (publish) is not created' do
- expect { pipeline }.to raise_error(Ci::CreatePipelineService::CreateError, 'No stages / jobs for this pipeline.')
+ expect(build_names).to be_empty
+ expect(pipeline.errors.full_messages).to match_array(["No stages / jobs for this pipeline."])
end
end
diff --git a/spec/lib/gitlab/ci/templates/terraform_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/terraform_gitlab_ci_yaml_spec.rb
index 2fc4b509aab..aa7d0249066 100644
--- a/spec/lib/gitlab/ci/templates/terraform_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/terraform_gitlab_ci_yaml_spec.rb
@@ -12,10 +12,10 @@ RSpec.describe 'Terraform.gitlab-ci.yml' do
describe 'the created pipeline' do
let(:default_branch) { project.default_branch_or_main }
let(:pipeline_branch) { default_branch }
- let(:project) { create(:project, :custom_repo, files: { 'README.md' => '' }) }
+ let_it_be(:project) { create(:project, :repository, create_branch: 'patch-1') }
let(:user) { project.first_owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
- let(:pipeline) { service.execute!(:push).payload }
+ let(:pipeline) { service.execute(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before do
@@ -27,23 +27,30 @@ RSpec.describe 'Terraform.gitlab-ci.yml' do
end
context 'on master branch' do
- it 'creates init, validate and build jobs', :aggregate_failures do
+ it 'creates init, validate,build terraform jobs as well as kics-iac-sast job', :aggregate_failures do
expect(pipeline.errors).to be_empty
- expect(build_names).to include('validate', 'build', 'deploy')
+ expect(build_names).to include('kics-iac-sast', 'validate', 'build', 'deploy')
end
end
context 'outside the master branch' do
let(:pipeline_branch) { 'patch-1' }
- before do
- project.repository.create_branch(pipeline_branch, default_branch)
- end
-
it 'does not creates a deploy and a test job', :aggregate_failures do
expect(pipeline.errors).to be_empty
expect(build_names).not_to include('deploy')
end
end
+
+ context 'on merge request' do
+ let(:service) { MergeRequests::CreatePipelineService.new(project: project, current_user: user) }
+ let(:merge_request) { create(:merge_request, :simple, source_project: project) }
+ let(:pipeline) { service.execute(merge_request).payload }
+
+ it 'creates a pipeline with no jobs' do
+ expect(pipeline).to be_merge_request_event
+ expect(pipeline.builds.count).to be_zero
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/ci/templates/terraform_latest_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/terraform_latest_gitlab_ci_yaml_spec.rb
index 42e56c4ab3c..6ae51f9783b 100644
--- a/spec/lib/gitlab/ci/templates/terraform_latest_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/terraform_latest_gitlab_ci_yaml_spec.rb
@@ -12,10 +12,10 @@ RSpec.describe 'Terraform.latest.gitlab-ci.yml' do
describe 'the created pipeline' do
let(:default_branch) { project.default_branch_or_main }
let(:pipeline_branch) { default_branch }
- let(:project) { create(:project, :custom_repo, files: { 'README.md' => '' }) }
- let(:user) { project.first_owner }
+ let_it_be(:project) { create(:project, :repository, create_branch: 'patch-1') }
+ let_it_be(:user) { project.first_owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
- let(:pipeline) { service.execute!(:push).payload }
+ let(:pipeline) { service.execute(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before do
@@ -36,14 +36,38 @@ RSpec.describe 'Terraform.latest.gitlab-ci.yml' do
context 'outside the master branch' do
let(:pipeline_branch) { 'patch-1' }
- before do
- project.repository.create_branch(pipeline_branch, default_branch)
- end
-
it 'does not creates a deploy and a test job', :aggregate_failures do
expect(pipeline.errors).to be_empty
expect(build_names).not_to include('deploy')
end
end
+
+ context 'on merge request' do
+ let(:pipeline_branch) { 'patch-1' }
+ let(:mr_service) { MergeRequests::CreatePipelineService.new(project: project, current_user: user) }
+ let(:merge_request) { create(:merge_request, :simple, source_project: project, source_branch: pipeline_branch ) }
+ let(:mr_pipeline) { mr_service.execute(merge_request).payload }
+ let(:mr_build_names) { mr_pipeline.builds.pluck(:name) }
+ let(:branch_service) { Ci::CreatePipelineService.new(project, user, ref: merge_request.source_branch ) }
+ let(:branch_pipeline) { branch_service.execute(:push).payload }
+ let(:branch_build_names) { branch_pipeline.builds.pluck(:name) }
+
+ # This is needed so that the terraform artifacts and sast_iac artifacts
+ # are both available in the MR
+ it 'creates a pipeline with the terraform and sast_iac jobs' do
+ expect(mr_pipeline).to be_merge_request_event
+ expect(mr_pipeline.errors.full_messages).to be_empty
+ expect(mr_build_names).to include('kics-iac-sast', 'validate', 'build')
+ end
+
+ it 'does not creates a deploy', :aggregate_failures do
+ expect(mr_build_names).not_to include('deploy')
+ end
+
+ it 'does not create a branch pipeline', :aggregate_failures do
+ expect(branch_build_names).to be_empty
+ expect(branch_pipeline.errors.full_messages).to match_array(["No stages / jobs for this pipeline."])
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/ci/templates/themekit_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/themekit_gitlab_ci_yaml_spec.rb
index 4708108f404..157fd39f1cc 100644
--- a/spec/lib/gitlab/ci/templates/themekit_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/themekit_gitlab_ci_yaml_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe 'ThemeKit.gitlab-ci.yml' do
let(:project) { create(:project, :custom_repo, files: { 'README.md' => '' }) }
let(:user) { project.first_owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_ref) }
- let(:pipeline) { service.execute!(:push).payload }
+ let(:pipeline) { service.execute(:push).payload }
let(:build_names) { pipeline.builds.pluck(:name) }
before do
@@ -51,9 +51,8 @@ RSpec.describe 'ThemeKit.gitlab-ci.yml' do
end
it 'has no jobs' do
- expect { pipeline }.to raise_error(
- Ci::CreatePipelineService::CreateError, 'No stages / jobs for this pipeline.'
- )
+ expect(build_names).to be_empty
+ expect(pipeline.errors.full_messages).to match_array(["No stages / jobs for this pipeline."])
end
end
end
diff --git a/spec/lib/gitlab/ci/variables/collection/item_spec.rb b/spec/lib/gitlab/ci/variables/collection/item_spec.rb
index 9443bf6d6d5..f7c6f7f51df 100644
--- a/spec/lib/gitlab/ci/variables/collection/item_spec.rb
+++ b/spec/lib/gitlab/ci/variables/collection/item_spec.rb
@@ -197,11 +197,11 @@ RSpec.describe Gitlab::Ci::Variables::Collection::Item do
end
end
- describe '#raw' do
+ describe '#raw?' do
it 'returns false when :raw is not specified' do
item = described_class.new(**variable)
- expect(item.raw).to eq false
+ expect(item.raw?).to eq false
end
context 'when :raw is specified as true' do
@@ -212,7 +212,7 @@ RSpec.describe Gitlab::Ci::Variables::Collection::Item do
it 'returns true' do
item = described_class.new(**variable)
- expect(item.raw).to eq true
+ expect(item.raw?).to eq true
end
end
end
diff --git a/spec/lib/gitlab/ci/variables/collection_spec.rb b/spec/lib/gitlab/ci/variables/collection_spec.rb
index 7d4a1eef70b..10b8f0065d9 100644
--- a/spec/lib/gitlab/ci/variables/collection_spec.rb
+++ b/spec/lib/gitlab/ci/variables/collection_spec.rb
@@ -300,7 +300,6 @@ RSpec.describe Gitlab::Ci::Variables::Collection do
Gitlab::Ci::Variables::Collection.new
.append(key: 'CI_JOB_NAME', value: 'test-1')
.append(key: 'CI_BUILD_ID', value: '1')
- .append(key: 'RAW_VAR', value: '$TEST1', raw: true)
.append(key: 'TEST1', value: 'test-3')
.append(key: 'FILEVAR1', value: 'file value 1', file: true)
end
@@ -322,10 +321,6 @@ RSpec.describe Gitlab::Ci::Variables::Collection do
value: 'key${TEST1}-${CI_JOB_NAME}',
result: 'keytest-3-test-1'
},
- "complex expansions with raw variable": {
- value: 'key${RAW_VAR}-${CI_JOB_NAME}',
- result: 'key$TEST1-test-1'
- },
"missing variable not keeping original": {
value: 'key${MISSING_VAR}-${CI_JOB_NAME}',
result: 'key-test-1'
@@ -339,22 +334,22 @@ RSpec.describe Gitlab::Ci::Variables::Collection do
value: 'key-$TEST1-%%HOME%%-$${HOME}',
result: 'key-test-3-%%HOME%%-$${HOME}'
},
- "file variable with expand_file_vars: true": {
+ "file variable with expand_file_refs: true": {
value: 'key-$FILEVAR1-$TEST1',
result: 'key-file value 1-test-3'
},
- "file variable with expand_file_vars: false": {
+ "file variable with expand_file_refs: false": {
value: 'key-$FILEVAR1-$TEST1',
result: 'key-$FILEVAR1-test-3',
- expand_file_vars: false
+ expand_file_refs: false
}
}
end
with_them do
- let(:options) { { keep_undefined: keep_undefined, expand_file_vars: expand_file_vars }.compact }
+ let(:options) { { keep_undefined: keep_undefined, expand_file_refs: expand_file_refs }.compact }
- subject(:result) { collection.expand_value(value, **options) }
+ subject(:expanded_result) { collection.expand_value(value, **options) }
it 'matches expected expansion' do
is_expected.to eq(result)
@@ -509,17 +504,35 @@ RSpec.describe Gitlab::Ci::Variables::Collection do
{ key: 'variable4', value: 'keyvalue${variable2}value3' }
]
},
- "complex expansions with raw variable": {
+ "complex expansions with raw variable with expand_raw_refs: true (default)": {
+ variables: [
+ { key: 'variable1', value: 'value1' },
+ { key: 'raw_var', value: 'raw-$variable1', raw: true },
+ { key: 'nonraw_var', value: 'nonraw-$variable1' },
+ { key: 'variable2', value: '$raw_var and $nonraw_var' }
+ ],
+ keep_undefined: false,
+ result: [
+ { key: 'variable1', value: 'value1' },
+ { key: 'raw_var', value: 'raw-$variable1', raw: true },
+ { key: 'nonraw_var', value: 'nonraw-value1' },
+ { key: 'variable2', value: 'raw-$variable1 and nonraw-value1' }
+ ]
+ },
+ "complex expansions with raw variable with expand_raw_refs: false": {
variables: [
- { key: 'variable3', value: 'key_${variable}_${variable2}' },
- { key: 'variable', value: '$variable2', raw: true },
- { key: 'variable2', value: 'value2' }
+ { key: 'variable1', value: 'value1' },
+ { key: 'raw_var', value: 'raw-$variable1', raw: true },
+ { key: 'nonraw_var', value: 'nonraw-$variable1' },
+ { key: 'variable2', value: '$raw_var and $nonraw_var' }
],
keep_undefined: false,
+ expand_raw_refs: false,
result: [
- { key: 'variable', value: '$variable2', raw: true },
- { key: 'variable2', value: 'value2' },
- { key: 'variable3', value: 'key_$variable2_value2' }
+ { key: 'variable1', value: 'value1' },
+ { key: 'raw_var', value: 'raw-$variable1', raw: true },
+ { key: 'nonraw_var', value: 'nonraw-value1' },
+ { key: 'variable2', value: '$raw_var and nonraw-value1' }
]
},
"variable value referencing password with special characters": {
@@ -553,8 +566,9 @@ RSpec.describe Gitlab::Ci::Variables::Collection do
with_them do
let(:collection) { Gitlab::Ci::Variables::Collection.new(variables) }
+ let(:options) { { keep_undefined: keep_undefined, expand_raw_refs: expand_raw_refs }.compact }
- subject { collection.sort_and_expand_all(keep_undefined: keep_undefined) }
+ subject(:expanded_result) { collection.sort_and_expand_all(**options) }
it 'returns Collection' do
is_expected.to be_an_instance_of(Gitlab::Ci::Variables::Collection)
@@ -601,7 +615,8 @@ RSpec.describe Gitlab::Ci::Variables::Collection do
it 'logs file_variable_is_referenced_in_another_variable once for VAR5' do
expect(Gitlab::AppJsonLogger).to receive(:info).with(
event: 'file_variable_is_referenced_in_another_variable',
- project_id: project.id
+ project_id: project.id,
+ variable: 'FILEVAR4'
).once
sort_and_expand_all
diff --git a/spec/lib/gitlab/ci/yaml_processor_spec.rb b/spec/lib/gitlab/ci/yaml_processor_spec.rb
index ebf8422489e..5de813f7739 100644
--- a/spec/lib/gitlab/ci/yaml_processor_spec.rb
+++ b/spec/lib/gitlab/ci/yaml_processor_spec.rb
@@ -1071,6 +1071,7 @@ module Gitlab
let(:build) { execute.builds.first }
let(:job_variables) { build[:job_variables] }
+ let(:root_variables) { execute.root_variables }
let(:root_variables_inheritance) { build[:root_variables_inheritance] }
context 'when global variables are defined' do
@@ -1193,6 +1194,78 @@ module Gitlab
expect(root_variables_inheritance).to eq(true)
end
end
+
+ context 'when variables have data other than value' do
+ let(:config) do
+ <<~YAML
+ variables:
+ VAR1: value1
+ VAR2:
+ value: value2
+ description: description2
+ VAR3:
+ value: value3
+ expand: false
+
+ rspec:
+ script: rspec
+ variables:
+ VAR4: value4
+ VAR5:
+ value: value5
+ expand: false
+ VAR6:
+ value: value6
+ expand: true
+ YAML
+ end
+
+ it 'returns variables' do
+ expect(job_variables).to contain_exactly(
+ { key: 'VAR4', value: 'value4' },
+ { key: 'VAR5', value: 'value5', raw: true },
+ { key: 'VAR6', value: 'value6', raw: false }
+ )
+
+ expect(execute.root_variables).to contain_exactly(
+ { key: 'VAR1', value: 'value1' },
+ { key: 'VAR2', value: 'value2' },
+ { key: 'VAR3', value: 'value3', raw: true }
+ )
+
+ expect(execute.root_variables_with_prefill_data).to eq(
+ 'VAR1' => { value: 'value1' },
+ 'VAR2' => { value: 'value2', description: 'description2' },
+ 'VAR3' => { value: 'value3', raw: true }
+ )
+ end
+
+ context 'when the FF ci_raw_variables_in_yaml_config is disabled' do
+ before do
+ stub_feature_flags(ci_raw_variables_in_yaml_config: false)
+ end
+
+ it 'returns variables without description and raw' do
+ expect(job_variables).to contain_exactly(
+ { key: 'VAR4', value: 'value4' },
+ { key: 'VAR5', value: 'value5' },
+ { key: 'VAR6', value: 'value6' }
+ )
+
+ expect(execute.root_variables).to contain_exactly(
+ { key: 'VAR1', value: 'value1' },
+ { key: 'VAR2', value: 'value2' },
+ { key: 'VAR3', value: 'value3' }
+ )
+
+ expect(execute.root_variables_with_prefill_data).to eq(
+ 'VAR1' => { value: 'value1' },
+ 'VAR2' => { value: 'value2', description: 'description2' },
+ 'VAR3' => { value: 'value3' }
+ )
+ end
+ end
+ end
end
context 'when using `extends`' do
@@ -1334,7 +1407,7 @@ module Gitlab
context "when an array of wrong keyed object is provided" do
let(:include_content) { [{ yolo: "/local.gitlab-ci.yml" }] }
- it_behaves_like 'returns errors', /needs to match exactly one accessor/
+ it_behaves_like 'returns errors', /does not have a valid subkey for include/
end
context "when an array of mixed typed objects is provided" do
@@ -1359,7 +1432,7 @@ module Gitlab
context "when the include type is incorrect" do
let(:include_content) { { name: "/local.gitlab-ci.yml" } }
- it_behaves_like 'returns errors', /needs to match exactly one accessor/
+ it_behaves_like 'returns errors', /does not have a valid subkey for include/
end
end