summaryrefslogtreecommitdiff
path: root/spec/lib/gitlab/ci/config
diff options
context:
space:
mode:
Diffstat (limited to 'spec/lib/gitlab/ci/config')
-rw-r--r--spec/lib/gitlab/ci/config/edge_stages_injector_spec.rb112
-rw-r--r--spec/lib/gitlab/ci/config/entry/cache_spec.rb1
-rw-r--r--spec/lib/gitlab/ci/config/entry/coverage_spec.rb7
-rw-r--r--spec/lib/gitlab/ci/config/entry/root_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/config/entry/rules/rule_spec.rb52
-rw-r--r--spec/lib/gitlab/ci/config/entry/stages_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/config/external/context_spec.rb128
-rw-r--r--spec/lib/gitlab/ci/config/external/file/base_spec.rb10
-rw-r--r--spec/lib/gitlab/ci/config/external/file/local_spec.rb11
-rw-r--r--spec/lib/gitlab/ci/config/external/file/project_spec.rb8
-rw-r--r--spec/lib/gitlab/ci/config/external/file/remote_spec.rb12
-rw-r--r--spec/lib/gitlab/ci/config/external/file/template_spec.rb12
-rw-r--r--spec/lib/gitlab/ci/config/external/mapper_spec.rb8
-rw-r--r--spec/lib/gitlab/ci/config/external/processor_spec.rb8
14 files changed, 354 insertions, 19 deletions
diff --git a/spec/lib/gitlab/ci/config/edge_stages_injector_spec.rb b/spec/lib/gitlab/ci/config/edge_stages_injector_spec.rb
new file mode 100644
index 00000000000..042f9b591b6
--- /dev/null
+++ b/spec/lib/gitlab/ci/config/edge_stages_injector_spec.rb
@@ -0,0 +1,112 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+describe Gitlab::Ci::Config::EdgeStagesInjector do
+ describe '#call' do
+ subject { described_class.new(config).to_hash }
+
+ context 'without stages' do
+ let(:config) do
+ {
+ test: { script: 'test' }
+ }
+ end
+
+ it { is_expected.to match config }
+ end
+
+ context 'with values' do
+ let(:config) do
+ {
+ stages: %w[stage1 stage2],
+ test: { script: 'test' }
+ }
+ end
+
+ let(:expected_stages) do
+ %w[.pre stage1 stage2 .post]
+ end
+
+ it { is_expected.to match(config.merge(stages: expected_stages)) }
+ end
+
+ context 'with bad values' do
+ let(:config) do
+ {
+ stages: 'stage1',
+ test: { script: 'test' }
+ }
+ end
+
+ it { is_expected.to match(config) }
+ end
+
+ context 'with collision values' do
+ let(:config) do
+ {
+ stages: %w[.post stage1 .pre .post stage2],
+ test: { script: 'test' }
+ }
+ end
+
+ let(:expected_stages) do
+ %w[.pre stage1 stage2 .post]
+ end
+
+ it { is_expected.to match(config.merge(stages: expected_stages)) }
+ end
+
+ context 'with types' do
+ let(:config) do
+ {
+ types: %w[stage1 stage2],
+ test: { script: 'test' }
+ }
+ end
+
+ let(:expected_config) do
+ {
+ types: %w[.pre stage1 stage2 .post],
+ test: { script: 'test' }
+ }
+ end
+
+ it { is_expected.to match expected_config }
+ end
+
+ context 'with types' do
+ let(:config) do
+ {
+ types: %w[.post stage1 .pre .post stage2],
+ test: { script: 'test' }
+ }
+ end
+
+ let(:expected_config) do
+ {
+ types: %w[.pre stage1 stage2 .post],
+ test: { script: 'test' }
+ }
+ end
+
+ it { is_expected.to match expected_config }
+ end
+ end
+
+ describe '.wrap_stages' do
+ subject { described_class.wrap_stages(stages) }
+
+ context 'with empty value' do
+ let(:stages) {}
+
+ it { is_expected.to eq %w[.pre .post] }
+ end
+
+ context 'with values' do
+ let(:stages) { %w[s1 .pre] }
+
+ it { is_expected.to eq %w[.pre s1 .post] }
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/config/entry/cache_spec.rb b/spec/lib/gitlab/ci/config/entry/cache_spec.rb
index 4cb63168ec7..9aab3664e1c 100644
--- a/spec/lib/gitlab/ci/config/entry/cache_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/cache_spec.rb
@@ -69,6 +69,7 @@ describe Gitlab::Ci::Config::Entry::Cache do
context 'when entry value is not correct' do
describe '#errors' do
subject { entry.errors }
+
context 'when is not a hash' do
let(:config) { 'ls' }
diff --git a/spec/lib/gitlab/ci/config/entry/coverage_spec.rb b/spec/lib/gitlab/ci/config/entry/coverage_spec.rb
index 48d0864cfca..877e3ec6216 100644
--- a/spec/lib/gitlab/ci/config/entry/coverage_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/coverage_spec.rb
@@ -11,11 +11,13 @@ describe Gitlab::Ci::Config::Entry::Coverage do
describe '#errors' do
subject { entry.errors }
+
it { is_expected.to include(/coverage config must be a regular expression/) }
end
describe '#valid?' do
subject { entry }
+
it { is_expected.not_to be_valid }
end
end
@@ -25,16 +27,19 @@ describe Gitlab::Ci::Config::Entry::Coverage do
describe '#value' do
subject { entry.value }
+
it { is_expected.to eq(config[1...-1]) }
end
describe '#errors' do
subject { entry.errors }
+
it { is_expected.to be_empty }
end
describe '#valid?' do
subject { entry }
+
it { is_expected.to be_valid }
end
end
@@ -44,11 +49,13 @@ describe Gitlab::Ci::Config::Entry::Coverage do
describe '#errors' do
subject { entry.errors }
+
it { is_expected.to include(/coverage config must be a regular expression/) }
end
describe '#valid?' do
subject { entry }
+
it { is_expected.not_to be_valid }
end
end
diff --git a/spec/lib/gitlab/ci/config/entry/root_spec.rb b/spec/lib/gitlab/ci/config/entry/root_spec.rb
index 968dbb9c7f2..7e1a80414d4 100644
--- a/spec/lib/gitlab/ci/config/entry/root_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/root_spec.rb
@@ -215,7 +215,7 @@ describe Gitlab::Ci::Config::Entry::Root do
describe '#stages_value' do
it 'returns an array of root stages' do
- expect(root.stages_value).to eq %w[build test deploy]
+ expect(root.stages_value).to eq %w[.pre build test deploy .post]
end
end
diff --git a/spec/lib/gitlab/ci/config/entry/rules/rule_spec.rb b/spec/lib/gitlab/ci/config/entry/rules/rule_spec.rb
index 18037a5612c..9d4f7153cd0 100644
--- a/spec/lib/gitlab/ci/config/entry/rules/rule_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/rules/rule_spec.rb
@@ -103,6 +103,52 @@ describe Gitlab::Ci::Config::Entry::Rules::Rule do
end
end
+ context 'when using a long list as an invalid changes: clause' do
+ let(:config) { { changes: ['app/'] * 51 } }
+
+ it { is_expected.not_to be_valid }
+
+ it 'returns errors' do
+ expect(subject.errors).to include(/changes is too long \(maximum is 50 characters\)/)
+ end
+ end
+
+ context 'when using a exists: clause' do
+ let(:config) { { exists: %w[app/ lib/ spec/ other/* paths/**/*.rb] } }
+
+ it { is_expected.to be_valid }
+ end
+
+ context 'when using a string as an invalid exists: clause' do
+ let(:config) { { exists: 'a regular string' } }
+
+ it { is_expected.not_to be_valid }
+
+ it 'reports an error about invalid policy' do
+ expect(subject.errors).to include(/should be an array of strings/)
+ end
+ end
+
+ context 'when using a list as an invalid exists: clause' do
+ let(:config) { { exists: [1, 2] } }
+
+ it { is_expected.not_to be_valid }
+
+ it 'returns errors' do
+ expect(subject.errors).to include(/exists should be an array of strings/)
+ end
+ end
+
+ context 'when using a long list as an invalid exists: clause' do
+ let(:config) { { exists: ['app/'] * 51 } }
+
+ it { is_expected.not_to be_valid }
+
+ it 'returns errors' do
+ expect(subject.errors).to include(/exists is too long \(maximum is 50 characters\)/)
+ end
+ end
+
context 'specifying a delayed job' do
let(:config) { { if: '$THIS || $THAT', when: 'delayed', start_in: '15 minutes' } }
@@ -198,6 +244,12 @@ describe Gitlab::Ci::Config::Entry::Rules::Rule do
expect(entry.value).to eq(config)
end
end
+
+ context 'when using a exists: clause' do
+ let(:config) { { exists: %w[app/ lib/ spec/ other/* paths/**/*.rb] } }
+
+ it { is_expected.to eq(config) }
+ end
end
describe '.default' do
diff --git a/spec/lib/gitlab/ci/config/entry/stages_spec.rb b/spec/lib/gitlab/ci/config/entry/stages_spec.rb
index 97970522104..3e6ff8eca28 100644
--- a/spec/lib/gitlab/ci/config/entry/stages_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/stages_spec.rb
@@ -42,7 +42,7 @@ describe Gitlab::Ci::Config::Entry::Stages do
describe '.default' do
it 'returns default stages' do
- expect(described_class.default).to eq %w[build test deploy]
+ expect(described_class.default).to eq %w[.pre build test deploy .post]
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
new file mode 100644
index 00000000000..610646ca85a
--- /dev/null
+++ b/spec/lib/gitlab/ci/config/external/context_spec.rb
@@ -0,0 +1,128 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+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 } }
+
+ subject(:subject) { described_class.new(**attributes) }
+
+ describe 'attributes' do
+ context 'with values' do
+ it { is_expected.to have_attributes(**attributes) }
+ it { expect(subject.expandset).to eq(Set.new) }
+ it { expect(subject.execution_deadline).to eq(0) }
+ end
+
+ context 'without values' do
+ let(:attributes) { { project: nil, user: nil, sha: nil } }
+
+ it { is_expected.to have_attributes(**attributes) }
+ it { expect(subject.expandset).to eq(Set.new) }
+ it { expect(subject.execution_deadline).to eq(0) }
+ end
+ end
+
+ describe '#set_deadline' do
+ let(:stubbed_time) { 1 }
+
+ before do
+ allow(subject).to receive(:current_monotonic_time).and_return(stubbed_time)
+ end
+
+ context 'with a float value' do
+ let(:timeout_seconds) { 10.5.seconds }
+
+ it 'updates execution_deadline' do
+ expect { subject.set_deadline(timeout_seconds) }
+ .to change { subject.execution_deadline }
+ .to(timeout_seconds + stubbed_time)
+ end
+ end
+
+ context 'with nil as a value' do
+ let(:timeout_seconds) {}
+
+ it 'updates execution_deadline' do
+ expect { subject.set_deadline(timeout_seconds) }
+ .to change { subject.execution_deadline }
+ .to(stubbed_time)
+ end
+ end
+ end
+
+ describe '#check_execution_time!' do
+ before do
+ allow(subject).to receive(:current_monotonic_time).and_return(stubbed_time)
+ allow(subject).to receive(:execution_deadline).and_return(stubbed_deadline)
+ end
+
+ context 'when execution is expired' do
+ let(:stubbed_time) { 2 }
+ let(:stubbed_deadline) { 1 }
+
+ it 'raises an error' do
+ expect { subject.check_execution_time! }
+ .to raise_error(described_class::TimeoutError)
+ end
+ end
+
+ context 'when execution is not expired' do
+ let(:stubbed_time) { 1 }
+ let(:stubbed_deadline) { 2 }
+
+ it 'does not raises any errors' do
+ expect { subject.check_execution_time! }.not_to raise_error
+ end
+ end
+
+ context 'without setting a deadline' do
+ let(:stubbed_time) { 2 }
+ let(:stubbed_deadline) { 1 }
+
+ before do
+ allow(subject).to receive(:execution_deadline).and_call_original
+ end
+
+ it 'does not raises any errors' do
+ expect { subject.check_execution_time! }.not_to raise_error
+ end
+ end
+ end
+
+ describe '#mutate' do
+ shared_examples 'a mutated context' do
+ let(:mutated) { subject.mutate(new_attributes) }
+
+ before do
+ subject.expandset << :a_file
+ subject.set_deadline(15.seconds)
+ end
+
+ it { expect(mutated).not_to eq(subject) }
+ it { expect(mutated).to be_a(described_class) }
+ 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) }
+ end
+
+ context 'with attributes' do
+ let(:new_attributes) { { project: double, user: double, sha: '56789' } }
+
+ it_behaves_like 'a mutated context'
+ end
+
+ context 'without attributes' do
+ let(:new_attributes) { {} }
+
+ it_behaves_like 'a mutated context'
+ end
+ end
+
+ describe '#sentry_payload' do
+ it { expect(subject.sentry_payload).to match(a_hash_including(:project, :user)) }
+ end
+end
diff --git a/spec/lib/gitlab/ci/config/external/file/base_spec.rb b/spec/lib/gitlab/ci/config/external/file/base_spec.rb
index af995f4869a..d472d6527e2 100644
--- a/spec/lib/gitlab/ci/config/external/file/base_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/file/base_spec.rb
@@ -1,13 +1,14 @@
# frozen_string_literal: true
-require 'fast_spec_helper'
+require 'spec_helper'
describe Gitlab::Ci::Config::External::File::Base do
- let(:context) { described_class::Context.new(nil, 'HEAD', nil, Set.new) }
+ let(:context_params) { { sha: 'HEAD' } }
+ let(:context) { Gitlab::Ci::Config::External::Context.new(**context_params) }
let(:test_class) do
Class.new(described_class) do
- def initialize(params, context = {})
+ def initialize(params, context)
@location = params
super
@@ -20,6 +21,9 @@ describe Gitlab::Ci::Config::External::File::Base do
before do
allow_any_instance_of(test_class)
.to receive(:content).and_return('key: value')
+
+ allow_any_instance_of(Gitlab::Ci::Config::External::Context)
+ .to receive(:check_execution_time!)
end
describe '#matching?' 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 9451db9522a..95f0c93e758 100644
--- a/spec/lib/gitlab/ci/config/external/file/local_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/file/local_spec.rb
@@ -7,10 +7,17 @@ describe Gitlab::Ci::Config::External::File::Local do
set(:user) { create(:user) }
let(:sha) { '12345' }
- let(:context) { described_class::Context.new(project, sha, user, Set.new) }
+ let(:context_params) { { project: project, sha: sha, user: user } }
+ let(:context) { Gitlab::Ci::Config::External::Context.new(**context_params) }
+
let(:params) { { local: location } }
let(:local_file) { described_class.new(params, context) }
+ before do
+ allow_any_instance_of(Gitlab::Ci::Config::External::Context)
+ .to receive(:check_execution_time!)
+ end
+
describe '#matching?' do
context 'when a local is specified' do
let(:params) { { local: 'file' } }
@@ -109,7 +116,7 @@ describe Gitlab::Ci::Config::External::File::Local do
describe '#expand_context' do
let(:location) { 'location.yml' }
- subject { local_file.send(:expand_context) }
+ subject { local_file.send(:expand_context_attrs) }
it 'inherits project, user and sha' do
is_expected.to include(user: user, project: project, sha: sha)
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 4acb4f324d3..dd869c227a1 100644
--- a/spec/lib/gitlab/ci/config/external/file/project_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/file/project_spec.rb
@@ -8,11 +8,15 @@ describe Gitlab::Ci::Config::External::File::Project do
set(:user) { create(:user) }
let(:context_user) { user }
- let(:context) { described_class::Context.new(context_project, '12345', context_user, Set.new) }
+ let(:context_params) { { project: context_project, sha: '12345', user: context_user } }
+ let(:context) { Gitlab::Ci::Config::External::Context.new(**context_params) }
let(:project_file) { described_class.new(params, context) }
before do
project.add_developer(user)
+
+ allow_any_instance_of(Gitlab::Ci::Config::External::Context)
+ .to receive(:check_execution_time!)
end
describe '#matching?' do
@@ -145,7 +149,7 @@ describe Gitlab::Ci::Config::External::File::Project do
describe '#expand_context' do
let(:params) { { file: 'file.yml', project: project.full_path, ref: 'master' } }
- subject { project_file.send(:expand_context) }
+ subject { project_file.send(:expand_context_attrs) }
it 'inherits user, and target project and sha' do
is_expected.to include(user: user, project: project, sha: project.commit('master').id)
diff --git a/spec/lib/gitlab/ci/config/external/file/remote_spec.rb b/spec/lib/gitlab/ci/config/external/file/remote_spec.rb
index 4a097b59216..08db00dda9d 100644
--- a/spec/lib/gitlab/ci/config/external/file/remote_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/file/remote_spec.rb
@@ -5,7 +5,8 @@ require 'spec_helper'
describe Gitlab::Ci::Config::External::File::Remote do
include StubRequests
- let(:context) { described_class::Context.new(nil, '12345', nil, Set.new) }
+ let(:context_params) { { sha: '12345' } }
+ let(:context) { Gitlab::Ci::Config::External::Context.new(**context_params) }
let(:params) { { remote: location } }
let(:remote_file) { described_class.new(params, context) }
let(:location) { 'https://gitlab.com/gitlab-org/gitlab-foss/blob/1234/.gitlab-ci-1.yml' }
@@ -19,6 +20,11 @@ describe Gitlab::Ci::Config::External::File::Remote do
HEREDOC
end
+ before do
+ allow_any_instance_of(Gitlab::Ci::Config::External::Context)
+ .to receive(:check_execution_time!)
+ end
+
describe '#matching?' do
context 'when a remote is specified' do
let(:params) { { remote: 'http://remote' } }
@@ -187,10 +193,10 @@ describe Gitlab::Ci::Config::External::File::Remote do
describe '#expand_context' do
let(:params) { { remote: 'http://remote' } }
- subject { remote_file.send(:expand_context) }
+ subject { remote_file.send(:expand_context_attrs) }
it 'drops all parameters' do
- is_expected.to include(user: nil, project: nil, sha: nil)
+ is_expected.to be_empty
end
end
end
diff --git a/spec/lib/gitlab/ci/config/external/file/template_spec.rb b/spec/lib/gitlab/ci/config/external/file/template_spec.rb
index 1609b8fd66b..164b5800abf 100644
--- a/spec/lib/gitlab/ci/config/external/file/template_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/file/template_spec.rb
@@ -6,12 +6,18 @@ describe Gitlab::Ci::Config::External::File::Template do
set(:project) { create(:project) }
set(:user) { create(:user) }
- let(:context) { described_class::Context.new(project, '12345', user, Set.new) }
+ let(:context_params) { { project: project, sha: '12345', user: user } }
+ let(:context) { Gitlab::Ci::Config::External::Context.new(**context_params) }
let(:template) { 'Auto-DevOps.gitlab-ci.yml' }
let(:params) { { template: template } }
let(:template_file) { described_class.new(params, context) }
+ before do
+ allow_any_instance_of(Gitlab::Ci::Config::External::Context)
+ .to receive(:check_execution_time!)
+ end
+
describe '#matching?' do
context 'when a template is specified' do
let(:params) { { template: 'some-template' } }
@@ -97,10 +103,10 @@ describe Gitlab::Ci::Config::External::File::Template do
describe '#expand_context' do
let(:location) { 'location.yml' }
- subject { template_file.send(:expand_context) }
+ subject { template_file.send(:expand_context_attrs) }
it 'drops all parameters' do
- is_expected.to include(user: nil, project: nil, sha: nil)
+ is_expected.to be_empty
end
end
end
diff --git a/spec/lib/gitlab/ci/config/external/mapper_spec.rb b/spec/lib/gitlab/ci/config/external/mapper_spec.rb
index 43708852594..8d09aa47f12 100644
--- a/spec/lib/gitlab/ci/config/external/mapper_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/mapper_spec.rb
@@ -11,7 +11,8 @@ 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(:expandset) { Set.new }
+ let(:context_params) { { project: project, sha: '123456', user: user } }
+ let(:context) { Gitlab::Ci::Config::External::Context.new(**context_params) }
let(:file_content) do
<<~HEREDOC
@@ -21,10 +22,13 @@ describe Gitlab::Ci::Config::External::Mapper do
before do
stub_full_request(remote_url).to_return(body: file_content)
+
+ allow_any_instance_of(Gitlab::Ci::Config::External::Context)
+ .to receive(:check_execution_time!)
end
describe '#process' do
- subject { described_class.new(values, project: project, sha: '123456', user: user, expandset: expandset).process }
+ subject { described_class.new(values, context).process }
context "when single 'include' keyword is defined" do
context 'when the string is a local file' do
diff --git a/spec/lib/gitlab/ci/config/external/processor_spec.rb b/spec/lib/gitlab/ci/config/external/processor_spec.rb
index 3b1a1e804f0..bb2d3f66972 100644
--- a/spec/lib/gitlab/ci/config/external/processor_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/processor_spec.rb
@@ -9,12 +9,16 @@ describe Gitlab::Ci::Config::External::Processor do
set(:another_project) { create(:project, :repository) }
set(:user) { create(:user) }
- let(:expandset) { Set.new }
let(:sha) { '12345' }
- let(:processor) { described_class.new(values, project: project, sha: '12345', user: user, expandset: expandset) }
+ let(:context_params) { { project: project, sha: sha, user: user } }
+ let(:context) { Gitlab::Ci::Config::External::Context.new(**context_params) }
+ let(:processor) { described_class.new(values, context) }
before do
project.add_developer(user)
+
+ allow_any_instance_of(Gitlab::Ci::Config::External::Context)
+ .to receive(:check_execution_time!)
end
describe "#perform" do