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/context/build_spec.rb22
-rw-r--r--spec/lib/gitlab/ci/build/context/global_spec.rb22
-rw-r--r--spec/lib/gitlab/ci/build/policy/variables_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/build/rules/rule/clause/changes_spec.rb8
-rw-r--r--spec/lib/gitlab/ci/build/rules/rule_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/build/rules_spec.rb6
-rw-r--r--spec/lib/gitlab/ci/config/entry/bridge_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/config/entry/job_spec.rb29
-rw-r--r--spec/lib/gitlab/ci/config/entry/processable_spec.rb29
-rw-r--r--spec/lib/gitlab/ci/config/entry/tags_spec.rb22
-rw-r--r--spec/lib/gitlab/ci/config/external/context_spec.rb18
-rw-r--r--spec/lib/gitlab/ci/config/external/processor_spec.rb13
-rw-r--r--spec/lib/gitlab/ci/config/external/rules_spec.rb6
-rw-r--r--spec/lib/gitlab/ci/parsers/terraform/tfplan_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/create_deployments_spec.rb97
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/create_spec.rb70
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/ensure_environments_spec.rb94
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/ensure_resource_groups_spec.rb85
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb18
-rw-r--r--spec/lib/gitlab/ci/pipeline/expression/lexeme/variable_spec.rb25
-rw-r--r--spec/lib/gitlab/ci/pipeline/expression/statement_spec.rb1
-rw-r--r--spec/lib/gitlab/ci/pipeline/logger_spec.rb132
-rw-r--r--spec/lib/gitlab/ci/pipeline/seed/build_spec.rb83
-rw-r--r--spec/lib/gitlab/ci/status/bridge/common_spec.rb10
-rw-r--r--spec/lib/gitlab/ci/tags/bulk_insert_spec.rb39
-rw-r--r--spec/lib/gitlab/ci/variables/builder_spec.rb10
-rw-r--r--spec/lib/gitlab/ci/yaml_processor_spec.rb6
27 files changed, 727 insertions, 130 deletions
diff --git a/spec/lib/gitlab/ci/build/context/build_spec.rb b/spec/lib/gitlab/ci/build/context/build_spec.rb
index 46447231424..7f862a3b80a 100644
--- a/spec/lib/gitlab/ci/build/context/build_spec.rb
+++ b/spec/lib/gitlab/ci/build/context/build_spec.rb
@@ -8,11 +8,7 @@ RSpec.describe Gitlab::Ci::Build::Context::Build do
let(:context) { described_class.new(pipeline, seed_attributes) }
- describe '#variables' do
- subject { context.variables.to_hash }
-
- it { expect(context.variables).to be_instance_of(Gitlab::Ci::Variables::Collection) }
-
+ shared_examples 'variables collection' do
it { is_expected.to include('CI_COMMIT_REF_NAME' => 'master') }
it { is_expected.to include('CI_PIPELINE_IID' => pipeline.iid.to_s) }
it { is_expected.to include('CI_PROJECT_PATH' => pipeline.project.full_path) }
@@ -27,4 +23,20 @@ RSpec.describe Gitlab::Ci::Build::Context::Build do
it { is_expected.to include('CI_PROJECT_PATH' => pipeline.project.full_path) }
end
end
+
+ describe '#variables' do
+ subject { context.variables.to_hash }
+
+ it { expect(context.variables).to be_instance_of(Gitlab::Ci::Variables::Collection) }
+
+ it_behaves_like 'variables collection'
+ end
+
+ describe '#variables_hash' do
+ subject { context.variables_hash }
+
+ it { expect(context.variables_hash).to be_instance_of(ActiveSupport::HashWithIndifferentAccess) }
+
+ it_behaves_like 'variables collection'
+ end
end
diff --git a/spec/lib/gitlab/ci/build/context/global_spec.rb b/spec/lib/gitlab/ci/build/context/global_spec.rb
index 61f2b90426d..d4141eb8389 100644
--- a/spec/lib/gitlab/ci/build/context/global_spec.rb
+++ b/spec/lib/gitlab/ci/build/context/global_spec.rb
@@ -8,11 +8,7 @@ RSpec.describe Gitlab::Ci::Build::Context::Global do
let(:context) { described_class.new(pipeline, yaml_variables: yaml_variables) }
- describe '#variables' do
- subject { context.variables.to_hash }
-
- it { expect(context.variables).to be_instance_of(Gitlab::Ci::Variables::Collection) }
-
+ shared_examples 'variables collection' do
it { is_expected.to include('CI_COMMIT_REF_NAME' => 'master') }
it { is_expected.to include('CI_PIPELINE_IID' => pipeline.iid.to_s) }
it { is_expected.to include('CI_PROJECT_PATH' => pipeline.project.full_path) }
@@ -26,4 +22,20 @@ RSpec.describe Gitlab::Ci::Build::Context::Global do
it { is_expected.to include('SUPPORTED' => 'parsed') }
end
end
+
+ describe '#variables' do
+ subject { context.variables.to_hash }
+
+ it { expect(context.variables).to be_instance_of(Gitlab::Ci::Variables::Collection) }
+
+ it_behaves_like 'variables collection'
+ end
+
+ describe '#variables_hash' do
+ subject { context.variables_hash }
+
+ it { is_expected.to be_instance_of(ActiveSupport::HashWithIndifferentAccess) }
+
+ it_behaves_like 'variables collection'
+ end
end
diff --git a/spec/lib/gitlab/ci/build/policy/variables_spec.rb b/spec/lib/gitlab/ci/build/policy/variables_spec.rb
index 6c8c968dc0c..436ad59bdf7 100644
--- a/spec/lib/gitlab/ci/build/policy/variables_spec.rb
+++ b/spec/lib/gitlab/ci/build/policy/variables_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe Gitlab::Ci::Build::Policy::Variables do
let(:seed) do
double('build seed',
to_resource: ci_build,
- variables: ci_build.scoped_variables
+ variables_hash: ci_build.scoped_variables.to_hash
)
end
@@ -91,7 +91,7 @@ RSpec.describe Gitlab::Ci::Build::Policy::Variables do
let(:seed) do
double('bridge seed',
to_resource: bridge,
- variables: ci_build.scoped_variables
+ variables_hash: ci_build.scoped_variables.to_hash
)
end
diff --git a/spec/lib/gitlab/ci/build/rules/rule/clause/changes_spec.rb b/spec/lib/gitlab/ci/build/rules/rule/clause/changes_spec.rb
index d20ea6c9202..532c83f6768 100644
--- a/spec/lib/gitlab/ci/build/rules/rule/clause/changes_spec.rb
+++ b/spec/lib/gitlab/ci/build/rules/rule/clause/changes_spec.rb
@@ -33,12 +33,12 @@ RSpec.describe Gitlab::Ci::Build::Rules::Rule::Clause::Changes do
end
context 'when context has the specified variables' do
- let(:variables) do
- [{ key: "HELM_DIR", value: "helm", public: true }]
+ let(:variables_hash) do
+ { 'HELM_DIR' => 'helm' }
end
before do
- allow(context).to receive(:variables).and_return(variables)
+ allow(context).to receive(:variables_hash).and_return(variables_hash)
end
it { is_expected.to be_truthy }
@@ -49,7 +49,7 @@ RSpec.describe Gitlab::Ci::Build::Rules::Rule::Clause::Changes do
let(:modified_paths) { ['path/with/$in/it/file.txt'] }
before do
- allow(context).to receive(:variables).and_return([])
+ allow(context).to receive(:variables_hash).and_return({})
end
it { is_expected.to be_truthy }
diff --git a/spec/lib/gitlab/ci/build/rules/rule_spec.rb b/spec/lib/gitlab/ci/build/rules/rule_spec.rb
index 6f3c9278677..f905e229415 100644
--- a/spec/lib/gitlab/ci/build/rules/rule_spec.rb
+++ b/spec/lib/gitlab/ci/build/rules/rule_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Gitlab::Ci::Build::Rules::Rule do
let(:seed) do
double('build seed',
to_resource: ci_build,
- variables: ci_build.scoped_variables
+ variables_hash: ci_build.scoped_variables.to_hash
)
end
diff --git a/spec/lib/gitlab/ci/build/rules_spec.rb b/spec/lib/gitlab/ci/build/rules_spec.rb
index 1d5bdf30278..37bfdca4d1d 100644
--- a/spec/lib/gitlab/ci/build/rules_spec.rb
+++ b/spec/lib/gitlab/ci/build/rules_spec.rb
@@ -3,13 +3,13 @@
require 'spec_helper'
RSpec.describe Gitlab::Ci::Build::Rules do
- let(:pipeline) { create(:ci_pipeline) }
- let(:ci_build) { build(:ci_build, pipeline: pipeline) }
+ let_it_be(:pipeline) { create(:ci_pipeline) }
+ let_it_be(:ci_build) { build(:ci_build, pipeline: pipeline) }
let(:seed) do
double('build seed',
to_resource: ci_build,
- variables: ci_build.scoped_variables
+ variables_hash: ci_build.scoped_variables.to_hash
)
end
diff --git a/spec/lib/gitlab/ci/config/entry/bridge_spec.rb b/spec/lib/gitlab/ci/config/entry/bridge_spec.rb
index 6c9c8fa5df5..62feed3dda0 100644
--- a/spec/lib/gitlab/ci/config/entry/bridge_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/bridge_spec.rb
@@ -163,7 +163,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Bridge do
})
end
- it { is_expected.not_to be_valid }
+ it { is_expected.to be_valid }
end
context 'when bridge configuration uses rules with only' do
diff --git a/spec/lib/gitlab/ci/config/entry/job_spec.rb b/spec/lib/gitlab/ci/config/entry/job_spec.rb
index 0bb26babfc0..885f3eaff79 100644
--- a/spec/lib/gitlab/ci/config/entry/job_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/job_spec.rb
@@ -118,6 +118,20 @@ RSpec.describe Gitlab::Ci::Config::Entry::Job do
end
end
+ context 'when config uses both "when:" and "rules:"' do
+ let(:config) do
+ {
+ script: 'echo',
+ when: 'on_failure',
+ rules: [{ if: '$VARIABLE', when: 'on_success' }]
+ }
+ end
+
+ it 'is valid' do
+ expect(entry).to be_valid
+ end
+ end
+
context 'when delayed job' do
context 'when start_in is specified' do
let(:config) { { script: 'echo', when: 'delayed', start_in: '1 week' } }
@@ -268,21 +282,6 @@ RSpec.describe Gitlab::Ci::Config::Entry::Job do
end
end
- context 'when it uses both "when:" and "rules:"' do
- let(:config) do
- {
- script: 'echo',
- when: 'on_failure',
- rules: [{ if: '$VARIABLE', when: 'on_success' }]
- }
- end
-
- it 'returns an error about when: being combined with rules' do
- expect(entry).not_to be_valid
- expect(entry.errors).to include 'job config key may not be used with `rules`: when'
- end
- end
-
context 'when delayed job' do
context 'when start_in is specified' do
let(:config) { { script: 'echo', when: 'delayed', start_in: '1 week' } }
diff --git a/spec/lib/gitlab/ci/config/entry/processable_spec.rb b/spec/lib/gitlab/ci/config/entry/processable_spec.rb
index c9c28e2eb8b..5b9337ede34 100644
--- a/spec/lib/gitlab/ci/config/entry/processable_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/processable_spec.rb
@@ -33,6 +33,20 @@ RSpec.describe Gitlab::Ci::Config::Entry::Processable do
end
end
+ context 'when config uses both "when:" and "rules:"' do
+ let(:config) do
+ {
+ script: 'echo',
+ when: 'on_failure',
+ rules: [{ if: '$VARIABLE', when: 'on_success' }]
+ }
+ end
+
+ it 'is valid' do
+ expect(entry).to be_valid
+ end
+ end
+
context 'when job name is more than 255' do
let(:entry) { node_class.new(config, name: ('a' * 256).to_sym) }
@@ -90,21 +104,6 @@ RSpec.describe Gitlab::Ci::Config::Entry::Processable do
end
end
- context 'when it uses both "when:" and "rules:"' do
- let(:config) do
- {
- script: 'echo',
- when: 'on_failure',
- rules: [{ if: '$VARIABLE', when: 'on_success' }]
- }
- end
-
- it 'returns an error about when: being combined with rules' do
- expect(entry).not_to be_valid
- expect(entry.errors).to include 'job config key may not be used with `rules`: when'
- end
- end
-
context 'when only: is used with rules:' do
let(:config) { { only: ['merge_requests'], rules: [{ if: '$THIS' }] } }
diff --git a/spec/lib/gitlab/ci/config/entry/tags_spec.rb b/spec/lib/gitlab/ci/config/entry/tags_spec.rb
index 79317de373b..e05d4ae52b2 100644
--- a/spec/lib/gitlab/ci/config/entry/tags_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/tags_spec.rb
@@ -36,25 +36,9 @@ RSpec.describe Gitlab::Ci::Config::Entry::Tags do
context 'when tags limit is reached' do
let(:config) { Array.new(50) {|i| "tag-#{i}" } }
- context 'when ci_build_tags_limit is enabled' do
- before do
- stub_feature_flags(ci_build_tags_limit: true)
- end
-
- it 'reports error' do
- expect(entry.errors)
- .to include "tags config must be less than the limit of #{described_class::TAGS_LIMIT} tags"
- end
- end
-
- context 'when ci_build_tags_limit is disabled' do
- before do
- stub_feature_flags(ci_build_tags_limit: false)
- end
-
- it 'does not report an error' do
- expect(entry.errors).to be_empty
- end
+ it 'reports error' do
+ expect(entry.errors)
+ .to include "tags config must be less than the limit of #{described_class::TAGS_LIMIT} tags"
end
end
end
diff --git a/spec/lib/gitlab/ci/config/external/context_spec.rb b/spec/lib/gitlab/ci/config/external/context_spec.rb
index 4b9adf7e87b..800c563cd0b 100644
--- a/spec/lib/gitlab/ci/config/external/context_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/context_spec.rb
@@ -6,7 +6,8 @@ RSpec.describe Gitlab::Ci::Config::External::Context do
let(:project) { double('Project') }
let(:user) { double('User') }
let(:sha) { '12345' }
- let(:attributes) { { project: project, user: user, sha: sha } }
+ let(:variables) { Gitlab::Ci::Variables::Collection.new([{ 'key' => 'a', 'value' => 'b' }]) }
+ let(:attributes) { { project: project, user: user, sha: sha, variables: variables } }
subject(:subject) { described_class.new(**attributes) }
@@ -15,6 +16,9 @@ RSpec.describe Gitlab::Ci::Config::External::Context do
it { is_expected.to have_attributes(**attributes) }
it { expect(subject.expandset).to eq(Set.new) }
it { expect(subject.execution_deadline).to eq(0) }
+ it { expect(subject.variables).to be_instance_of(Gitlab::Ci::Variables::Collection) }
+ it { expect(subject.variables_hash).to be_instance_of(ActiveSupport::HashWithIndifferentAccess) }
+ it { expect(subject.variables_hash).to include('a' => 'b') }
end
context 'without values' do
@@ -23,6 +27,8 @@ RSpec.describe Gitlab::Ci::Config::External::Context do
it { is_expected.to have_attributes(**attributes) }
it { expect(subject.expandset).to eq(Set.new) }
it { expect(subject.execution_deadline).to eq(0) }
+ it { expect(subject.variables).to be_instance_of(Gitlab::Ci::Variables::Collection) }
+ it { expect(subject.variables_hash).to be_instance_of(ActiveSupport::HashWithIndifferentAccess) }
end
end
@@ -94,6 +100,15 @@ RSpec.describe Gitlab::Ci::Config::External::Context do
end
describe '#mutate' do
+ let(:attributes) do
+ {
+ project: project,
+ user: user,
+ sha: sha,
+ logger: double('logger')
+ }
+ end
+
shared_examples 'a mutated context' do
let(:mutated) { subject.mutate(new_attributes) }
@@ -107,6 +122,7 @@ RSpec.describe Gitlab::Ci::Config::External::Context do
it { expect(mutated).to have_attributes(new_attributes) }
it { expect(mutated.expandset).to eq(subject.expandset) }
it { expect(mutated.execution_deadline).to eq(mutated.execution_deadline) }
+ it { expect(mutated.logger).to eq(mutated.logger) }
end
context 'with attributes' do
diff --git a/spec/lib/gitlab/ci/config/external/processor_spec.rb b/spec/lib/gitlab/ci/config/external/processor_spec.rb
index 2e9e6f95071..97bd74721f2 100644
--- a/spec/lib/gitlab/ci/config/external/processor_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/processor_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Gitlab::Ci::Config::External::Processor do
include StubRequests
let_it_be(:project) { create(:project, :repository) }
- let_it_be(:another_project) { create(:project, :repository) }
+ let_it_be_with_reload(:another_project) { create(:project, :repository) }
let_it_be(:user) { create(:user) }
let(:sha) { '12345' }
@@ -251,6 +251,17 @@ RSpec.describe Gitlab::Ci::Config::External::Processor do
it 'properly expands all includes' do
is_expected.to include(:my_build, :remote_build, :rspec)
end
+
+ it 'propagates the pipeline logger' do
+ processor.perform
+
+ process_obs_count = processor
+ .logger
+ .observations_hash
+ .dig('config_mapper_process_duration_s', 'count')
+
+ expect(process_obs_count).to eq(3)
+ end
end
context 'when user is reporter of another project' do
diff --git a/spec/lib/gitlab/ci/config/external/rules_spec.rb b/spec/lib/gitlab/ci/config/external/rules_spec.rb
index 1e42cb30ae7..091bd3b07e6 100644
--- a/spec/lib/gitlab/ci/config/external/rules_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/rules_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe Gitlab::Ci::Config::External::Rules do
subject(:rules) { described_class.new(rule_hashes) }
describe '#evaluate' do
- let(:context) { double(variables: {}) }
+ let(:context) { double(variables_hash: {}) }
subject(:result) { rules.evaluate(context).pass? }
@@ -20,13 +20,13 @@ RSpec.describe Gitlab::Ci::Config::External::Rules do
let(:rule_hashes) { [{ if: '$MY_VAR == "hello"' }] }
context 'when the rule matches' do
- let(:context) { double(variables: { MY_VAR: 'hello' }) }
+ let(:context) { double(variables_hash: { 'MY_VAR' => 'hello' }) }
it { is_expected.to eq(true) }
end
context 'when the rule does not match' do
- let(:context) { double(variables: { MY_VAR: 'invalid' }) }
+ let(:context) { double(variables_hash: { 'MY_VAR' => 'invalid' }) }
it { is_expected.to eq(false) }
end
diff --git a/spec/lib/gitlab/ci/parsers/terraform/tfplan_spec.rb b/spec/lib/gitlab/ci/parsers/terraform/tfplan_spec.rb
index f487fccdab7..60b4e01f382 100644
--- a/spec/lib/gitlab/ci/parsers/terraform/tfplan_spec.rb
+++ b/spec/lib/gitlab/ci/parsers/terraform/tfplan_spec.rb
@@ -103,7 +103,7 @@ RSpec.describe Gitlab::Ci::Parsers::Terraform::Tfplan do
'create' => 0,
'update' => 1,
'delete' => 0,
- 'job_name' => artifact.job.options.dig(:artifacts, :name).to_s
+ 'job_name' => artifact.job.name
)
)
)
@@ -124,7 +124,7 @@ RSpec.describe Gitlab::Ci::Parsers::Terraform::Tfplan do
'create' => 0,
'update' => 1,
'delete' => 0,
- 'job_name' => artifact.job.options.dig(:artifacts, :name).to_s
+ 'job_name' => artifact.job.name
)
)
)
diff --git a/spec/lib/gitlab/ci/pipeline/chain/create_deployments_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/create_deployments_spec.rb
new file mode 100644
index 00000000000..28bc685286f
--- /dev/null
+++ b/spec/lib/gitlab/ci/pipeline/chain/create_deployments_spec.rb
@@ -0,0 +1,97 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Pipeline::Chain::CreateDeployments do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { create(:user) }
+
+ let(:stage) { build(:ci_stage_entity, project: project, statuses: [job]) }
+ let(:pipeline) { create(:ci_pipeline, project: project, stages: [stage]) }
+
+ 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 { step.perform! }
+
+ before do
+ job.pipeline = pipeline
+ end
+
+ context 'when a pipeline contains a deployment job' do
+ let!(:job) { build(:ci_build, :start_review_app, project: project) }
+ let!(:environment) { create(:environment, project: project, name: job.expanded_environment_name) }
+
+ it 'creates a deployment record' do
+ expect { subject }.to change { Deployment.count }.by(1)
+
+ job.reset
+ expect(job.deployment.project).to eq(job.project)
+ expect(job.deployment.ref).to eq(job.ref)
+ expect(job.deployment.sha).to eq(job.sha)
+ expect(job.deployment.deployable).to eq(job)
+ expect(job.deployment.deployable_type).to eq('CommitStatus')
+ expect(job.deployment.environment).to eq(job.persisted_environment)
+ end
+
+ context 'when creation failure occures' do
+ before do
+ allow_next_instance_of(Deployment) do |deployment|
+ allow(deployment).to receive(:save!) { raise ActiveRecord::RecordInvalid }
+ end
+ end
+
+ it 'trackes the exception' do
+ expect { subject }.to raise_error(described_class::DeploymentCreationError)
+
+ expect(Deployment.count).to eq(0)
+ end
+ end
+
+ context 'when the corresponding environment does not exist' do
+ let!(:environment) { }
+
+ it 'does not create a deployment record' do
+ expect { subject }.not_to change { Deployment.count }
+
+ expect(job.deployment).to be_nil
+ end
+ end
+
+ context 'when create_deployment_in_separate_transaction feature flag is disabled' do
+ before do
+ stub_feature_flags(create_deployment_in_separate_transaction: false)
+ end
+
+ it 'does not create a deployment record' do
+ expect { subject }.not_to change { Deployment.count }
+
+ expect(job.deployment).to be_nil
+ end
+ end
+ end
+
+ context 'when a pipeline contains a teardown job' do
+ let!(:job) { build(:ci_build, :stop_review_app, project: project) }
+ let!(:environment) { create(:environment, name: job.expanded_environment_name) }
+
+ it 'does not create a deployment record' do
+ expect { subject }.not_to change { Deployment.count }
+
+ expect(job.deployment).to be_nil
+ end
+ end
+
+ context 'when a pipeline does not contain a deployment job' do
+ let!(:job) { build(:ci_build, project: project) }
+
+ it 'does not create any deployments' do
+ expect { subject }.not_to change { Deployment.count }
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/create_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/create_spec.rb
index d60ecc80a6e..4206483b228 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/create_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/create_spec.rb
@@ -56,4 +56,74 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Create do
.to include /Failed to persist the pipeline/
end
end
+
+ context 'tags persistence' do
+ let(:stage) do
+ build(:ci_stage_entity, pipeline: pipeline)
+ end
+
+ let(:job) do
+ build(:ci_build, stage: stage, pipeline: pipeline, project: project)
+ end
+
+ let(:bridge) do
+ build(:ci_bridge, stage: stage, pipeline: pipeline, project: project)
+ end
+
+ before do
+ pipeline.stages = [stage]
+ stage.statuses = [job, bridge]
+ end
+
+ context 'without tags' do
+ it 'extracts an empty tag list' do
+ expect(CommitStatus)
+ .to receive(:bulk_insert_tags!)
+ .with(stage.statuses, {})
+ .and_call_original
+
+ step.perform!
+
+ expect(job.instance_variable_defined?(:@tag_list)).to be_falsey
+ expect(job).to be_persisted
+ expect(job.tag_list).to eq([])
+ end
+ end
+
+ context 'with tags' do
+ before do
+ job.tag_list = %w[tag1 tag2]
+ end
+
+ it 'bulk inserts tags' do
+ expect(CommitStatus)
+ .to receive(:bulk_insert_tags!)
+ .with(stage.statuses, { job.name => %w[tag1 tag2] })
+ .and_call_original
+
+ step.perform!
+
+ expect(job.instance_variable_defined?(:@tag_list)).to be_falsey
+ expect(job).to be_persisted
+ expect(job.tag_list).to match_array(%w[tag1 tag2])
+ end
+ end
+
+ context 'when the feature flag is disabled' do
+ before do
+ job.tag_list = %w[tag1 tag2]
+ stub_feature_flags(ci_bulk_insert_tags: false)
+ end
+
+ it 'follows the old code path' do
+ expect(CommitStatus).not_to receive(:bulk_insert_tags!)
+
+ step.perform!
+
+ expect(job.instance_variable_defined?(:@tag_list)).to be_truthy
+ expect(job).to be_persisted
+ expect(job.reload.tag_list).to match_array(%w[tag1 tag2])
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/ensure_environments_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/ensure_environments_spec.rb
new file mode 100644
index 00000000000..253928e1a19
--- /dev/null
+++ b/spec/lib/gitlab/ci/pipeline/chain/ensure_environments_spec.rb
@@ -0,0 +1,94 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Pipeline::Chain::EnsureEnvironments do
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+ let(:stage) { build(:ci_stage_entity, project: project, statuses: [job]) }
+ let(:pipeline) { build(:ci_pipeline, project: project, stages: [stage]) }
+
+ 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 { step.perform! }
+
+ before do
+ job.pipeline = pipeline
+ end
+
+ context 'when a pipeline contains a deployment job' do
+ let!(:job) { build(:ci_build, :start_review_app, project: project) }
+
+ it 'ensures environment existence for the job' do
+ expect { subject }.to change { Environment.count }.by(1)
+
+ expect(project.environments.find_by_name('review/master')).to be_present
+ expect(job.persisted_environment.name).to eq('review/master')
+ expect(job.metadata.expanded_environment_name).to eq('review/master')
+ end
+
+ context 'when an environment has already been existed' do
+ before do
+ create(:environment, project: project, name: 'review/master')
+ end
+
+ it 'ensures environment existence for the job' do
+ expect { subject }.not_to change { Environment.count }
+
+ expect(project.environments.find_by_name('review/master')).to be_present
+ expect(job.persisted_environment.name).to eq('review/master')
+ expect(job.metadata.expanded_environment_name).to eq('review/master')
+ end
+ end
+
+ context 'when an environment name contains an invalid character' do
+ let(:pipeline) { build(:ci_pipeline, ref: '!!!', project: project, stages: [stage]) }
+
+ it 'sets the failure status' do
+ expect { subject }.not_to change { Environment.count }
+
+ expect(job).to be_failed
+ expect(job).to be_environment_creation_failure
+ expect(job.persisted_environment).to be_nil
+ end
+ end
+
+ context 'when create_deployment_in_separate_transaction feature flag is disabled' do
+ before do
+ stub_feature_flags(create_deployment_in_separate_transaction: false)
+ end
+
+ it 'does not create any environments' do
+ expect { subject }.not_to change { Environment.count }
+
+ expect(job.persisted_environment).to be_nil
+ end
+ end
+ end
+
+ context 'when a pipeline contains a teardown job' do
+ let!(:job) { build(:ci_build, :stop_review_app, project: project) }
+
+ it 'ensures environment existence for the job' do
+ expect { subject }.to change { Environment.count }.by(1)
+
+ expect(project.environments.find_by_name('review/master')).to be_present
+ expect(job.persisted_environment.name).to eq('review/master')
+ expect(job.metadata.expanded_environment_name).to eq('review/master')
+ end
+ end
+
+ context 'when a pipeline does not contain a deployment job' do
+ let!(:job) { build(:ci_build, project: project) }
+
+ it 'does not create any environments' do
+ expect { subject }.not_to change { Environment.count }
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/ensure_resource_groups_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/ensure_resource_groups_spec.rb
new file mode 100644
index 00000000000..87df5a3e21b
--- /dev/null
+++ b/spec/lib/gitlab/ci/pipeline/chain/ensure_resource_groups_spec.rb
@@ -0,0 +1,85 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Pipeline::Chain::EnsureResourceGroups do
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+ let(:stage) { build(:ci_stage_entity, project: project, statuses: [job]) }
+ let(:pipeline) { build(:ci_pipeline, project: project, stages: [stage]) }
+ let!(:environment) { create(:environment, name: 'production', 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 { step.perform! }
+
+ before do
+ job.pipeline = pipeline
+ end
+
+ context 'when a pipeline contains a job that requires a resource group' do
+ let!(:job) do
+ build(:ci_build, project: project, environment: 'production', options: { resource_group_key: '$CI_ENVIRONMENT_NAME' })
+ end
+
+ it 'ensures the resource group existence' do
+ expect { subject }.to change { Ci::ResourceGroup.count }.by(1)
+
+ expect(project.resource_groups.find_by_key('production')).to be_present
+ expect(job.resource_group.key).to eq('production')
+ expect(job.options[:resource_group_key]).to be_nil
+ end
+
+ context 'when a resource group has already been existed' do
+ before do
+ create(:ci_resource_group, project: project, key: 'production')
+ end
+
+ it 'ensures the resource group existence' do
+ expect { subject }.not_to change { Ci::ResourceGroup.count }
+
+ expect(project.resource_groups.find_by_key('production')).to be_present
+ expect(job.resource_group.key).to eq('production')
+ expect(job.options[:resource_group_key]).to be_nil
+ end
+ end
+
+ context 'when a resource group key contains an invalid character' do
+ let!(:job) do
+ build(:ci_build, project: project, environment: '!!!', options: { resource_group_key: '$CI_ENVIRONMENT_NAME' })
+ end
+
+ it 'does not create any resource groups' do
+ expect { subject }.not_to change { Ci::ResourceGroup.count }
+
+ expect(job.resource_group).to be_nil
+ end
+ end
+
+ context 'when create_deployment_in_separate_transaction feature flag is disabled' do
+ before do
+ stub_feature_flags(create_deployment_in_separate_transaction: false)
+ end
+
+ it 'does not create any resource groups' do
+ expect { subject }.not_to change { Ci::ResourceGroup.count }
+
+ expect(job.resource_group).to be_nil
+ end
+ end
+ end
+
+ context 'when a pipeline does not contain a job that requires a resource group' do
+ let!(:job) { build(:ci_build, project: project) }
+
+ it 'does not create any resource groups' do
+ expect { subject }.not_to change { Ci::ResourceGroup.count }
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb
index cf21c98dbd5..cebc4c02d11 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb
@@ -24,6 +24,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Validate::External do
second_stage_job_name:
stage: second_stage
services:
+ -
- postgres
before_script:
- echo 'first hello'
@@ -142,6 +143,23 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Validate::External do
perform!
end
+
+ it 'returns expected payload' do
+ expect(::Gitlab::HTTP).to receive(:post) do |_url, params|
+ payload = Gitlab::Json.parse(params[:body])
+
+ builds = payload['builds']
+ expect(builds.count).to eq(2)
+ expect(builds[0]['services']).to be_nil
+ expect(builds[0]['stage']).to eq('first_stage')
+ expect(builds[0]['image']).to eq('hello_world')
+ expect(builds[1]['services']).to eq(['postgres'])
+ expect(builds[1]['stage']).to eq('second_stage')
+ expect(builds[1]['image']).to be_nil
+ end
+
+ perform!
+ end
end
context 'when EXTERNAL_VALIDATION_SERVICE_TOKEN is set' do
diff --git a/spec/lib/gitlab/ci/pipeline/expression/lexeme/variable_spec.rb b/spec/lib/gitlab/ci/pipeline/expression/lexeme/variable_spec.rb
index 115674edc48..3e10ca686ba 100644
--- a/spec/lib/gitlab/ci/pipeline/expression/lexeme/variable_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/expression/lexeme/variable_spec.rb
@@ -17,30 +17,33 @@ RSpec.describe Gitlab::Ci::Pipeline::Expression::Lexeme::Variable do
end
describe '#evaluate' do
- it 'returns variable value if it is defined' do
- variable = described_class.new('VARIABLE')
+ let(:lexeme) { described_class.new('VARIABLE') }
- expect(variable.evaluate(VARIABLE: 'my variable'))
+ it 'returns variable value if it is defined' do
+ expect(lexeme.evaluate(VARIABLE: 'my variable'))
.to eq 'my variable'
end
it 'allows to use a string as a variable key too' do
- variable = described_class.new('VARIABLE')
-
- expect(variable.evaluate('VARIABLE' => 'my variable'))
+ expect(lexeme.evaluate('VARIABLE' => 'my variable'))
.to eq 'my variable'
end
it 'returns nil if it is not defined' do
- variable = described_class.new('VARIABLE')
-
- expect(variable.evaluate(OTHER: 'variable')).to be_nil
+ expect(lexeme.evaluate('OTHER' => 'variable')).to be_nil
+ expect(lexeme.evaluate(OTHER: 'variable')).to be_nil
end
it 'returns an empty string if it is empty' do
- variable = described_class.new('VARIABLE')
+ expect(lexeme.evaluate('VARIABLE' => '')).to eq ''
+ expect(lexeme.evaluate(VARIABLE: '')).to eq ''
+ end
+
+ it 'does not call with_indifferent_access unnecessarily' do
+ variables_hash = { VARIABLE: 'my variable' }.with_indifferent_access
- expect(variable.evaluate(VARIABLE: '')).to eq ''
+ expect(variables_hash).not_to receive(:with_indifferent_access)
+ expect(lexeme.evaluate(variables_hash)).to eq 'my variable'
end
end
end
diff --git a/spec/lib/gitlab/ci/pipeline/expression/statement_spec.rb b/spec/lib/gitlab/ci/pipeline/expression/statement_spec.rb
index ec7eebdc056..84713e2a798 100644
--- a/spec/lib/gitlab/ci/pipeline/expression/statement_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/expression/statement_spec.rb
@@ -9,6 +9,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Expression::Statement do
.append(key: 'PATH_VARIABLE', value: 'a/path/variable/value')
.append(key: 'FULL_PATH_VARIABLE', value: '/a/full/path/variable/value')
.append(key: 'EMPTY_VARIABLE', value: '')
+ .to_hash
end
subject do
diff --git a/spec/lib/gitlab/ci/pipeline/logger_spec.rb b/spec/lib/gitlab/ci/pipeline/logger_spec.rb
new file mode 100644
index 00000000000..0b44e35dec1
--- /dev/null
+++ b/spec/lib/gitlab/ci/pipeline/logger_spec.rb
@@ -0,0 +1,132 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Gitlab::Ci::Pipeline::Logger do
+ let_it_be(:project) { build_stubbed(:project) }
+ let_it_be(:pipeline) { build_stubbed(:ci_pipeline, project: project) }
+
+ subject(:logger) { described_class.new(project: project) }
+
+ describe '#log_when' do
+ it 'stores blocks for later evaluation' do
+ logger.log_when { |obs| true }
+
+ expect(logger.send(:log_conditions).first).to be_a(Proc)
+ end
+ end
+
+ describe '#instrument' do
+ it "returns the block's value" do
+ expect(logger.instrument(:expensive_operation) { 123 }).to eq(123)
+ end
+
+ it 'records durations of instrumented operations' do
+ loggable_data = {
+ 'expensive_operation_duration_s' => {
+ 'count' => 1,
+ 'avg' => a_kind_of(Numeric),
+ 'max' => a_kind_of(Numeric),
+ 'min' => a_kind_of(Numeric)
+ }
+ }
+
+ logger.instrument(:expensive_operation) { 123 }
+ expect(logger.observations_hash).to match(a_hash_including(loggable_data))
+ end
+
+ it 'raises an error when block is not provided' do
+ expect { logger.instrument(:expensive_operation) }
+ .to raise_error(ArgumentError, 'block not given')
+ end
+ end
+
+ describe '#observe' do
+ it 'records durations of observed operations' do
+ loggable_data = {
+ 'pipeline_creation_duration_s' => {
+ 'avg' => 30, 'count' => 1, 'max' => 30, 'min' => 30
+ }
+ }
+
+ expect(logger.observe(:pipeline_creation_duration_s, 30)).to be_truthy
+ expect(logger.observations_hash).to match(a_hash_including(loggable_data))
+ end
+ end
+
+ describe '#commit' do
+ subject(:commit) { logger.commit(pipeline: pipeline, caller: 'source') }
+
+ before do
+ stub_feature_flags(ci_pipeline_creation_logger: flag)
+ allow(logger).to receive(:current_monotonic_time) { Time.current.to_i }
+
+ logger.instrument(:pipeline_save) { travel(60.seconds) }
+ logger.observe(:pipeline_creation_duration_s, 30)
+ logger.observe(:pipeline_creation_duration_s, 10)
+ end
+
+ context 'when the feature flag is enabled' do
+ let(:flag) { true }
+
+ let(:loggable_data) do
+ {
+ 'class' => described_class.name.to_s,
+ 'pipeline_id' => pipeline.id,
+ 'pipeline_persisted' => true,
+ 'project_id' => project.id,
+ 'pipeline_creation_service_duration_s' => a_kind_of(Numeric),
+ 'pipeline_creation_caller' => 'source',
+ 'pipeline_source' => pipeline.source,
+ 'pipeline_save_duration_s' => {
+ 'avg' => 60, 'count' => 1, 'max' => 60, 'min' => 60
+ },
+ 'pipeline_creation_duration_s' => {
+ 'avg' => 20, 'count' => 2, 'max' => 30, 'min' => 10
+ }
+ }
+ end
+
+ it 'logs to application.json' do
+ expect(Gitlab::AppJsonLogger)
+ .to receive(:info)
+ .with(a_hash_including(loggable_data))
+ .and_call_original
+
+ expect(commit).to be_truthy
+ end
+
+ context 'with log conditions' do
+ it 'does not log when the conditions are false' do
+ logger.log_when { |_obs| false }
+
+ expect(Gitlab::AppJsonLogger).not_to receive(:info)
+
+ expect(commit).to be_falsey
+ end
+
+ it 'logs when a condition is true' do
+ logger.log_when { |_obs| true }
+ logger.log_when { |_obs| false }
+
+ expect(Gitlab::AppJsonLogger)
+ .to receive(:info)
+ .with(a_hash_including(loggable_data))
+ .and_call_original
+
+ expect(commit).to be_truthy
+ end
+ end
+ end
+
+ context 'when the feature flag is disabled' do
+ let(:flag) { false }
+
+ it 'does not log' do
+ expect(Gitlab::AppJsonLogger).not_to receive(:info)
+
+ expect(commit).to be_falsey
+ end
+ 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 e2b64e65938..68806fbf287 100644
--- a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
let(:pipeline) { build(:ci_empty_pipeline, project: project, sha: head_sha) }
let(:root_variables) { [] }
let(:seed_context) { double(pipeline: pipeline, root_variables: root_variables) }
- let(:attributes) { { name: 'rspec', ref: 'master', scheduling_type: :stage } }
+ let(:attributes) { { name: 'rspec', ref: 'master', scheduling_type: :stage, when: 'on_success' } }
let(:previous_stages) { [] }
let(:current_stage) { double(seeds_names: [attributes[:name]]) }
@@ -61,17 +61,35 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
end
end
- context 'with job:rules but no explicit when:' do
- context 'is matched' do
- let(:attributes) { { name: 'rspec', ref: 'master', rules: [{ if: '$VAR == null' }] } }
+ context 'with job: rules but no explicit when:' do
+ let(:base_attributes) { { name: 'rspec', ref: 'master' } }
+
+ context 'with a manual job' do
+ context 'with a matched rule' do
+ let(:attributes) { base_attributes.merge(when: 'manual', rules: [{ if: '$VAR == null' }]) }
+
+ it { is_expected.to include(when: 'manual') }
+ end
- it { is_expected.to include(when: 'on_success') }
+ context 'is not matched' do
+ let(:attributes) { base_attributes.merge(when: 'manual', rules: [{ if: '$VAR != null' }]) }
+
+ it { is_expected.to include(when: 'never') }
+ end
end
- context 'is not matched' do
- let(:attributes) { { name: 'rspec', ref: 'master', rules: [{ if: '$VAR != null' }] } }
+ context 'with an automatic job' do
+ context 'is matched' do
+ let(:attributes) { base_attributes.merge(when: 'on_success', rules: [{ if: '$VAR == null' }]) }
- it { is_expected.to include(when: 'never') }
+ it { is_expected.to include(when: 'on_success') }
+ end
+
+ context 'is not matched' do
+ let(:attributes) { base_attributes.merge(when: 'on_success', rules: [{ if: '$VAR != null' }]) }
+
+ it { is_expected.to include(when: 'never') }
+ end
end
end
@@ -393,6 +411,10 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
describe '#to_resource' do
subject { seed_build.to_resource }
+ before do
+ stub_feature_flags(create_deployment_in_separate_transaction: false)
+ end
+
context 'when job is Ci::Build' do
it { is_expected.to be_a(::Ci::Build) }
it { is_expected.to be_valid }
@@ -443,6 +465,18 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
it_behaves_like 'deployment job'
it_behaves_like 'ensures environment existence'
+ context 'when create_deployment_in_separate_transaction feature flag is enabled' do
+ before do
+ stub_feature_flags(create_deployment_in_separate_transaction: true)
+ end
+
+ it 'does not create any deployments nor environments' do
+ expect(subject.deployment).to be_nil
+ expect(Environment.count).to eq(0)
+ expect(Deployment.count).to eq(0)
+ end
+ end
+
context 'when the environment name is invalid' do
let(:attributes) { { name: 'deploy', ref: 'master', environment: '!!!' } }
@@ -452,25 +486,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
expect(subject.metadata.expanded_environment_name).to be_nil
expect(Environment.exists?(name: expected_environment_name)).to eq(false)
end
-
- context 'when surface_environment_creation_failure feature flag is disabled' do
- before do
- stub_feature_flags(surface_environment_creation_failure: false)
- end
-
- it_behaves_like 'non-deployment job'
- it_behaves_like 'ensures environment inexistence'
-
- it 'tracks an exception' do
- expect(Gitlab::ErrorTracking).to receive(:track_exception)
- .with(an_instance_of(described_class::EnvironmentCreationFailure),
- project_id: project.id,
- reason: %q{Name can contain only letters, digits, '-', '_', '/', '$', '{', '}', '.', and spaces, but it cannot start or end with '/'})
- .once
-
- subject
- end
- end
end
end
@@ -515,6 +530,18 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
it 'returns a job with resource group' do
expect(subject.resource_group).not_to be_nil
expect(subject.resource_group.key).to eq('iOS')
+ expect(Ci::ResourceGroup.count).to eq(1)
+ end
+
+ context 'when create_deployment_in_separate_transaction feature flag is enabled' do
+ before do
+ stub_feature_flags(create_deployment_in_separate_transaction: true)
+ end
+
+ it 'does not create any resource groups' do
+ expect(subject.resource_group).to be_nil
+ expect(Ci::ResourceGroup.count).to eq(0)
+ end
end
context 'when resource group has $CI_ENVIRONMENT_NAME in it' do
@@ -892,7 +919,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
context 'using rules:' do
using RSpec::Parameterized
- let(:attributes) { { name: 'rspec', rules: rule_set } }
+ let(:attributes) { { name: 'rspec', rules: rule_set, when: 'on_success' } }
context 'with a matching if: rule' do
context 'with an explicit `when: never`' do
diff --git a/spec/lib/gitlab/ci/status/bridge/common_spec.rb b/spec/lib/gitlab/ci/status/bridge/common_spec.rb
index 37524afc83d..30e6ad234a0 100644
--- a/spec/lib/gitlab/ci/status/bridge/common_spec.rb
+++ b/spec/lib/gitlab/ci/status/bridge/common_spec.rb
@@ -29,7 +29,15 @@ RSpec.describe Gitlab::Ci::Status::Bridge::Common do
end
it { expect(subject).to have_details }
- it { expect(subject.details_path).to include "pipelines/#{downstream_pipeline.id}" }
+ it { expect(subject.details_path).to include "jobs/#{bridge.id}" }
+
+ context 'with ci_retry_downstream_pipeline ff disabled' do
+ before do
+ stub_feature_flags(ci_retry_downstream_pipeline: false)
+ end
+
+ it { expect(subject.details_path).to include "pipelines/#{downstream_pipeline.id}" }
+ end
end
context 'when user does not have access to read downstream pipeline' do
diff --git a/spec/lib/gitlab/ci/tags/bulk_insert_spec.rb b/spec/lib/gitlab/ci/tags/bulk_insert_spec.rb
new file mode 100644
index 00000000000..6c1f56de840
--- /dev/null
+++ b/spec/lib/gitlab/ci/tags/bulk_insert_spec.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Tags::BulkInsert do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project) }
+ let_it_be_with_refind(:job) { create(:ci_build, :unique_name, pipeline: pipeline, project: project) }
+ let_it_be_with_refind(:other_job) { create(:ci_build, :unique_name, pipeline: pipeline, project: project) }
+ let_it_be_with_refind(:bridge) { create(:ci_bridge, pipeline: pipeline, project: project) }
+
+ let(:statuses) { [job, bridge, other_job] }
+
+ subject(:service) { described_class.new(statuses, tags_list) }
+
+ describe '#insert!' do
+ context 'without tags' do
+ let(:tags_list) { {} }
+
+ it { expect(service.insert!).to be_falsey }
+ end
+
+ context 'with tags' do
+ let(:tags_list) do
+ {
+ job.name => %w[tag1 tag2],
+ other_job.name => %w[tag2 tag3 tag4]
+ }
+ end
+
+ it 'persists tags' do
+ expect(service.insert!).to be_truthy
+
+ expect(job.reload.tag_list).to match_array(%w[tag1 tag2])
+ expect(other_job.reload.tag_list).to match_array(%w[tag2 tag3 tag4])
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/variables/builder_spec.rb b/spec/lib/gitlab/ci/variables/builder_spec.rb
index 10275f33484..5ff34592b2f 100644
--- a/spec/lib/gitlab/ci/variables/builder_spec.rb
+++ b/spec/lib/gitlab/ci/variables/builder_spec.rb
@@ -24,15 +24,5 @@ RSpec.describe Gitlab::Ci::Variables::Builder do
expect(names).to include(*keys)
end
end
-
- context 'feature flag disabled' do
- before do
- stub_feature_flags(ci_predefined_vars_in_builder: false)
- end
-
- it 'returns no variables' do
- expect(subject.map { |env| env[:key] }).to be_empty
- 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 f00a801286d..e8b38b21ef8 100644
--- a/spec/lib/gitlab/ci/yaml_processor_spec.rb
+++ b/spec/lib/gitlab/ci/yaml_processor_spec.rb
@@ -2139,7 +2139,7 @@ module Gitlab
end
end
- context 'with when/rules conflict' do
+ context 'with when/rules' do
subject { Gitlab::Ci::YamlProcessor.new(YAML.dump(config)).execute }
let(:config) do
@@ -2174,7 +2174,7 @@ module Gitlab
}
end
- it_behaves_like 'returns errors', /may not be used with `rules`: when/
+ it { is_expected.to be_valid }
end
context 'used with job-level when:delayed' do
@@ -2190,7 +2190,7 @@ module Gitlab
}
end
- it_behaves_like 'returns errors', /may not be used with `rules`: when, start_in/
+ it_behaves_like 'returns errors', /may not be used with `rules`: start_in/
end
end