summaryrefslogtreecommitdiff
path: root/spec/lib/gitlab/ci
diff options
context:
space:
mode:
Diffstat (limited to 'spec/lib/gitlab/ci')
-rw-r--r--spec/lib/gitlab/ci/config/entry/artifacts_spec.rb17
-rw-r--r--spec/lib/gitlab/ci/config/entry/variables_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/config/external/file/local_spec.rb6
-rw-r--r--spec/lib/gitlab/ci/config/external/file/project_spec.rb6
-rw-r--r--spec/lib/gitlab/ci/config/external/mapper_spec.rb126
-rw-r--r--spec/lib/gitlab/ci/config/external/processor_spec.rb13
-rw-r--r--spec/lib/gitlab/ci/config_spec.rb24
-rw-r--r--spec/lib/gitlab/ci/lint_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/parsers/coverage/cobertura_spec.rb6
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/build_spec.rb114
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/command_spec.rb26
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/seed_block_spec.rb12
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb39
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/template_usage_spec.rb37
-rw-r--r--spec/lib/gitlab/ci/pipeline/seed/build_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/pipeline/seed/pipeline_spec.rb3
-rw-r--r--spec/lib/gitlab/ci/reports/test_failure_history_spec.rb13
-rw-r--r--spec/lib/gitlab/ci/status/group/factory_spec.rb5
-rw-r--r--spec/lib/gitlab/ci/syntax_templates_spec.rb25
-rw-r--r--spec/lib/gitlab/ci/templates/5_minute_production_app_ci_yaml_spec.rb49
-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.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/Jobs/code_quality_gitlab_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/Jobs/deploy_gitlab_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/Jobs/test_gitlab_ci_yaml_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/Verify/load_performance_testing_gitlab_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/templates/flutter_gitlab_ci_yaml_spec.rb25
-rw-r--r--spec/lib/gitlab/ci/templates/npm_spec.rb3
-rw-r--r--spec/lib/gitlab/ci/templates/terraform_latest_gitlab_ci_yaml_spec.rb3
-rw-r--r--spec/lib/gitlab/ci/variables/collection/sorted_spec.rb251
-rw-r--r--spec/lib/gitlab/ci/yaml_processor_spec.rb34
33 files changed, 707 insertions, 154 deletions
diff --git a/spec/lib/gitlab/ci/config/entry/artifacts_spec.rb b/spec/lib/gitlab/ci/config/entry/artifacts_spec.rb
index 028dcd3e1e6..0e6d5b6c311 100644
--- a/spec/lib/gitlab/ci/config/entry/artifacts_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/artifacts_spec.rb
@@ -36,6 +36,14 @@ RSpec.describe Gitlab::Ci::Config::Entry::Artifacts do
expect(entry.value).to eq config
end
end
+
+ context "when value includes 'public' keyword" do
+ let(:config) { { paths: %w[results.txt], public: false } }
+
+ it 'returns general artifact and report-type artifacts configuration' do
+ expect(entry.value).to eq config
+ end
+ end
end
context 'when entry value is not correct' do
@@ -67,6 +75,15 @@ RSpec.describe Gitlab::Ci::Config::Entry::Artifacts do
end
end
+ context "when 'public' is not a boolean" do
+ let(:config) { { paths: %w[results.txt], public: 'false' } }
+
+ it 'reports error' do
+ expect(entry.errors)
+ .to include 'artifacts public should be a boolean value'
+ end
+ end
+
context "when 'expose_as' is not a string" do
let(:config) { { paths: %w[results.txt], expose_as: 1 } }
diff --git a/spec/lib/gitlab/ci/config/entry/variables_spec.rb b/spec/lib/gitlab/ci/config/entry/variables_spec.rb
index 426a38e2ef7..78d37e228df 100644
--- a/spec/lib/gitlab/ci/config/entry/variables_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/variables_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Ci::Config::Entry::Variables do
let(:metadata) { {} }
- subject { described_class.new(config, metadata) }
+ subject { described_class.new(config, **metadata) }
shared_examples 'valid config' do
describe '#value' do
diff --git a/spec/lib/gitlab/ci/config/external/file/local_spec.rb b/spec/lib/gitlab/ci/config/external/file/local_spec.rb
index fdd29afe2d6..7e39fae7b9b 100644
--- a/spec/lib/gitlab/ci/config/external/file/local_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/file/local_spec.rb
@@ -16,7 +16,8 @@ RSpec.describe Gitlab::Ci::Config::External::File::Local do
project: project,
sha: sha,
user: user,
- parent_pipeline: parent_pipeline
+ parent_pipeline: parent_pipeline,
+ variables: project.predefined_variables.to_runner_variables
}
end
@@ -131,7 +132,8 @@ RSpec.describe Gitlab::Ci::Config::External::File::Local do
user: user,
project: project,
sha: sha,
- parent_pipeline: parent_pipeline)
+ parent_pipeline: parent_pipeline,
+ variables: project.predefined_variables.to_runner_variables)
end
end
diff --git a/spec/lib/gitlab/ci/config/external/file/project_spec.rb b/spec/lib/gitlab/ci/config/external/file/project_spec.rb
index a5e4e27df6f..0e8851ba915 100644
--- a/spec/lib/gitlab/ci/config/external/file/project_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/file/project_spec.rb
@@ -16,7 +16,8 @@ RSpec.describe Gitlab::Ci::Config::External::File::Project do
project: context_project,
sha: '12345',
user: context_user,
- parent_pipeline: parent_pipeline
+ parent_pipeline: parent_pipeline,
+ variables: project.predefined_variables.to_runner_variables
}
end
@@ -165,7 +166,8 @@ RSpec.describe Gitlab::Ci::Config::External::File::Project do
user: user,
project: project,
sha: project.commit('master').id,
- parent_pipeline: parent_pipeline)
+ parent_pipeline: parent_pipeline,
+ variables: project.predefined_variables.to_runner_variables)
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 7ad57827e30..4fdaaca8316 100644
--- a/spec/lib/gitlab/ci/config/external/mapper_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/mapper_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe Gitlab::Ci::Config::External::Mapper do
let(:local_file) { '/lib/gitlab/ci/templates/non-existent-file.yml' }
let(:remote_url) { 'https://gitlab.com/gitlab-org/gitlab-foss/blob/1234/.gitlab-ci-1.yml' }
let(:template_file) { 'Auto-DevOps.gitlab-ci.yml' }
- let(:context_params) { { project: project, sha: '123456', user: user } }
+ let(:context_params) { { project: project, sha: '123456', user: user, variables: project.predefined_variables.to_runner_variables } }
let(:context) { Gitlab::Ci::Config::External::Context.new(**context_params) }
let(:file_content) do
@@ -124,17 +124,6 @@ RSpec.describe Gitlab::Ci::Config::External::Mapper do
an_instance_of(Gitlab::Ci::Config::External::File::Project),
an_instance_of(Gitlab::Ci::Config::External::File::Project))
end
-
- context 'when FF ci_include_multiple_files_from_project is disabled' do
- before do
- stub_feature_flags(ci_include_multiple_files_from_project: false)
- end
-
- it 'returns a File instance' do
- expect(subject).to contain_exactly(
- an_instance_of(Gitlab::Ci::Config::External::File::Project))
- end
- end
end
end
@@ -236,5 +225,118 @@ RSpec.describe Gitlab::Ci::Config::External::Mapper do
end
end
end
+
+ context "when 'include' section uses project variable" do
+ let(:full_local_file_path) { '$CI_PROJECT_PATH' + local_file }
+
+ context 'when local file is included as a single string' do
+ let(:values) do
+ { include: full_local_file_path }
+ end
+
+ it 'expands the variable', :aggregate_failures do
+ expect(subject[0].location).to eq(project.full_path + local_file)
+ expect(subject).to contain_exactly(an_instance_of(Gitlab::Ci::Config::External::File::Local))
+ end
+ end
+
+ context 'when remote file is included as a single string' do
+ let(:remote_url) { "#{Gitlab.config.gitlab.url}/radio/.gitlab-ci.yml" }
+
+ let(:values) do
+ { include: '$CI_SERVER_URL/radio/.gitlab-ci.yml' }
+ end
+
+ it 'expands the variable', :aggregate_failures do
+ expect(subject[0].location).to eq(remote_url)
+ expect(subject).to contain_exactly(an_instance_of(Gitlab::Ci::Config::External::File::Remote))
+ end
+ end
+
+ context 'defined as an array' do
+ let(:values) do
+ { include: [full_local_file_path, remote_url],
+ image: 'ruby:2.7' }
+ end
+
+ it 'expands the variable' do
+ expect(subject[0].location).to eq(project.full_path + local_file)
+ expect(subject[1].location).to eq(remote_url)
+ end
+ end
+
+ context 'defined as an array of hashes' do
+ let(:values) do
+ { include: [{ local: full_local_file_path }, { remote: remote_url }],
+ image: 'ruby:2.7' }
+ end
+
+ it 'expands the variable' do
+ expect(subject[0].location).to eq(project.full_path + local_file)
+ expect(subject[1].location).to eq(remote_url)
+ end
+ end
+
+ context 'local file hash' do
+ let(:values) do
+ { include: { 'local' => full_local_file_path } }
+ end
+
+ it 'expands the variable' do
+ expect(subject[0].location).to eq(project.full_path + local_file)
+ end
+ end
+
+ context 'project name' do
+ let(:values) do
+ { include: { project: '$CI_PROJECT_PATH', file: local_file },
+ image: 'ruby:2.7' }
+ end
+
+ it 'expands the variable', :aggregate_failures do
+ expect(subject[0].project_name).to eq(project.full_path)
+ expect(subject).to contain_exactly(an_instance_of(Gitlab::Ci::Config::External::File::Project))
+ end
+ end
+
+ context 'with multiple files' do
+ let(:values) do
+ { include: { project: project.full_path, file: [full_local_file_path, 'another_file_path.yml'] },
+ image: 'ruby:2.7' }
+ end
+
+ it 'expands the variable' do
+ expect(subject[0].location).to eq(project.full_path + local_file)
+ expect(subject[1].location).to eq('another_file_path.yml')
+ end
+ end
+
+ context 'when include variable has an unsupported type for variable expansion' do
+ let(:values) do
+ { include: { project: project.id, file: local_file },
+ image: 'ruby:2.7' }
+ end
+
+ it 'does not invoke expansion for the variable', :aggregate_failures do
+ expect(ExpandVariables).not_to receive(:expand).with(project.id, context_params[:variables])
+
+ expect { subject }.to raise_error(described_class::AmbigiousSpecificationError)
+ end
+ end
+
+ context 'when feature flag is turned off' do
+ let(:values) do
+ { include: full_local_file_path }
+ end
+
+ before do
+ stub_feature_flags(variables_in_include_section_ci: false)
+ end
+
+ it 'does not expand the variables' do
+ expect(subject[0].location).to eq('$CI_PROJECT_PATH' + local_file)
+ end
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/ci/config/external/processor_spec.rb b/spec/lib/gitlab/ci/config/external/processor_spec.rb
index 150a2ec2929..d2d7116bb12 100644
--- a/spec/lib/gitlab/ci/config/external/processor_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/processor_spec.rb
@@ -365,19 +365,6 @@ RSpec.describe Gitlab::Ci::Config::External::Processor do
output = processor.perform
expect(output.keys).to match_array([:image, :my_build, :my_test])
end
-
- context 'when FF ci_include_multiple_files_from_project is disabled' do
- before do
- stub_feature_flags(ci_include_multiple_files_from_project: false)
- end
-
- it 'raises an error' do
- expect { processor.perform }.to raise_error(
- described_class::IncludeError,
- 'Included file `["/templates/my-build.yml", "/templates/my-test.yml"]` needs to be a string'
- )
- end
- end
end
end
end
diff --git a/spec/lib/gitlab/ci/config_spec.rb b/spec/lib/gitlab/ci/config_spec.rb
index b5a0f0e3fd7..dc03d2f80fe 100644
--- a/spec/lib/gitlab/ci/config_spec.rb
+++ b/spec/lib/gitlab/ci/config_spec.rb
@@ -82,6 +82,30 @@ RSpec.describe Gitlab::Ci::Config do
end
end
+ describe '#included_templates' do
+ let(:yml) do
+ <<-EOS
+ include:
+ - template: Jobs/Deploy.gitlab-ci.yml
+ - template: Jobs/Build.gitlab-ci.yml
+ - remote: https://example.com/gitlab-ci.yml
+ EOS
+ end
+
+ before do
+ stub_request(:get, 'https://example.com/gitlab-ci.yml').to_return(status: 200, body: <<-EOS)
+ test:
+ script: [ 'echo hello world' ]
+ EOS
+ end
+
+ subject(:included_templates) do
+ config.included_templates
+ end
+
+ it { is_expected.to contain_exactly('Jobs/Deploy.gitlab-ci.yml', 'Jobs/Build.gitlab-ci.yml') }
+ end
+
context 'when using extendable hash' do
let(:yml) do
<<-EOS
diff --git a/spec/lib/gitlab/ci/lint_spec.rb b/spec/lib/gitlab/ci/lint_spec.rb
index c67f8464123..67324c09d86 100644
--- a/spec/lib/gitlab/ci/lint_spec.rb
+++ b/spec/lib/gitlab/ci/lint_spec.rb
@@ -247,7 +247,7 @@ RSpec.describe Gitlab::Ci::Lint do
include_context 'advanced validations' do
it 'runs advanced logical validations' do
expect(subject).not_to be_valid
- expect(subject.errors).to eq(["test: needs 'build'"])
+ expect(subject.errors).to eq(["'test' job needs 'build' job, but it was not added to the pipeline"])
end
end
diff --git a/spec/lib/gitlab/ci/parsers/coverage/cobertura_spec.rb b/spec/lib/gitlab/ci/parsers/coverage/cobertura_spec.rb
index 2313378d1e9..546de2bee5c 100644
--- a/spec/lib/gitlab/ci/parsers/coverage/cobertura_spec.rb
+++ b/spec/lib/gitlab/ci/parsers/coverage/cobertura_spec.rb
@@ -224,6 +224,12 @@ RSpec.describe Gitlab::Ci::Parsers::Coverage::Cobertura do
it_behaves_like 'ignoring sources, project_path, and worktree_paths'
end
+ context 'when there is an empty <sources>' do
+ let(:sources_xml) { '<sources />' }
+
+ it_behaves_like 'ignoring sources, project_path, and worktree_paths'
+ end
+
context 'when there is a <sources>' do
context 'and has a single source with a pattern for Go projects' do
let(:project_path) { 'local/go' } # Make sure we're not making false positives
diff --git a/spec/lib/gitlab/ci/pipeline/chain/build_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/build_spec.rb
index 6da565a2bf6..20406acb658 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/build_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/build_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Ci::Pipeline::Chain::Build do
- let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:project, reload: true) { create(:project, :repository) }
let_it_be(:user) { create(:user, developer_projects: [project]) }
let(:pipeline) { Ci::Pipeline.new }
@@ -29,29 +29,96 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Build do
let(:step) { described_class.new(pipeline, command) }
- before do
- stub_ci_pipeline_yaml_file(gitlab_ci_yaml)
+ shared_examples 'builds pipeline' do
+ it 'builds a pipeline with the expected attributes' do
+ step.perform!
+
+ expect(pipeline.sha).not_to be_empty
+ expect(pipeline.sha).to eq project.commit.id
+ expect(pipeline.ref).to eq 'master'
+ expect(pipeline.tag).to be false
+ expect(pipeline.user).to eq user
+ expect(pipeline.project).to eq project
+ end
end
- it 'never breaks the chain' do
- step.perform!
+ shared_examples 'breaks the chain' do
+ it 'returns true' do
+ step.perform!
+
+ expect(step.break?).to be true
+ end
+ end
+
+ shared_examples 'does not break the chain' do
+ it 'returns false' do
+ step.perform!
+
+ expect(step.break?).to be false
+ end
+ end
- expect(step.break?).to be false
+ before do
+ stub_ci_pipeline_yaml_file(gitlab_ci_yaml)
end
- it 'fills pipeline object with data' do
+ it_behaves_like 'does not break the chain'
+ it_behaves_like 'builds pipeline'
+
+ it 'sets pipeline variables' do
step.perform!
- expect(pipeline.sha).not_to be_empty
- expect(pipeline.sha).to eq project.commit.id
- expect(pipeline.ref).to eq 'master'
- expect(pipeline.tag).to be false
- expect(pipeline.user).to eq user
- expect(pipeline.project).to eq project
expect(pipeline.variables.map { |var| var.slice(:key, :secret_value) })
.to eq variables_attributes.map(&:with_indifferent_access)
end
+ context 'when project setting restrict_user_defined_variables is enabled' do
+ before do
+ project.update!(restrict_user_defined_variables: true)
+ end
+
+ context 'when user is developer' do
+ it_behaves_like 'breaks the chain'
+ it_behaves_like 'builds pipeline'
+
+ it 'returns an error on variables_attributes', :aggregate_failures do
+ step.perform!
+
+ expect(pipeline.errors.full_messages).to eq(['Insufficient permissions to set pipeline variables'])
+ expect(pipeline.variables).to be_empty
+ end
+
+ context 'when variables_attributes is not specified' do
+ let(:variables_attributes) { nil }
+
+ it_behaves_like 'does not break the chain'
+ it_behaves_like 'builds pipeline'
+
+ it 'assigns empty variables' do
+ step.perform!
+
+ expect(pipeline.variables).to be_empty
+ end
+ end
+ end
+
+ context 'when user is maintainer' do
+ before do
+ project.add_maintainer(user)
+ end
+
+ it_behaves_like 'does not break the chain'
+ it_behaves_like 'builds pipeline'
+
+ it 'assigns variables_attributes' do
+ step.perform!
+
+ expect(pipeline.variables.map { |var| var.slice(:key, :secret_value) })
+ .to eq variables_attributes.map(&:with_indifferent_access)
+ end
+ end
+ end
+
it 'returns a valid pipeline' do
step.perform!
@@ -157,4 +224,25 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Build do
expect(pipeline.target_sha).to eq(external_pull_request.target_sha)
end
end
+
+ context 'when keep_latest_artifact is set' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:keep_latest_artifact, :locking_result) do
+ true | 'artifacts_locked'
+ false | 'unlocked'
+ end
+
+ with_them do
+ before do
+ project.update!(ci_keep_latest_artifact: keep_latest_artifact)
+ end
+
+ it 'builds a pipeline with appropriate locked value' do
+ step.perform!
+
+ expect(pipeline.locked).to eq(locking_result)
+ 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 bc2012e83bd..9ca5aeeea58 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/command_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/command_spec.rb
@@ -295,4 +295,30 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Command do
it { is_expected.to eq(false) }
end
end
+
+ describe '#creates_child_pipeline?' do
+ let(:command) { described_class.new(bridge: bridge) }
+
+ subject { command.creates_child_pipeline? }
+
+ context 'when bridge is present' do
+ context 'when bridge triggers a child pipeline' do
+ let(:bridge) { double(: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) }
+
+ it { is_expected.to be_falsey }
+ end
+ end
+
+ context 'when bridge is not present' do
+ let(:bridge) { nil }
+
+ it { is_expected.to be_falsey }
+ end
+ end
end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/seed_block_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/seed_block_spec.rb
index 85c8e20767f..fabfbd779f3 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/seed_block_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/seed_block_spec.rb
@@ -51,18 +51,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::SeedBlock do
expect(pipeline.variables.size).to eq(1)
end
-
- context 'when FF ci_seed_block_run_before_workflow_rules is disabled' do
- before do
- stub_feature_flags(ci_seed_block_run_before_workflow_rules: false)
- end
-
- it 'does not execute the block' do
- run_chain
-
- expect(pipeline.variables.size).to eq(0)
- end
- end
end
context 'when the seeds_block tries to save the pipelie' do
diff --git a/spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb
index 0ce8b80902e..80013cab6ee 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb
@@ -20,6 +20,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Seed do
describe '#perform!' do
before do
stub_ci_pipeline_yaml_file(YAML.dump(config))
+ run_chain
end
let(:config) do
@@ -36,20 +37,14 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Seed do
end
it 'allocates next IID' do
- run_chain
-
expect(pipeline.iid).to be_present
end
it 'ensures ci_ref' do
- run_chain
-
expect(pipeline.ci_ref).to be_present
end
it 'sets the seeds in the command object' do
- run_chain
-
expect(command.pipeline_seed).to be_a(Gitlab::Ci::Pipeline::Seed::Pipeline)
expect(command.pipeline_seed.size).to eq 1
end
@@ -64,8 +59,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Seed do
end
it 'correctly fabricates stages and builds' do
- run_chain
-
seed = command.pipeline_seed
expect(seed.stages.size).to eq 2
@@ -91,8 +84,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Seed do
end
it 'returns pipeline seed with jobs only assigned to master' do
- run_chain
-
seed = command.pipeline_seed
expect(seed.size).to eq 1
@@ -112,8 +103,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Seed do
end
it 'returns pipeline seed with jobs only assigned to schedules' do
- run_chain
-
seed = command.pipeline_seed
expect(seed.size).to eq 1
@@ -141,8 +130,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Seed do
let(:pipeline) { build(:ci_pipeline, project: project) }
it 'returns seeds for kubernetes dependent job' do
- run_chain
-
seed = command.pipeline_seed
expect(seed.size).to eq 2
@@ -154,8 +141,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Seed do
context 'when kubernetes is not active' do
it 'does not return seeds for kubernetes dependent job' do
- run_chain
-
seed = command.pipeline_seed
expect(seed.size).to eq 1
@@ -173,8 +158,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Seed do
end
it 'returns stage seeds only when variables expression is truthy' do
- run_chain
-
seed = command.pipeline_seed
expect(seed.size).to eq 1
@@ -187,24 +170,8 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Seed do
->(pipeline) { pipeline.variables.build(key: 'VAR', value: '123') }
end
- context 'when FF ci_seed_block_run_before_workflow_rules is enabled' do
- it 'does not execute the block' do
- run_chain
-
- expect(pipeline.variables.size).to eq(0)
- end
- end
-
- context 'when FF ci_seed_block_run_before_workflow_rules is disabled' do
- before do
- stub_feature_flags(ci_seed_block_run_before_workflow_rules: false)
- end
-
- it 'executes the block' do
- run_chain
-
- expect(pipeline.variables.size).to eq(1)
- end
+ it 'does not execute the block' do
+ expect(pipeline.variables.size).to eq(0)
end
end
end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/template_usage_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/template_usage_spec.rb
new file mode 100644
index 00000000000..3616461d94f
--- /dev/null
+++ b/spec/lib/gitlab/ci/pipeline/chain/template_usage_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Pipeline::Chain::TemplateUsage do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { create(:user) }
+ let(:pipeline) { create(:ci_pipeline, project: project) }
+
+ let(:command) do
+ Gitlab::Ci::Pipeline::Chain::Command.new(project: project, current_user: user)
+ end
+
+ let(:step) { described_class.new(pipeline, command) }
+
+ describe '#perform!' do
+ subject(:perform) { step.perform! }
+
+ it 'tracks the included templates' do
+ expect(command).to(
+ receive(:yaml_processor_result)
+ .and_return(
+ double(included_templates: %w(Template-1 Template-2))
+ )
+ )
+
+ %w(Template-1 Template-2).each do |expected_template|
+ expect(Gitlab::UsageDataCounters::CiTemplateUniqueCounter).to(
+ receive(:track_unique_project_event)
+ .with(project_id: project.id, template: expected_template)
+ )
+ end
+
+ perform
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
index bc10e94c81d..cf020fc343c 100644
--- a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
@@ -966,7 +966,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
it "returns an error" do
expect(subject.errors).to contain_exactly(
- "rspec: needs 'build'")
+ "'rspec' job needs 'build' job, but it was not added to the pipeline")
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 1790388da03..860b07647bd 100644
--- a/spec/lib/gitlab/ci/pipeline/seed/pipeline_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/seed/pipeline_spec.rb
@@ -62,7 +62,8 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Pipeline do
needs_attributes: [{ name: 'non-existent', artifacts: true }]
}
- expect(seed.errors).to contain_exactly("invalid_job: needs 'non-existent'")
+ expect(seed.errors).to contain_exactly(
+ "'invalid_job' job needs 'non-existent' job, but it was not added to the pipeline")
end
end
end
diff --git a/spec/lib/gitlab/ci/reports/test_failure_history_spec.rb b/spec/lib/gitlab/ci/reports/test_failure_history_spec.rb
index 8df34eddffd..831bc5e9f37 100644
--- a/spec/lib/gitlab/ci/reports/test_failure_history_spec.rb
+++ b/spec/lib/gitlab/ci/reports/test_failure_history_spec.rb
@@ -28,18 +28,5 @@ RSpec.describe Gitlab::Ci::Reports::TestFailureHistory, :aggregate_failures do
expect(failed_rspec.recent_failures).to eq(count: 2, base_branch: 'master')
expect(failed_java.recent_failures).to eq(count: 1, base_branch: 'master')
end
-
- context 'when feature flag is disabled' do
- before do
- stub_feature_flags(test_failure_history: false)
- end
-
- it 'does not set recent failures' do
- load_history
-
- expect(failed_rspec.recent_failures).to be_nil
- expect(failed_java.recent_failures).to be_nil
- end
- end
end
end
diff --git a/spec/lib/gitlab/ci/status/group/factory_spec.rb b/spec/lib/gitlab/ci/status/group/factory_spec.rb
index 6267b26aa78..c67c7ff8271 100644
--- a/spec/lib/gitlab/ci/status/group/factory_spec.rb
+++ b/spec/lib/gitlab/ci/status/group/factory_spec.rb
@@ -12,4 +12,9 @@ RSpec.describe Gitlab::Ci::Status::Group::Factory do
expect(described_class.common_helpers)
.to eq Gitlab::Ci::Status::Group::Common
end
+
+ it 'exposes extended statuses' do
+ expect(described_class.extended_statuses)
+ .to eq([[Gitlab::Ci::Status::SuccessWarning]])
+ end
end
diff --git a/spec/lib/gitlab/ci/syntax_templates_spec.rb b/spec/lib/gitlab/ci/syntax_templates_spec.rb
new file mode 100644
index 00000000000..ce3169e17ec
--- /dev/null
+++ b/spec/lib/gitlab/ci/syntax_templates_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'ci/syntax_templates' do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { create(:user) }
+ let(:lint) { Gitlab::Ci::Lint.new(project: project, current_user: user) }
+
+ before do
+ project.add_developer(user)
+ end
+
+ subject(:lint_result) { lint.validate(content) }
+
+ Dir.glob('lib/gitlab/ci/syntax_templates/**/*.yml').each do |template|
+ describe template do
+ let(:content) { File.read(template) }
+
+ it 'validates the template' do
+ expect(lint_result).to be_valid, "got errors: #{lint_result.errors.join(', ')}"
+ end
+ end
+ end
+end
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
new file mode 100644
index 00000000000..6bc8e261640
--- /dev/null
+++ b/spec/lib/gitlab/ci/templates/5_minute_production_app_ci_yaml_spec.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe '5-Minute-Production-App.gitlab-ci.yml' do
+ subject(:template) { Gitlab::Template::GitlabCiYmlTemplate.find('5-Minute-Production-App') }
+
+ describe 'the created pipeline' do
+ let_it_be(:project) { create(:project, :auto_devops, :custom_repo, files: { 'README.md' => '' }) }
+
+ let(:user) { project.owner }
+ let(:default_branch) { 'master' }
+ let(:pipeline_branch) { default_branch }
+ let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
+ let(:pipeline) { service.execute!(:push) }
+ let(:build_names) { pipeline.builds.pluck(:name) }
+
+ before do
+ stub_ci_pipeline_yaml_file(template.content)
+ end
+
+ it 'creates only build job' do
+ expect(build_names).to match_array('build')
+ end
+
+ context 'when AWS variables are set' do
+ before do
+ create(:ci_variable, project: project, key: 'AWS_ACCESS_KEY_ID', value: 'AKIAIOSFODNN7EXAMPLE')
+ create(:ci_variable, project: project, key: 'AWS_SECRET_ACCESS_KEY', value: 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY')
+ create(:ci_variable, project: project, key: 'AWS_DEFAULT_REGION', value: 'us-west-2')
+ end
+
+ it 'creates all jobs' do
+ expect(build_names).to match_array(%w(build terraform_apply deploy terraform_destroy))
+ end
+
+ context 'pipeline branch is protected' do
+ before do
+ create(:protected_branch, project: project, name: pipeline_branch)
+ project.reload
+ end
+
+ it 'does not create a destroy job' do
+ expect(build_names).to match_array(%w(build terraform_apply deploy))
+ end
+ end
+ end
+ end
+end
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 4be92e8608e..653b3be0b2a 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
@@ -6,10 +6,10 @@ RSpec.describe 'Deploy-ECS.gitlab-ci.yml' do
subject(:template) { Gitlab::Template::GitlabCiYmlTemplate.find('AWS/Deploy-ECS') }
describe 'the created pipeline' do
- let_it_be(:user) { create(:admin) }
let(:default_branch) { 'master' }
let(:pipeline_branch) { default_branch }
let(:project) { create(:project, :auto_devops, :custom_repo, files: { 'README.md' => '' }) }
+ let(:user) { project.owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
let(:pipeline) { service.execute!(:push) }
let(:build_names) { pipeline.builds.pluck(:name) }
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 4f8faa5ddb1..1f278048ad5 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
@@ -6,8 +6,8 @@ RSpec.describe 'Jobs/Build.gitlab-ci.yml' do
subject(:template) { Gitlab::Template::GitlabCiYmlTemplate.find('Jobs/Build') }
describe 'the created pipeline' do
- let_it_be(:user) { create(:admin) }
let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { project.owner }
let(:default_branch) { 'master' }
let(:pipeline_ref) { default_branch }
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 e685ad3b46e..0a76de82421 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
@@ -6,8 +6,8 @@ RSpec.describe 'Jobs/Code-Quality.gitlab-ci.yml' do
subject(:template) { Gitlab::Template::GitlabCiYmlTemplate.find('Jobs/Code-Quality') }
describe 'the created pipeline' do
- let_it_be(:user) { create(:admin) }
let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { project.owner }
let(:default_branch) { 'master' }
let(:pipeline_ref) { default_branch }
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 ea9bd5bd02c..25c88c161ea 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
@@ -27,8 +27,8 @@ RSpec.describe 'Jobs/Deploy.gitlab-ci.yml' do
end
describe 'the created pipeline' do
- let(:user) { create(:admin) }
let(:project) { create(:project, :repository) }
+ let(:user) { project.owner }
let(:default_branch) { 'master' }
let(:pipeline_ref) { default_branch }
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 f475785be98..b64959a9917 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
@@ -6,8 +6,8 @@ RSpec.describe 'Jobs/Test.gitlab-ci.yml' do
subject(:template) { Gitlab::Template::GitlabCiYmlTemplate.find('Jobs/Test') }
describe 'the created pipeline' do
- let_it_be(:user) { create(:admin) }
let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { project.owner }
let(:default_branch) { 'master' }
let(:pipeline_ref) { default_branch }
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 8df739d9245..0811c07e896 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
@@ -6,10 +6,10 @@ RSpec.describe 'Terraform/Base.latest.gitlab-ci.yml' do
subject(:template) { Gitlab::Template::GitlabCiYmlTemplate.find('Terraform/Base.latest') }
describe 'the created pipeline' do
- let(:user) { create(:admin) }
let(:default_branch) { 'master' }
let(:pipeline_branch) { default_branch }
let(:project) { create(:project, :custom_repo, files: { 'README.md' => '' }) }
+ let(:user) { project.owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
let(:pipeline) { service.execute!(:push) }
let(:build_names) { pipeline.builds.pluck(:name) }
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 9711df55226..03fa45fe0a1 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
@@ -19,8 +19,8 @@ RSpec.describe 'Verify/Load-Performance-Testing.gitlab-ci.yml' do
end
describe 'the created pipeline' do
- let(:user) { create(:admin) }
let(:project) { create(:project, :repository) }
+ let(:user) { project.owner }
let(:default_branch) { 'master' }
let(:pipeline_ref) { default_branch }
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 793df55f45d..f9d6fe24e70 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
@@ -6,10 +6,10 @@ RSpec.describe 'Auto-DevOps.gitlab-ci.yml' do
subject(:template) { Gitlab::Template::GitlabCiYmlTemplate.find('Auto-DevOps') }
describe 'the created pipeline' do
- let(:user) { create(:admin) }
let(:default_branch) { 'master' }
let(:pipeline_branch) { default_branch }
let(:project) { create(:project, :auto_devops, :custom_repo, files: { 'README.md' => '' }) }
+ let(:user) { project.owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
let(:pipeline) { service.execute!(:push) }
let(:build_names) { pipeline.builds.pluck(:name) }
@@ -232,8 +232,8 @@ RSpec.describe 'Auto-DevOps.gitlab-ci.yml' do
end
with_them do
- let(:user) { create(:admin) }
let(:project) { create(:project, :custom_repo, files: files) }
+ let(:user) { project.owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: 'master' ) }
let(:pipeline) { service.execute(:push) }
let(:build_names) { pipeline.builds.pluck(:name) }
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
new file mode 100644
index 00000000000..4e5fe622648
--- /dev/null
+++ b/spec/lib/gitlab/ci/templates/flutter_gitlab_ci_yaml_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Flutter.gitlab-ci.yml' do
+ subject(:template) { Gitlab::Template::GitlabCiYmlTemplate.find('Flutter') }
+
+ describe 'the created pipeline' do
+ let(:pipeline_branch) { 'master' }
+ let(:project) { create(:project, :custom_repo, files: { 'README.md' => '' }) }
+ let(:user) { project.owner }
+ let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
+ let(:pipeline) { service.execute!(:push) }
+ let(:build_names) { pipeline.builds.pluck(:name) }
+
+ before do
+ stub_ci_pipeline_yaml_file(template.content)
+ allow(Ci::BuildScheduleWorker).to receive(:perform).and_return(true)
+ end
+
+ it 'creates test and code_quality jobs' do
+ expect(build_names).to include('test', 'code_quality')
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/templates/npm_spec.rb b/spec/lib/gitlab/ci/templates/npm_spec.rb
index 1f8e32ce019..b10e2b0e057 100644
--- a/spec/lib/gitlab/ci/templates/npm_spec.rb
+++ b/spec/lib/gitlab/ci/templates/npm_spec.rb
@@ -6,11 +6,10 @@ RSpec.describe 'npm.latest.gitlab-ci.yml' do
subject(:template) { Gitlab::Template::GitlabCiYmlTemplate.find('npm.latest') }
describe 'the created pipeline' do
- let_it_be(:user) { create(:admin) }
-
let(:repo_files) { { 'package.json' => '{}', 'README.md' => '' } }
let(:modified_files) { %w[package.json] }
let(:project) { create(:project, :custom_repo, files: repo_files) }
+ let(:user) { project.owner }
let(:pipeline_branch) { project.default_branch }
let(:pipeline_tag) { 'v1.2.1' }
let(:pipeline_ref) { pipeline_branch }
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 5eec021b9d7..4377f155d34 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
@@ -10,11 +10,10 @@ RSpec.describe 'Terraform.latest.gitlab-ci.yml' do
subject(:template) { Gitlab::Template::GitlabCiYmlTemplate.find('Terraform.latest') }
describe 'the created pipeline' do
- let_it_be(:user) { create(:admin) }
-
let(:default_branch) { 'master' }
let(:pipeline_branch) { default_branch }
let(:project) { create(:project, :custom_repo, files: { 'README.md' => '' }) }
+ let(:user) { project.owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
let(:pipeline) { service.execute!(:push) }
let(:build_names) { pipeline.builds.pluck(:name) }
diff --git a/spec/lib/gitlab/ci/variables/collection/sorted_spec.rb b/spec/lib/gitlab/ci/variables/collection/sorted_spec.rb
new file mode 100644
index 00000000000..d85bf29f77f
--- /dev/null
+++ b/spec/lib/gitlab/ci/variables/collection/sorted_spec.rb
@@ -0,0 +1,251 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Variables::Collection::Sorted do
+ describe '#errors' do
+ context 'when FF :variable_inside_variable is disabled' do
+ before do
+ stub_feature_flags(variable_inside_variable: false)
+ end
+
+ context 'table tests' do
+ using RSpec::Parameterized::TableSyntax
+
+ where do
+ {
+ "empty array": {
+ variables: []
+ },
+ "simple expansions": {
+ variables: [
+ { key: 'variable', value: 'value' },
+ { key: 'variable2', value: 'result' },
+ { key: 'variable3', value: 'key$variable$variable2' }
+ ]
+ },
+ "complex expansion": {
+ variables: [
+ { key: 'variable', value: 'value' },
+ { key: 'variable2', value: 'key${variable}' }
+ ]
+ },
+ "complex expansions with missing variable for Windows": {
+ variables: [
+ { key: 'variable', value: 'value' },
+ { key: 'variable3', value: 'key%variable%%variable2%' }
+ ]
+ },
+ "out-of-order variable reference": {
+ variables: [
+ { key: 'variable2', value: 'key${variable}' },
+ { key: 'variable', value: 'value' }
+ ]
+ },
+ "array with cyclic dependency": {
+ variables: [
+ { key: 'variable', value: '$variable2' },
+ { key: 'variable2', value: '$variable3' },
+ { key: 'variable3', value: 'key$variable$variable2' }
+ ]
+ }
+ }
+ end
+
+ with_them do
+ subject { Gitlab::Ci::Variables::Collection::Sorted.new(variables) }
+
+ it 'does not report error' do
+ expect(subject.errors).to eq(nil)
+ end
+
+ it 'valid? reports true' do
+ expect(subject.valid?).to eq(true)
+ end
+ end
+ end
+ end
+
+ context 'when FF :variable_inside_variable is enabled' do
+ before do
+ stub_feature_flags(variable_inside_variable: true)
+ end
+
+ context 'table tests' do
+ using RSpec::Parameterized::TableSyntax
+
+ where do
+ {
+ "empty array": {
+ variables: [],
+ validation_result: nil
+ },
+ "simple expansions": {
+ variables: [
+ { key: 'variable', value: 'value' },
+ { key: 'variable2', value: 'result' },
+ { key: 'variable3', value: 'key$variable$variable2' }
+ ],
+ validation_result: nil
+ },
+ "cyclic dependency": {
+ variables: [
+ { key: 'variable', value: '$variable2' },
+ { key: 'variable2', value: '$variable3' },
+ { key: 'variable3', value: 'key$variable$variable2' }
+ ],
+ validation_result: 'circular variable reference detected: ["variable", "variable2", "variable3"]'
+ }
+ }
+ end
+
+ with_them do
+ subject { Gitlab::Ci::Variables::Collection::Sorted.new(variables) }
+
+ it 'errors matches expected validation result' do
+ expect(subject.errors).to eq(validation_result)
+ end
+
+ it 'valid? matches expected validation result' do
+ expect(subject.valid?).to eq(validation_result.nil?)
+ end
+ end
+ end
+ end
+ end
+
+ describe '#sort' do
+ context 'when FF :variable_inside_variable is disabled' do
+ before do
+ stub_feature_flags(variable_inside_variable: false)
+ end
+
+ context 'table tests' do
+ using RSpec::Parameterized::TableSyntax
+
+ where do
+ {
+ "empty array": {
+ variables: []
+ },
+ "simple expansions": {
+ variables: [
+ { key: 'variable', value: 'value' },
+ { key: 'variable2', value: 'result' },
+ { key: 'variable3', value: 'key$variable$variable2' }
+ ]
+ },
+ "complex expansion": {
+ variables: [
+ { key: 'variable', value: 'value' },
+ { key: 'variable2', value: 'key${variable}' }
+ ]
+ },
+ "complex expansions with missing variable for Windows": {
+ variables: [
+ { key: 'variable', value: 'value' },
+ { key: 'variable3', value: 'key%variable%%variable2%' }
+ ]
+ },
+ "out-of-order variable reference": {
+ variables: [
+ { key: 'variable2', value: 'key${variable}' },
+ { key: 'variable', value: 'value' }
+ ]
+ },
+ "array with cyclic dependency": {
+ variables: [
+ { key: 'variable', value: '$variable2' },
+ { key: 'variable2', value: '$variable3' },
+ { key: 'variable3', value: 'key$variable$variable2' }
+ ]
+ }
+ }
+ end
+
+ with_them do
+ subject { Gitlab::Ci::Variables::Collection::Sorted.new(variables) }
+
+ it 'does not expand variables' do
+ expect(subject.sort).to eq(variables)
+ end
+ end
+ end
+ end
+
+ context 'when FF :variable_inside_variable is enabled' do
+ before do
+ stub_licensed_features(group_saml_group_sync: true)
+ stub_feature_flags(saml_group_links: true)
+ stub_feature_flags(variable_inside_variable: true)
+ end
+
+ context 'table tests' do
+ using RSpec::Parameterized::TableSyntax
+
+ where do
+ {
+ "empty array": {
+ variables: [],
+ result: []
+ },
+ "simple expansions, no reordering needed": {
+ variables: [
+ { key: 'variable', value: 'value' },
+ { key: 'variable2', value: 'result' },
+ { key: 'variable3', value: 'key$variable$variable2' }
+ ],
+ result: %w[variable variable2 variable3]
+ },
+ "complex expansion, reordering needed": {
+ variables: [
+ { key: 'variable2', value: 'key${variable}' },
+ { key: 'variable', value: 'value' }
+ ],
+ result: %w[variable variable2]
+ },
+ "unused variables": {
+ variables: [
+ { key: 'variable', value: 'value' },
+ { key: 'variable4', value: 'key$variable$variable3' },
+ { key: 'variable2', value: 'result2' },
+ { key: 'variable3', value: 'result3' }
+ ],
+ result: %w[variable variable3 variable4 variable2]
+ },
+ "missing variable": {
+ variables: [
+ { key: 'variable2', value: 'key$variable' }
+ ],
+ result: %w[variable2]
+ },
+ "complex expansions with missing variable": {
+ variables: [
+ { key: 'variable4', value: 'key${variable}${variable2}${variable3}' },
+ { key: 'variable', value: 'value' },
+ { key: 'variable3', value: 'value3' }
+ ],
+ result: %w[variable variable3 variable4]
+ },
+ "cyclic dependency causes original array to be returned": {
+ variables: [
+ { key: 'variable2', value: '$variable3' },
+ { key: 'variable3', value: 'key$variable$variable2' },
+ { key: 'variable', value: '$variable2' }
+ ],
+ result: %w[variable2 variable3 variable]
+ }
+ }
+ end
+
+ with_them do
+ subject { Gitlab::Ci::Variables::Collection::Sorted.new(variables) }
+
+ it 'sort returns correctly sorted variables' do
+ expect(subject.sort.map { |var| var[:key] }).to eq(result)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/yaml_processor_spec.rb b/spec/lib/gitlab/ci/yaml_processor_spec.rb
index 5ad1b3dd241..9498453852a 100644
--- a/spec/lib/gitlab/ci/yaml_processor_spec.rb
+++ b/spec/lib/gitlab/ci/yaml_processor_spec.rb
@@ -2711,40 +2711,6 @@ module Gitlab
end
end
- describe "#validation_message" do
- subject { Gitlab::Ci::YamlProcessor.validation_message(content) }
-
- context "when the YAML could not be parsed" do
- let(:content) { YAML.dump("invalid: yaml: test") }
-
- it { is_expected.to eq "Invalid configuration format" }
- end
-
- context "when the tags parameter is invalid" do
- let(:content) { YAML.dump({ rspec: { script: "test", tags: "mysql" } }) }
-
- it { is_expected.to eq "jobs:rspec:tags config should be an array of strings" }
- end
-
- context "when YAML content is empty" do
- let(:content) { '' }
-
- it { is_expected.to eq "Please provide content of .gitlab-ci.yml" }
- end
-
- context 'when the YAML contains an unknown alias' do
- let(:content) { 'steps: *bad_alias' }
-
- it { is_expected.to eq "Unknown alias: bad_alias" }
- end
-
- context "when the YAML is valid" do
- let(:content) { File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml')) }
-
- it { is_expected.to be_nil }
- end
- end
-
describe '#execute' do
subject { Gitlab::Ci::YamlProcessor.new(content).execute }