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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/lib/gitlab/ci')
-rw-r--r--spec/lib/gitlab/ci/ansi2json/line_spec.rb26
-rw-r--r--spec/lib/gitlab/ci/badge/coverage/template_spec.rb52
-rw-r--r--spec/lib/gitlab/ci/badge/pipeline/template_spec.rb52
-rw-r--r--spec/lib/gitlab/ci/build/auto_retry_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/config/entry/need_spec.rb20
-rw-r--r--spec/lib/gitlab/ci/config/entry/processable_spec.rb8
-rw-r--r--spec/lib/gitlab/ci/config/entry/reports_spec.rb1
-rw-r--r--spec/lib/gitlab/ci/jwt_spec.rb1
-rw-r--r--spec/lib/gitlab/ci/matching/build_matcher_spec.rb64
-rw-r--r--spec/lib/gitlab/ci/matching/runner_matcher_spec.rb113
-rw-r--r--spec/lib/gitlab/ci/parsers/test/junit_spec.rb24
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb59
-rw-r--r--spec/lib/gitlab/ci/pipeline/preloader_spec.rb8
-rw-r--r--spec/lib/gitlab/ci/pipeline/seed/build_spec.rb11
-rw-r--r--spec/lib/gitlab/ci/pipeline/seed/environment_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/npm_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/templates/templates_spec.rb162
-rw-r--r--spec/lib/gitlab/ci/trace/chunked_io_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/variables/collection/item_spec.rb39
-rw-r--r--spec/lib/gitlab/ci/variables/collection/sort_spec.rb11
-rw-r--r--spec/lib/gitlab/ci/variables/collection_spec.rb76
-rw-r--r--spec/lib/gitlab/ci/yaml_processor/result_spec.rb53
-rw-r--r--spec/lib/gitlab/ci/yaml_processor_spec.rb25
23 files changed, 538 insertions, 279 deletions
diff --git a/spec/lib/gitlab/ci/ansi2json/line_spec.rb b/spec/lib/gitlab/ci/ansi2json/line_spec.rb
index d681447a0e8..909c0f1b3ea 100644
--- a/spec/lib/gitlab/ci/ansi2json/line_spec.rb
+++ b/spec/lib/gitlab/ci/ansi2json/line_spec.rb
@@ -76,10 +76,30 @@ RSpec.describe Gitlab::Ci::Ansi2json::Line do
end
describe '#set_section_duration' do
- it 'sets and formats the section_duration' do
- subject.set_section_duration(75)
+ shared_examples 'set_section_duration' do
+ it 'sets and formats the section_duration' do
+ subject.set_section_duration(75)
- expect(subject.section_duration).to eq('01:15')
+ expect(subject.section_duration).to eq('01:15')
+ end
+ end
+
+ context 'with default timezone' do
+ it_behaves_like 'set_section_duration'
+ end
+
+ context 'with a timezone carrying minutes offset' do
+ before do
+ # The actual call by does use Time.at(...).utc that the following
+ # rubocop rule (Rails/TimeZone) suggests, but for this specific
+ # test's purposes we needed to mock at the Time.at call point.
+
+ # rubocop:disable Rails/TimeZone
+ allow(Time).to receive(:at).with(75).and_return(Time.at(75, in: '+05:30'))
+ # rubocop:enable Rails/TimeZone
+ end
+
+ it_behaves_like 'set_section_duration'
end
end
diff --git a/spec/lib/gitlab/ci/badge/coverage/template_spec.rb b/spec/lib/gitlab/ci/badge/coverage/template_spec.rb
index f010d1bce50..b03ca3c93ca 100644
--- a/spec/lib/gitlab/ci/badge/coverage/template_spec.rb
+++ b/spec/lib/gitlab/ci/badge/coverage/template_spec.rb
@@ -6,31 +6,7 @@ RSpec.describe Gitlab::Ci::Badge::Coverage::Template do
let(:badge) { double(entity: 'coverage', status: 90.00, customization: {}) }
let(:template) { described_class.new(badge) }
- describe '#key_text' do
- it 'says coverage by default' do
- expect(template.key_text).to eq 'coverage'
- end
-
- context 'when custom key_text is defined' do
- before do
- allow(badge).to receive(:customization).and_return({ key_text: "custom text" })
- end
-
- it 'returns custom value' do
- expect(template.key_text).to eq "custom text"
- end
-
- context 'when its size is larger than the max allowed value' do
- before do
- allow(badge).to receive(:customization).and_return({ key_text: 't' * 65 })
- end
-
- it 'returns default value' do
- expect(template.key_text).to eq 'coverage'
- end
- end
- end
- end
+ it_behaves_like 'a badge template', 'coverage'
describe '#value_text' do
context 'when coverage is known' do
@@ -60,32 +36,6 @@ RSpec.describe Gitlab::Ci::Badge::Coverage::Template do
end
end
- describe '#key_width' do
- it 'is fixed by default' do
- expect(template.key_width).to eq 62
- end
-
- context 'when custom key_width is defined' do
- before do
- allow(badge).to receive(:customization).and_return({ key_width: 101 })
- end
-
- it 'returns custom value' do
- expect(template.key_width).to eq 101
- end
-
- context 'when it is larger than the max allowed value' do
- before do
- allow(badge).to receive(:customization).and_return({ key_width: 513 })
- end
-
- it 'returns default value' do
- expect(template.key_width).to eq 62
- end
- end
- end
- end
-
describe '#value_width' do
context 'when coverage is known' do
it 'is narrower when coverage is known' do
diff --git a/spec/lib/gitlab/ci/badge/pipeline/template_spec.rb b/spec/lib/gitlab/ci/badge/pipeline/template_spec.rb
index 696bb62b4d6..9392ccef147 100644
--- a/spec/lib/gitlab/ci/badge/pipeline/template_spec.rb
+++ b/spec/lib/gitlab/ci/badge/pipeline/template_spec.rb
@@ -6,31 +6,7 @@ RSpec.describe Gitlab::Ci::Badge::Pipeline::Template do
let(:badge) { double(entity: 'pipeline', status: 'success', customization: {}) }
let(:template) { described_class.new(badge) }
- describe '#key_text' do
- it 'says pipeline by default' do
- expect(template.key_text).to eq 'pipeline'
- end
-
- context 'when custom key_text is defined' do
- before do
- allow(badge).to receive(:customization).and_return({ key_text: 'custom text' })
- end
-
- it 'returns custom value' do
- expect(template.key_text).to eq 'custom text'
- end
-
- context 'when its size is larger than the max allowed value' do
- before do
- allow(badge).to receive(:customization).and_return({ key_text: 't' * 65 })
- end
-
- it 'returns default value' do
- expect(template.key_text).to eq 'pipeline'
- end
- end
- end
- end
+ it_behaves_like 'a badge template', 'pipeline'
describe '#value_text' do
it 'is status value' do
@@ -38,32 +14,6 @@ RSpec.describe Gitlab::Ci::Badge::Pipeline::Template do
end
end
- describe '#key_width' do
- it 'is fixed by default' do
- expect(template.key_width).to eq 62
- end
-
- context 'when custom key_width is defined' do
- before do
- allow(badge).to receive(:customization).and_return({ key_width: 101 })
- end
-
- it 'returns custom value' do
- expect(template.key_width).to eq 101
- end
-
- context 'when it is larger than the max allowed value' do
- before do
- allow(badge).to receive(:customization).and_return({ key_width: 513 })
- end
-
- it 'returns default value' do
- expect(template.key_width).to eq 62
- end
- end
- end
- end
-
describe 'widths and text anchors' do
it 'has fixed width and text anchors' do
expect(template.width).to eq 116
diff --git a/spec/lib/gitlab/ci/build/auto_retry_spec.rb b/spec/lib/gitlab/ci/build/auto_retry_spec.rb
index cfa8c9cd938..b107553bbce 100644
--- a/spec/lib/gitlab/ci/build/auto_retry_spec.rb
+++ b/spec/lib/gitlab/ci/build/auto_retry_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe Gitlab::Ci::Build::AutoRetry do
describe '#allowed?' do
using RSpec::Parameterized::TableSyntax
- let(:build) { create(:ci_build) }
+ let(:build) { build_stubbed(:ci_build) }
subject { auto_retry.allowed? }
@@ -22,6 +22,8 @@ RSpec.describe Gitlab::Ci::Build::AutoRetry do
"not matching reason" | 0 | { when: %w[script_error], max: 2 } | :api_failure | false
"scheduler failure override" | 1 | { when: %w[scheduler_failure], max: 1 } | :scheduler_failure | false
"default for scheduler failure" | 1 | {} | :scheduler_failure | true
+ "quota is exceeded" | 0 | { max: 2 } | :ci_quota_exceeded | false
+ "no matching runner" | 0 | { max: 2 } | :no_matching_runner | false
end
with_them do
diff --git a/spec/lib/gitlab/ci/config/entry/need_spec.rb b/spec/lib/gitlab/ci/config/entry/need_spec.rb
index a0a5dd52ad4..ab2e8d4db78 100644
--- a/spec/lib/gitlab/ci/config/entry/need_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/need_spec.rb
@@ -25,16 +25,6 @@ RSpec.describe ::Gitlab::Ci::Config::Entry::Need do
it 'returns job needs configuration' do
expect(need.value).to eq(name: 'job_name', artifacts: true, optional: false)
end
-
- context 'when the FF ci_needs_optional is disabled' do
- before do
- stub_feature_flags(ci_needs_optional: false)
- end
-
- it 'returns job needs configuration without `optional`' do
- expect(need.value).to eq(name: 'job_name', artifacts: true)
- end
- end
end
it_behaves_like 'job type'
@@ -134,16 +124,6 @@ RSpec.describe ::Gitlab::Ci::Config::Entry::Need do
it 'returns job needs configuration' do
expect(need.value).to eq(name: 'job_name', artifacts: true, optional: true)
end
-
- context 'when the FF ci_needs_optional is disabled' do
- before do
- stub_feature_flags(ci_needs_optional: false)
- end
-
- it 'returns job needs configuration without `optional`' do
- expect(need.value).to eq(name: 'job_name', artifacts: true)
- end
- end
end
end
diff --git a/spec/lib/gitlab/ci/config/entry/processable_spec.rb b/spec/lib/gitlab/ci/config/entry/processable_spec.rb
index 016d59e98b9..f98a6a869d6 100644
--- a/spec/lib/gitlab/ci/config/entry/processable_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/processable_spec.rb
@@ -271,10 +271,8 @@ RSpec.describe Gitlab::Ci::Config::Entry::Processable do
context 'when workflow rules is not used' do
let(:workflow) { double('workflow', 'has_rules?' => false) }
- let(:feature_flag_value) { true }
before do
- stub_feature_flags(ci_raise_job_rules_without_workflow_rules_warning: feature_flag_value)
entry.compose!(deps)
end
@@ -298,12 +296,6 @@ RSpec.describe Gitlab::Ci::Config::Entry::Processable do
it 'raises a warning' do
expect(entry.warnings).to contain_exactly(/may allow multiple pipelines/)
end
-
- context 'when feature flag is disabled' do
- let(:feature_flag_value) { false }
-
- it_behaves_like 'has no warnings'
- end
end
context 'and its value is `never`' do
diff --git a/spec/lib/gitlab/ci/config/entry/reports_spec.rb b/spec/lib/gitlab/ci/config/entry/reports_spec.rb
index 98105ebcd55..d8907f7015b 100644
--- a/spec/lib/gitlab/ci/config/entry/reports_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/reports_spec.rb
@@ -41,7 +41,6 @@ RSpec.describe Gitlab::Ci::Config::Entry::Reports do
:dependency_scanning | 'gl-dependency-scanning-report.json'
:container_scanning | 'gl-container-scanning-report.json'
:dast | 'gl-dast-report.json'
- :license_management | 'gl-license-management-report.json'
:license_scanning | 'gl-license-scanning-report.json'
:performance | 'performance.json'
:browser_performance | 'browser-performance.json'
diff --git a/spec/lib/gitlab/ci/jwt_spec.rb b/spec/lib/gitlab/ci/jwt_spec.rb
index 480a4a05379..b0d6f5adfb1 100644
--- a/spec/lib/gitlab/ci/jwt_spec.rb
+++ b/spec/lib/gitlab/ci/jwt_spec.rb
@@ -42,6 +42,7 @@ RSpec.describe Gitlab::Ci::Jwt do
expect(payload[:user_email]).to eq(user.email)
expect(payload[:user_login]).to eq(user.username)
expect(payload[:pipeline_id]).to eq(pipeline.id.to_s)
+ expect(payload[:pipeline_source]).to eq(pipeline.source.to_s)
expect(payload[:job_id]).to eq(build.id.to_s)
expect(payload[:ref]).to eq(pipeline.source_ref)
expect(payload[:ref_protected]).to eq(build.protected.to_s)
diff --git a/spec/lib/gitlab/ci/matching/build_matcher_spec.rb b/spec/lib/gitlab/ci/matching/build_matcher_spec.rb
new file mode 100644
index 00000000000..f12e85da9c2
--- /dev/null
+++ b/spec/lib/gitlab/ci/matching/build_matcher_spec.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+RSpec.describe Gitlab::Ci::Matching::BuildMatcher do
+ let(:dummy_attributes) do
+ {
+ protected: true,
+ tag_list: %w[tag1 tag2],
+ build_ids: [1, 2, 3],
+ project: :my_project
+ }
+ end
+
+ subject(:matcher) { described_class.new(attributes) }
+
+ describe '.new' do
+ context 'when attributes are missing' do
+ let(:attributes) { {} }
+
+ it { expect { matcher }.to raise_error(KeyError) }
+ end
+
+ context 'with attributes' do
+ let(:attributes) { dummy_attributes }
+
+ it { expect(matcher.protected).to eq(true) }
+
+ it { expect(matcher.tag_list).to eq(%w[tag1 tag2]) }
+
+ it { expect(matcher.build_ids).to eq([1, 2, 3]) }
+
+ it { expect(matcher.project).to eq(:my_project) }
+ end
+ end
+
+ describe '#protected?' do
+ context 'when protected is set to true' do
+ let(:attributes) { dummy_attributes }
+
+ it { expect(matcher.protected?).to be_truthy }
+ end
+
+ context 'when protected is set to false' do
+ let(:attributes) { dummy_attributes.merge(protected: false) }
+
+ it { expect(matcher.protected?).to be_falsey }
+ end
+ end
+
+ describe '#has_tags?' do
+ context 'when tags are present' do
+ let(:attributes) { dummy_attributes }
+
+ it { expect(matcher.has_tags?).to be_truthy }
+ end
+
+ context 'when tags are empty' do
+ let(:attributes) { dummy_attributes.merge(tag_list: []) }
+
+ it { expect(matcher.has_tags?).to be_falsey }
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/matching/runner_matcher_spec.rb b/spec/lib/gitlab/ci/matching/runner_matcher_spec.rb
new file mode 100644
index 00000000000..d6492caa31a
--- /dev/null
+++ b/spec/lib/gitlab/ci/matching/runner_matcher_spec.rb
@@ -0,0 +1,113 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Matching::RunnerMatcher do
+ let(:dummy_attributes) do
+ {
+ runner_type: 'instance_type',
+ public_projects_minutes_cost_factor: 0,
+ private_projects_minutes_cost_factor: 1,
+ run_untagged: false,
+ access_level: 'ref_protected',
+ tag_list: %w[tag1 tag2]
+ }
+ end
+
+ subject(:matcher) { described_class.new(attributes) }
+
+ describe '.new' do
+ context 'when attributes are missing' do
+ let(:attributes) { {} }
+
+ it { expect { matcher }.to raise_error(KeyError) }
+ end
+
+ context 'with attributes' do
+ let(:attributes) { dummy_attributes }
+
+ it { expect(matcher.runner_type).to eq('instance_type') }
+
+ it { expect(matcher.public_projects_minutes_cost_factor).to eq(0) }
+
+ it { expect(matcher.private_projects_minutes_cost_factor).to eq(1) }
+
+ it { expect(matcher.run_untagged).to eq(false) }
+
+ it { expect(matcher.access_level).to eq('ref_protected') }
+
+ it { expect(matcher.tag_list).to eq(%w[tag1 tag2]) }
+ end
+ end
+
+ describe '#instance_type?' do
+ let(:attributes) { dummy_attributes }
+
+ it { expect(matcher.instance_type?).to be_truthy }
+
+ context 'context with private runners' do
+ let(:attributes) { dummy_attributes.merge(runner_type: 'project_type') }
+
+ it { expect(matcher.instance_type?).to be_falsey }
+ end
+ end
+
+ describe '#matches?' do
+ let(:build) { build_stubbed(:ci_build, build_attributes) }
+ let(:runner_matcher) { described_class.new(dummy_attributes.merge(runner_attributes)) }
+
+ subject { runner_matcher.matches?(record) }
+
+ context 'with an instance of BuildMatcher' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:ref_protected, :build_protected, :run_untagged, :runner_tags, :build_tags, :result) do
+ # the `ref_protected? && !build.protected?` part:
+ true | true | true | [] | [] | true
+ true | false | true | [] | [] | false
+ false | true | true | [] | [] | true
+ false | false | true | [] | [] | true
+ # `accepting_tags?(build)` bit:
+ true | true | true | [] | [] | true
+ true | true | true | [] | ['a'] | false
+ true | true | true | %w[a b] | ['a'] | true
+ true | true | true | ['a'] | %w[a b] | false
+ true | true | true | ['a'] | ['a'] | true
+ true | true | false | ['a'] | ['a'] | true
+ true | true | false | ['b'] | ['a'] | false
+ true | true | false | %w[a b] | ['a'] | true
+ end
+
+ with_them do
+ let(:build_attributes) do
+ {
+ tag_list: build_tags,
+ protected: build_protected
+ }
+ end
+
+ let(:runner_attributes) do
+ {
+ access_level: ref_protected ? 'ref_protected' : 'not_protected',
+ run_untagged: run_untagged,
+ tag_list: runner_tags
+ }
+ end
+
+ let(:record) { build.build_matcher }
+
+ it { is_expected.to eq(result) }
+ end
+ end
+
+ context 'with an instance of Ci::Build' do
+ let(:runner_attributes) { {} }
+ let(:build_attributes) { {} }
+ let(:record) { build }
+
+ it 'raises ArgumentError' do
+ expect { subject }.to raise_error ArgumentError, /BuildMatcher are allowed/
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/parsers/test/junit_spec.rb b/spec/lib/gitlab/ci/parsers/test/junit_spec.rb
index 7da602251a5..4ca8f74e57f 100644
--- a/spec/lib/gitlab/ci/parsers/test/junit_spec.rb
+++ b/spec/lib/gitlab/ci/parsers/test/junit_spec.rb
@@ -417,6 +417,30 @@ RSpec.describe Gitlab::Ci::Parsers::Test::Junit do
end
end
+ context 'when attachment is specified in test case with error' do
+ let(:junit) do
+ <<~EOF
+ <testsuites>
+ <testsuite>
+ <testcase classname='Calculator' name='sumTest1' time='0.01'>
+ <error>Some error</error>
+ <system-out>[[ATTACHMENT|some/path.png]]</system-out>
+ </testcase>
+ </testsuite>
+ </testsuites>
+ EOF
+ end
+
+ it 'assigns correct attributes to the test case' do
+ expect { subject }.not_to raise_error
+
+ expect(test_cases[0].has_attachment?).to be_truthy
+ expect(test_cases[0].attachment).to eq("some/path.png")
+
+ expect(test_cases[0].job).to eq(job)
+ end
+ end
+
private
def flattened_test_cases(test_suite)
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 e3061f8095b..16517b39a45 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Ci::Pipeline::Chain::Validate::External do
let_it_be(:project) { create(:project) }
- let_it_be(:user) { create(:user) }
+ let_it_be(:user) { create(:user, :with_sign_ins) }
let(:pipeline) { build(:ci_empty_pipeline, user: user, project: project) }
let!(:step) { described_class.new(pipeline, command) }
@@ -43,7 +43,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Validate::External do
end
let(:save_incompleted) { true }
- let(:dot_com) { true }
let(:command) do
Gitlab::Ci::Pipeline::Chain::Command.new(
project: project, current_user: user, yaml_processor_result: yaml_processor_result, save_incompleted: save_incompleted
@@ -57,7 +56,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Validate::External do
before do
stub_env('EXTERNAL_VALIDATION_SERVICE_URL', validation_service_url)
- allow(Gitlab).to receive(:com?).and_return(dot_com)
allow(Labkit::Correlation::CorrelationId).to receive(:current_id).and_return('correlation-id')
end
@@ -199,61 +197,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Validate::External do
end
end
- context 'when the feature flag is disabled' do
- before do
- stub_feature_flags(ci_external_validation_service: false)
- stub_request(:post, validation_service_url)
- end
-
- it 'does not drop the pipeline' do
- perform!
-
- expect(pipeline.status).not_to eq('failed')
- expect(pipeline.errors).to be_empty
- end
-
- it 'does not break the chain' do
- perform!
-
- expect(step.break?).to be false
- end
-
- it 'does not make requests' do
- perform!
-
- expect(WebMock).not_to have_requested(:post, validation_service_url)
- end
- end
-
- context 'when not on .com' do
- let(:dot_com) { false }
-
- before do
- stub_feature_flags(ci_external_validation_service: false)
- stub_request(:post, validation_service_url).to_return(status: 404, body: "{}")
- end
-
- it 'drops the pipeline' do
- perform!
-
- expect(pipeline.status).to eq('failed')
- expect(pipeline).to be_persisted
- expect(pipeline.errors.to_a).to include('External validation failed')
- end
-
- it 'breaks the chain' do
- perform!
-
- expect(step.break?).to be true
- end
-
- it 'logs the authorization' do
- expect(Gitlab::AppLogger).to receive(:info).with(message: 'Pipeline not authorized', project_id: project.id, user_id: user.id)
-
- perform!
- end
- end
-
context 'when validation returns 406 Not Acceptable' do
before do
stub_request(:post, validation_service_url).to_return(status: 406, body: "{}")
diff --git a/spec/lib/gitlab/ci/pipeline/preloader_spec.rb b/spec/lib/gitlab/ci/pipeline/preloader_spec.rb
index ae423fa04f9..5b644e42451 100644
--- a/spec/lib/gitlab/ci/pipeline/preloader_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/preloader_spec.rb
@@ -5,9 +5,11 @@ require 'spec_helper'
RSpec.describe Gitlab::Ci::Pipeline::Preloader do
let(:stage) { double(:stage) }
let(:commit) { double(:commit) }
+ let(:scheduled_action) { double(:scheduled_action) }
+ let(:manual_action) { double(:manual_action) }
let(:pipeline) do
- double(:pipeline, commit: commit, stages: [stage])
+ double(:pipeline, commit: commit, stages: [stage], scheduled_actions: [scheduled_action], manual_actions: [manual_action])
end
describe '.preload!' do
@@ -33,6 +35,8 @@ RSpec.describe Gitlab::Ci::Pipeline::Preloader do
expect(pipeline).to receive(:lazy_ref_commit)
expect(pipeline).to receive(:number_of_warnings)
expect(stage).to receive(:number_of_warnings)
+ expect(scheduled_action).to receive(:persisted_environment)
+ expect(manual_action).to receive(:persisted_environment)
described_class.preload!([pipeline])
end
@@ -42,6 +46,8 @@ RSpec.describe Gitlab::Ci::Pipeline::Preloader do
allow(pipeline).to receive(:lazy_ref_commit)
allow(pipeline).to receive(:number_of_warnings)
allow(stage).to receive(:number_of_warnings)
+ allow(scheduled_action).to receive(:persisted_environment)
+ allow(manual_action).to receive(:persisted_environment)
pipelines = [pipeline, pipeline]
diff --git a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
index 058fb25807d..020f957cf70 100644
--- a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
@@ -1101,17 +1101,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
it "does not return an error" do
expect(subject.errors).to be_empty
end
-
- context 'when the FF ci_needs_optional is disabled' do
- before do
- stub_feature_flags(ci_needs_optional: false)
- end
-
- it "returns an error" do
- expect(subject.errors).to contain_exactly(
- "'rspec' job needs 'build' job, but it was not added to the pipeline")
- 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
index 175b12637e6..ad89f1f5cda 100644
--- a/spec/lib/gitlab/ci/pipeline/seed/environment_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/seed/environment_spec.rb
@@ -128,7 +128,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Environment do
context 'when environment has already been created' do
before do
- create(:environment, :staging, project: project, name: 'customer-portal')
+ create(:environment, project: project, name: 'customer-portal', tier: :staging)
end
it 'does not overwrite the specified deployment tier' do
diff --git a/spec/lib/gitlab/ci/templates/npm_spec.rb b/spec/lib/gitlab/ci/templates/npm_spec.rb
index b10e2b0e057..2456c9ae545 100644
--- a/spec/lib/gitlab/ci/templates/npm_spec.rb
+++ b/spec/lib/gitlab/ci/templates/npm_spec.rb
@@ -2,8 +2,8 @@
require 'spec_helper'
-RSpec.describe 'npm.latest.gitlab-ci.yml' do
- subject(:template) { Gitlab::Template::GitlabCiYmlTemplate.find('npm.latest') }
+RSpec.describe 'npm.gitlab-ci.yml' do
+ subject(:template) { Gitlab::Template::GitlabCiYmlTemplate.find('npm') }
describe 'the created pipeline' do
let(:repo_files) { { 'package.json' => '{}', 'README.md' => '' } }
diff --git a/spec/lib/gitlab/ci/templates/templates_spec.rb b/spec/lib/gitlab/ci/templates/templates_spec.rb
index 56443e611e8..2e6df7da232 100644
--- a/spec/lib/gitlab/ci/templates/templates_spec.rb
+++ b/spec/lib/gitlab/ci/templates/templates_spec.rb
@@ -6,26 +6,105 @@ RSpec.describe 'CI YML Templates' do
subject { Gitlab::Ci::YamlProcessor.new(content).execute }
let(:all_templates) { Gitlab::Template::GitlabCiYmlTemplate.all.map(&:full_name) }
-
let(:excluded_templates) do
- all_templates.select do |name|
+ excluded = all_templates.select do |name|
Gitlab::Template::GitlabCiYmlTemplate.excluded_patterns.any? { |pattern| pattern.match?(name) }
end
+ excluded + ["Terraform.gitlab-ci.yml"]
end
- context 'when including available templates in a CI YAML configuration' do
- using RSpec::Parameterized::TableSyntax
+ before do
+ stub_feature_flags(
+ redirect_to_latest_template_terraform: false,
+ redirect_to_latest_template_security_api_fuzzing: false,
+ redirect_to_latest_template_security_dast: false)
+ end
- where(:template_name) do
- all_templates - excluded_templates
+ shared_examples 'require default stages to be included' do
+ it 'require default stages to be included' do
+ expect(subject.stages).to include(*Gitlab::Ci::Config::Entry::Stages.default)
end
+ end
+
+ context 'that support autodevops' do
+ non_autodevops_templates = [
+ 'Security/DAST-API.gitlab-ci.yml',
+ 'Security/API-Fuzzing.gitlab-ci.yml'
+ ]
+
+ context 'when including available templates in a CI YAML configuration' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:template_name) do
+ all_templates - excluded_templates - non_autodevops_templates
+ end
+
+ with_them do
+ let(:content) do
+ <<~EOS
+ include:
+ - template: #{template_name}
+
+ concrete_build_implemented_by_a_user:
+ stage: test
+ script: do something
+ EOS
+ end
+
+ it { is_expected.to be_valid }
+
+ include_examples 'require default stages to be included'
+ end
+ end
+
+ context 'when including unavailable templates in a CI YAML configuration' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:template_name) do
+ excluded_templates
+ end
+
+ with_them do
+ let(:content) do
+ <<~EOS
+ include:
+ - template: #{template_name}
+
+ concrete_build_implemented_by_a_user:
+ stage: test
+ script: do something
+ EOS
+ end
+
+ it { is_expected.not_to be_valid }
+ end
+ end
+ end
+
+ describe 'that do not support autodevops' do
+ context 'when DAST API template' do
+ # The DAST API template purposly excludes a stages
+ # definition.
- with_them do
- let(:content) do
- if template_name == 'Security/DAST-API.gitlab-ci.yml'
- # The DAST-API template purposly excludes a stages
- # definition.
+ let(:template_name) { 'Security/DAST-API.gitlab-ci.yml' }
+ context 'with default stages' do
+ let(:content) do
+ <<~EOS
+ include:
+ - template: #{template_name}
+
+ concrete_build_implemented_by_a_user:
+ stage: test
+ script: do something
+ EOS
+ end
+
+ it { is_expected.not_to be_valid }
+ end
+
+ context 'with defined stages' do
+ let(:content) do
<<~EOS
include:
- template: #{template_name}
@@ -40,7 +119,22 @@ RSpec.describe 'CI YML Templates' do
stage: test
script: do something
EOS
- else
+ end
+
+ it { is_expected.to be_valid }
+
+ include_examples 'require default stages to be included'
+ end
+ end
+
+ context 'when API Fuzzing template' do
+ # The API Fuzzing template purposly excludes a stages
+ # definition.
+
+ let(:template_name) { 'Security/API-Fuzzing.gitlab-ci.yml' }
+
+ context 'with default stages' do
+ let(:content) do
<<~EOS
include:
- template: #{template_name}
@@ -50,39 +144,31 @@ RSpec.describe 'CI YML Templates' do
script: do something
EOS
end
- end
-
- it 'is valid' do
- expect(subject).to be_valid
- end
- it 'require default stages to be included' do
- expect(subject.stages).to include(*Gitlab::Ci::Config::Entry::Stages.default)
+ it { is_expected.not_to be_valid }
end
- end
- end
- context 'when including unavailable templates in a CI YAML configuration' do
- using RSpec::Parameterized::TableSyntax
+ context 'with defined stages' do
+ let(:content) do
+ <<~EOS
+ include:
+ - template: #{template_name}
- where(:template_name) do
- excluded_templates
- end
+ stages:
+ - build
+ - test
+ - deploy
+ - fuzz
- with_them do
- let(:content) do
- <<~EOS
- include:
- - template: #{template_name}
+ concrete_build_implemented_by_a_user:
+ stage: test
+ script: do something
+ EOS
+ end
- concrete_build_implemented_by_a_user:
- stage: test
- script: do something
- EOS
- end
+ it { is_expected.to be_valid }
- it 'is not valid' do
- expect(subject).not_to be_valid
+ include_examples 'require default stages to be included'
end
end
end
diff --git a/spec/lib/gitlab/ci/trace/chunked_io_spec.rb b/spec/lib/gitlab/ci/trace/chunked_io_spec.rb
index f878d24fe4b..63625244fe8 100644
--- a/spec/lib/gitlab/ci/trace/chunked_io_spec.rb
+++ b/spec/lib/gitlab/ci/trace/chunked_io_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe Gitlab::Ci::Trace::ChunkedIO, :clean_gitlab_redis_cache do
let(:chunked_io) { described_class.new(build) }
before do
- stub_feature_flags(ci_enable_live_trace: true, gitlab_ci_trace_read_consistency: true)
+ stub_feature_flags(ci_enable_live_trace: true)
end
describe "#initialize" do
diff --git a/spec/lib/gitlab/ci/variables/collection/item_spec.rb b/spec/lib/gitlab/ci/variables/collection/item_spec.rb
index ca9dc95711d..9443bf6d6d5 100644
--- a/spec/lib/gitlab/ci/variables/collection/item_spec.rb
+++ b/spec/lib/gitlab/ci/variables/collection/item_spec.rb
@@ -70,6 +70,43 @@ RSpec.describe Gitlab::Ci::Variables::Collection::Item do
end
end
+ describe '.possible_var_reference?' do
+ context 'table tests' do
+ using RSpec::Parameterized::TableSyntax
+
+ where do
+ {
+ "empty value": {
+ value: '',
+ result: false
+ },
+ "normal value": {
+ value: 'some value',
+ result: false
+ },
+ "simple expansions": {
+ value: 'key$variable',
+ result: true
+ },
+ "complex expansions": {
+ value: 'key${variable}${variable2}',
+ result: true
+ },
+ "complex expansions for Windows": {
+ value: 'key%variable%%variable2%',
+ result: true
+ }
+ }
+ end
+
+ with_them do
+ subject { Gitlab::Ci::Variables::Collection::Item.possible_var_reference?(value) }
+
+ it { is_expected.to eq(result) }
+ end
+ end
+ end
+
describe '#depends_on' do
let(:item) { Gitlab::Ci::Variables::Collection::Item.new(**variable) }
@@ -128,7 +165,7 @@ RSpec.describe Gitlab::Ci::Variables::Collection::Item do
end
it 'supports using an active record resource' do
- variable = create(:ci_variable, key: 'CI_VAR', value: '123')
+ variable = build(:ci_variable, key: 'CI_VAR', value: '123')
resource = described_class.fabricate(variable)
expect(resource).to be_a(described_class)
diff --git a/spec/lib/gitlab/ci/variables/collection/sort_spec.rb b/spec/lib/gitlab/ci/variables/collection/sort_spec.rb
index 73cf0e19d00..01eef673c35 100644
--- a/spec/lib/gitlab/ci/variables/collection/sort_spec.rb
+++ b/spec/lib/gitlab/ci/variables/collection/sort_spec.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require 'spec_helper'
+require 'fast_spec_helper'
+require 'rspec-parameterized'
RSpec.describe Gitlab::Ci::Variables::Collection::Sort do
describe '#initialize with non-Collection value' do
@@ -57,9 +58,9 @@ RSpec.describe Gitlab::Ci::Variables::Collection::Sort do
},
"variable containing escaped variable reference": {
variables: [
- { key: 'variable_a', value: 'value' },
{ key: 'variable_b', value: '$$variable_a' },
- { key: 'variable_c', value: '$variable_b' }
+ { key: 'variable_c', value: '$variable_a' },
+ { key: 'variable_a', value: 'value' }
],
expected_errors: nil
}
@@ -144,11 +145,11 @@ RSpec.describe Gitlab::Ci::Variables::Collection::Sort do
},
"variable containing escaped variable reference": {
variables: [
- { key: 'variable_c', value: '$variable_b' },
{ key: 'variable_b', value: '$$variable_a' },
+ { key: 'variable_c', value: '$variable_a' },
{ key: 'variable_a', value: 'value' }
],
- result: %w[variable_a variable_b variable_c]
+ result: %w[variable_b variable_a variable_c]
}
}
end
diff --git a/spec/lib/gitlab/ci/variables/collection_spec.rb b/spec/lib/gitlab/ci/variables/collection_spec.rb
index 7b77754190a..abda27f0d6e 100644
--- a/spec/lib/gitlab/ci/variables/collection_spec.rb
+++ b/spec/lib/gitlab/ci/variables/collection_spec.rb
@@ -44,6 +44,30 @@ RSpec.describe Gitlab::Ci::Variables::Collection do
end
end
+ describe '#compact' do
+ subject do
+ described_class.new
+ .append(key: 'STRING', value: 'string')
+ .append(key: 'NIL', value: nil)
+ .append(key: nil, value: 'string')
+ end
+
+ it 'returns a new Collection instance', :aggregate_failures do
+ collection = subject.compact
+
+ expect(collection).to be_an_instance_of(described_class)
+ expect(collection).not_to eql(subject)
+ end
+
+ it 'rejects pair that has nil value', :aggregate_failures do
+ collection = subject.compact
+
+ expect(collection).not_to include(key: 'NIL', value: nil, public: true)
+ expect(collection).to include(key: 'STRING', value: 'string', public: true)
+ expect(collection).to include(key: nil, value: 'string', public: true)
+ end
+ end
+
describe '#concat' do
it 'appends all elements from an array' do
collection = described_class.new([{ key: 'VAR_1', value: '1' }])
@@ -229,6 +253,11 @@ RSpec.describe Gitlab::Ci::Variables::Collection do
value: 'key${MISSING_VAR}-${CI_JOB_NAME}',
result: 'key${MISSING_VAR}-test-1',
keep_undefined: true
+ },
+ "escaped characters are kept intact": {
+ value: 'key-$TEST1-%%HOME%%-$${HOME}',
+ result: 'key-test-3-%%HOME%%-$${HOME}',
+ keep_undefined: false
}
}
end
@@ -291,6 +320,14 @@ RSpec.describe Gitlab::Ci::Variables::Collection do
],
keep_undefined: false
},
+ "escaped characters in complex expansions are kept intact": {
+ variables: [
+ { key: 'variable3', value: 'key_${variable}_$${HOME}_%%HOME%%' },
+ { key: 'variable', value: '$variable2' },
+ { key: 'variable2', value: 'value2' }
+ ],
+ keep_undefined: false
+ },
"array with cyclic dependency": {
variables: [
{ key: 'variable', value: '$variable2' },
@@ -391,6 +428,30 @@ RSpec.describe Gitlab::Ci::Variables::Collection do
{ key: 'variable3', value: 'keyvalueresult' }
]
},
+ "escaped characters in complex expansions keeping undefined are kept intact": {
+ variables: [
+ { key: 'variable3', value: 'key_${variable}_$${HOME}_%%HOME%%' },
+ { key: 'variable', value: '$variable2' },
+ { key: 'variable2', value: 'value' }
+ ],
+ keep_undefined: true,
+ result: [
+ { key: 'variable', value: 'value' },
+ { key: 'variable2', value: 'value' },
+ { key: 'variable3', value: 'key_value_$${HOME}_%%HOME%%' }
+ ]
+ },
+ "escaped characters in complex expansions discarding undefined are kept intact": {
+ variables: [
+ { key: 'variable2', value: 'key_${variable4}_$${HOME}_%%HOME%%' },
+ { key: 'variable', value: 'value_$${HOME}_%%HOME%%' }
+ ],
+ keep_undefined: false,
+ result: [
+ { key: 'variable', value: 'value_$${HOME}_%%HOME%%' },
+ { key: 'variable2', value: 'key__$${HOME}_%%HOME%%' }
+ ]
+ },
"out-of-order expansion": {
variables: [
{ key: 'variable3', value: 'key$variable2$variable' },
@@ -417,7 +478,7 @@ RSpec.describe Gitlab::Ci::Variables::Collection do
{ key: 'variable3', value: 'keyresultvalue' }
]
},
- "missing variable": {
+ "missing variable discarding original": {
variables: [
{ key: 'variable2', value: 'key$variable' }
],
@@ -461,6 +522,19 @@ RSpec.describe Gitlab::Ci::Variables::Collection do
{ key: 'variable3', value: 'key_$variable2_value2' }
]
},
+ "variable value referencing password with special characters": {
+ variables: [
+ { key: 'VAR', value: '$PASSWORD' },
+ { key: 'PASSWORD', value: 'my_password$$_%%_$A' },
+ { key: 'A', value: 'value' }
+ ],
+ keep_undefined: false,
+ result: [
+ { key: 'VAR', value: 'my_password$$_%%_value' },
+ { key: 'PASSWORD', value: 'my_password$$_%%_value' },
+ { key: 'A', value: 'value' }
+ ]
+ },
"cyclic dependency causes original array to be returned": {
variables: [
{ key: 'variable', value: '$variable2' },
diff --git a/spec/lib/gitlab/ci/yaml_processor/result_spec.rb b/spec/lib/gitlab/ci/yaml_processor/result_spec.rb
index e345cd4de9b..25705fd4260 100644
--- a/spec/lib/gitlab/ci/yaml_processor/result_spec.rb
+++ b/spec/lib/gitlab/ci/yaml_processor/result_spec.rb
@@ -39,6 +39,59 @@ module Gitlab
expect(expanded_config).to include(*included_config.keys)
end
end
+
+ describe '#yaml_variables_for' do
+ let(:config_content) do
+ <<~YAML
+ variables:
+ VAR1: value 1
+ VAR2: value 2
+
+ job:
+ script: echo 'hello'
+ variables:
+ VAR1: value 11
+ YAML
+ end
+
+ let(:job_name) { :job }
+
+ subject(:yaml_variables_for) { result.yaml_variables_for(job_name) }
+
+ it 'returns calculated variables with root and job variables' do
+ is_expected.to match_array([
+ { key: 'VAR1', value: 'value 11', public: true },
+ { key: 'VAR2', value: 'value 2', public: true }
+ ])
+ end
+
+ context 'when an absent job is sent' do
+ let(:job_name) { :invalid_job }
+
+ it { is_expected.to eq([]) }
+ end
+ end
+
+ describe '#stage_for' do
+ let(:config_content) do
+ <<~YAML
+ job:
+ script: echo 'hello'
+ YAML
+ end
+
+ let(:job_name) { :job }
+
+ subject(:stage_for) { result.stage_for(job_name) }
+
+ it { is_expected.to eq('test') }
+
+ context 'when an absent job is sent' do
+ let(:job_name) { :invalid_job }
+
+ it { is_expected.to be_nil }
+ 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 94ab4819361..e8e44f884cf 100644
--- a/spec/lib/gitlab/ci/yaml_processor_spec.rb
+++ b/spec/lib/gitlab/ci/yaml_processor_spec.rb
@@ -485,10 +485,6 @@ module Gitlab
end
describe '#warnings' do
- before do
- stub_feature_flags(ci_raise_job_rules_without_workflow_rules_warning: true)
- end
-
context 'when a warning is raised in a given entry' do
let(:config) do
<<-EOYML
@@ -602,27 +598,6 @@ module Gitlab
it_behaves_like 'has warnings and expected error', /build job: need test is not defined in prior stages/
end
end
-
- context 'when feature flag is disabled' do
- before do
- stub_feature_flags(ci_raise_job_rules_without_workflow_rules_warning: false)
- end
-
- context 'job rules used without workflow rules' do
- let(:config) do
- <<-EOYML
- rspec:
- script: rspec
- rules:
- - when: always
- EOYML
- end
-
- it 'does not raise the warning' do
- expect(subject.warnings).to be_empty
- end
- end
- end
end
describe 'only / except policies validations' do