summaryrefslogtreecommitdiff
path: root/spec/lib
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-03-06 15:08:05 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-03-06 15:08:05 +0000
commitf78257cbddd711e18cbce93ad740a4aa0acac347 (patch)
tree7f018abe3ce1c0010879cc480f348a35e616fabb /spec/lib
parentf500600a43b531e2e7a5858b74bd35312b02c349 (diff)
downloadgitlab-ce-f78257cbddd711e18cbce93ad740a4aa0acac347.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/lib')
-rw-r--r--spec/lib/backup/manager_spec.rb17
-rw-r--r--spec/lib/gitlab/ci/artifact_file_reader_spec.rb100
-rw-r--r--spec/lib/gitlab/ci/config/entry/bridge_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/config/entry/job_spec.rb16
-rw-r--r--spec/lib/gitlab/ci/config/entry/jobs_spec.rb1
-rw-r--r--spec/lib/gitlab/ci/config/entry/processable_spec.rb105
-rw-r--r--spec/lib/gitlab/ci/config/entry/root_spec.rb17
-rw-r--r--spec/lib/gitlab/ci/config/external/file/artifact_spec.rb167
-rw-r--r--spec/lib/gitlab/ci/config/external/file/local_spec.rb17
-rw-r--r--spec/lib/gitlab/ci/config/external/file/project_spec.rb17
-rw-r--r--spec/lib/gitlab/ci/config_spec.rb88
-rw-r--r--spec/lib/gitlab/ci/yaml_processor_spec.rb76
-rw-r--r--spec/lib/gitlab/config/entry/attributable_spec.rb2
13 files changed, 555 insertions, 70 deletions
diff --git a/spec/lib/backup/manager_spec.rb b/spec/lib/backup/manager_spec.rb
index cee299522ce..b86e92d5969 100644
--- a/spec/lib/backup/manager_spec.rb
+++ b/spec/lib/backup/manager_spec.rb
@@ -319,18 +319,21 @@ describe Backup::Manager do
context 'when there is a non-tarred backup in the directory' do
before do
- allow(Dir).to receieve(:glob).and_return(
+ allow(Dir).to receive(:glob).and_return(
[
'backup_information.yml'
]
)
+ allow(File).to receive(:exist?).and_return(true)
+ end
+
+ it 'selects the non-tarred backup to restore from' do
+ expect(Kernel).not_to receive(:system)
- it 'selects the non-tarred backup to restore from' do
- expect { subject.unpack }.to output.to_stdout
- expect(progress).to have_received(:puts)
- .with(a_string_matching('Non tarred backup found '))
- expect(Kernel).not_to receive(:system)
- end
+ subject.unpack
+
+ expect(progress).to have_received(:puts)
+ .with(a_string_matching('Non tarred backup found '))
end
end
end
diff --git a/spec/lib/gitlab/ci/artifact_file_reader_spec.rb b/spec/lib/gitlab/ci/artifact_file_reader_spec.rb
new file mode 100644
index 00000000000..04017b9ae3e
--- /dev/null
+++ b/spec/lib/gitlab/ci/artifact_file_reader_spec.rb
@@ -0,0 +1,100 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Ci::ArtifactFileReader do
+ let(:job) { create(:ci_build) }
+ let(:path) { 'generated.yml' } # included in the ci_build_artifacts.zip
+
+ describe '#read' do
+ subject { described_class.new(job).read(path) }
+
+ context 'when job has artifacts and metadata' do
+ let!(:artifacts) { create(:ci_job_artifact, :archive, job: job) }
+ let!(:metadata) { create(:ci_job_artifact, :metadata, job: job) }
+
+ it 'returns the content at the path' do
+ is_expected.to be_present
+ expect(YAML.safe_load(subject).keys).to contain_exactly('rspec', 'time', 'custom')
+ end
+
+ context 'when path does not exist' do
+ let(:path) { 'file/does/not/exist.txt' }
+ let(:expected_error) do
+ "Path `#{path}` does not exist inside the `#{job.name}` artifacts archive!"
+ end
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(described_class::Error, expected_error)
+ end
+ end
+
+ context 'when path points to a directory' do
+ let(:path) { 'other_artifacts_0.1.2' }
+ let(:expected_error) do
+ "Path `#{path}` was expected to be a file but it was a directory!"
+ end
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(described_class::Error, expected_error)
+ end
+ end
+
+ context 'when path is nested' do
+ # path exists in ci_build_artifacts.zip
+ let(:path) { 'other_artifacts_0.1.2/doc_sample.txt' }
+
+ it 'returns the content at the nested path' do
+ is_expected.to be_present
+ end
+ end
+
+ context 'when artifact archive size is greater than the limit' do
+ let(:expected_error) do
+ "Artifacts archive for job `#{job.name}` is too large: max 1 KB"
+ end
+
+ before do
+ stub_const("#{described_class}::MAX_ARCHIVE_SIZE", 1.kilobyte)
+ end
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(described_class::Error, expected_error)
+ end
+ end
+
+ context 'when metadata entry shows size greater than the limit' do
+ let(:expected_error) do
+ "Artifacts archive for job `#{job.name}` is too large: max 5 MB"
+ end
+
+ before do
+ expect_next_instance_of(Gitlab::Ci::Build::Artifacts::Metadata::Entry) do |entry|
+ expect(entry).to receive(:total_size).and_return(10.megabytes)
+ end
+ end
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(described_class::Error, expected_error)
+ end
+ end
+ end
+
+ context 'when job does not have metadata artifacts' do
+ let!(:artifacts) { create(:ci_job_artifact, :archive, job: job) }
+ let(:expected_error) do
+ "Job `#{job.name}` has missing artifacts metadata and cannot be extracted!"
+ end
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(described_class::Error, expected_error)
+ end
+ end
+
+ context 'when job does not have artifacts' do
+ it 'raises ArgumentError' do
+ expect { subject }.to raise_error(ArgumentError, 'Job does not have artifacts')
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/config/entry/bridge_spec.rb b/spec/lib/gitlab/ci/config/entry/bridge_spec.rb
index ad388886681..d08ce30618d 100644
--- a/spec/lib/gitlab/ci/config/entry/bridge_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/bridge_spec.rb
@@ -106,6 +106,7 @@ describe Gitlab::Ci::Config::Entry::Bridge do
ignore: false,
stage: 'test',
only: { refs: %w[branches tags] },
+ variables: {},
scheduling_type: :stage)
end
end
@@ -128,6 +129,7 @@ describe Gitlab::Ci::Config::Entry::Bridge do
ignore: false,
stage: 'test',
only: { refs: %w[branches tags] },
+ variables: {},
scheduling_type: :stage)
end
end
diff --git a/spec/lib/gitlab/ci/config/entry/job_spec.rb b/spec/lib/gitlab/ci/config/entry/job_spec.rb
index 313b504ab59..7df0eccb3ed 100644
--- a/spec/lib/gitlab/ci/config/entry/job_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/job_spec.rb
@@ -6,6 +6,7 @@ describe Gitlab::Ci::Config::Entry::Job do
let(:entry) { described_class.new(config, name: :rspec) }
it_behaves_like 'with inheritable CI config' do
+ let(:config) { { script: 'echo' } }
let(:inheritable_key) { 'default' }
let(:inheritable_class) { Gitlab::Ci::Config::Entry::Default }
@@ -15,6 +16,10 @@ describe Gitlab::Ci::Config::Entry::Job do
let(:ignored_inheritable_columns) do
%i[]
end
+
+ before do
+ allow(entry).to receive_message_chain(:inherit_entry, :default_value).and_return(true)
+ end
end
describe '.nodes' do
@@ -24,7 +29,8 @@ describe Gitlab::Ci::Config::Entry::Job do
let(:result) do
%i[before_script script stage type after_script cache
image services only except rules needs variables artifacts
- environment coverage retry interruptible timeout release tags]
+ environment coverage retry interruptible timeout release tags
+ inherit]
end
it { is_expected.to match_array result }
@@ -500,7 +506,13 @@ describe Gitlab::Ci::Config::Entry::Job do
let(:unspecified) { double('unspecified', 'specified?' => false) }
let(:default) { double('default', '[]' => unspecified) }
let(:workflow) { double('workflow', 'has_rules?' => false) }
- let(:deps) { double('deps', 'default' => default, '[]' => unspecified, 'workflow' => workflow) }
+
+ let(:deps) do
+ double('deps',
+ 'default_entry' => default,
+ 'workflow_entry' => workflow,
+ 'variables_value' => nil)
+ end
context 'when job config overrides default config' do
before do
diff --git a/spec/lib/gitlab/ci/config/entry/jobs_spec.rb b/spec/lib/gitlab/ci/config/entry/jobs_spec.rb
index c8c188d71bf..203342ab620 100644
--- a/spec/lib/gitlab/ci/config/entry/jobs_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/jobs_spec.rb
@@ -99,6 +99,7 @@ describe Gitlab::Ci::Config::Entry::Jobs do
only: { refs: %w[branches tags] },
stage: 'test',
trigger: { project: 'my/project' },
+ variables: {},
scheduling_type: :stage
},
regular_job: {
diff --git a/spec/lib/gitlab/ci/config/entry/processable_spec.rb b/spec/lib/gitlab/ci/config/entry/processable_spec.rb
index 410aef1cd53..5c2c6520f25 100644
--- a/spec/lib/gitlab/ci/config/entry/processable_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/processable_spec.rb
@@ -7,6 +7,10 @@ describe Gitlab::Ci::Config::Entry::Processable do
Class.new(::Gitlab::Config::Entry::Node) do
include Gitlab::Ci::Config::Entry::Processable
+ entry :tags, ::Gitlab::Config::Entry::ArrayOfStrings,
+ description: 'Set the default tags.',
+ inherit: true
+
def self.name
'job'
end
@@ -189,14 +193,17 @@ describe Gitlab::Ci::Config::Entry::Processable do
end
describe '#compose!' do
- let(:specified) do
- double('specified', 'specified?' => true, value: 'specified')
- end
-
let(:unspecified) { double('unspecified', 'specified?' => false) }
let(:default) { double('default', '[]' => unspecified) }
let(:workflow) { double('workflow', 'has_rules?' => false) }
- let(:deps) { double('deps', 'default' => default, '[]' => unspecified, 'workflow' => workflow) }
+ let(:variables) { }
+
+ let(:deps) do
+ double('deps',
+ default_entry: default,
+ workflow_entry: workflow,
+ variables_value: variables)
+ end
context 'with workflow rules' do
using RSpec::Parameterized::TableSyntax
@@ -240,6 +247,84 @@ describe Gitlab::Ci::Config::Entry::Processable do
end
end
end
+
+ context 'with inheritance' do
+ context 'of variables' do
+ let(:config) do
+ { variables: { A: 'job', B: 'job' } }
+ end
+
+ before do
+ entry.compose!(deps)
+ end
+
+ context 'with only job variables' do
+ it 'does return defined variables' do
+ expect(entry.value).to include(
+ variables: { 'A' => 'job', 'B' => 'job' }
+ )
+ end
+ end
+
+ context 'when root yaml variables are used' do
+ let(:variables) do
+ Gitlab::Ci::Config::Entry::Variables.new(
+ A: 'root', C: 'root'
+ ).value
+ end
+
+ it 'does return all variables and overwrite them' do
+ expect(entry.value).to include(
+ variables: { 'A' => 'job', 'B' => 'job', 'C' => 'root' }
+ )
+ end
+
+ context 'when inherit of defaults is disabled' do
+ let(:config) do
+ {
+ variables: { A: 'job', B: 'job' },
+ inherit: { variables: false }
+ }
+ end
+
+ it 'does return only job variables' do
+ expect(entry.value).to include(
+ variables: { 'A' => 'job', 'B' => 'job' }
+ )
+ end
+ end
+ end
+ end
+
+ context 'of default:tags' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:default_tags, :tags, :inherit_default, :result) do
+ nil | %w[a b] | nil | %w[a b]
+ nil | %w[a b] | true | %w[a b]
+ nil | %w[a b] | false | %w[a b]
+ %w[b c] | %w[a b] | nil | %w[a b]
+ %w[b c] | %w[a b] | true | %w[a b]
+ %w[b c] | %w[a b] | false | %w[a b]
+ %w[b c] | nil | nil | %w[b c]
+ %w[b c] | nil | true | %w[b c]
+ %w[b c] | nil | false | nil
+ end
+
+ with_them do
+ let(:config) { { tags: tags, inherit: { default: inherit_default } } }
+ let(:default_specified_tags) { double('tags', 'specified?' => true, 'valid?' => true, 'value' => default_tags) }
+
+ before do
+ allow(default).to receive('[]').with(:tags).and_return(default_specified_tags)
+
+ entry.compose!(deps)
+ end
+
+ it { expect(entry.tags_value).to eq(result) }
+ end
+ end
+ end
end
context 'when composed' do
@@ -254,10 +339,12 @@ describe Gitlab::Ci::Config::Entry::Processable do
end
it 'returns correct value' do
- expect(entry.value)
- .to eq(name: :rspec,
- stage: 'test',
- only: { refs: %w[branches tags] })
+ expect(entry.value).to eq(
+ name: :rspec,
+ stage: 'test',
+ only: { refs: %w[branches tags] },
+ variables: {}
+ )
end
end
end
diff --git a/spec/lib/gitlab/ci/config/entry/root_spec.rb b/spec/lib/gitlab/ci/config/entry/root_spec.rb
index cf0a3cfa963..c3871b6b3cf 100644
--- a/spec/lib/gitlab/ci/config/entry/root_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/root_spec.rb
@@ -32,7 +32,7 @@ describe Gitlab::Ci::Config::Entry::Root do
image: 'ruby:2.2',
default: {},
services: ['postgres:9.1', 'mysql:5.5'],
- variables: { VAR: 'value' },
+ variables: { VAR: 'root' },
after_script: ['make clean'],
stages: %w(build pages release),
cache: { key: 'k', untracked: true, paths: ['public/'] },
@@ -42,6 +42,7 @@ describe Gitlab::Ci::Config::Entry::Root do
stage: 'release',
before_script: [],
after_script: [],
+ variables: { 'VAR' => 'job' },
script: ["make changelog | tee release_changelog.txt"],
release: {
tag_name: 'v0.06',
@@ -127,7 +128,7 @@ describe Gitlab::Ci::Config::Entry::Root do
services: [{ name: 'postgres:9.1' }, { name: 'mysql:5.5' }],
stage: 'test',
cache: { key: 'k', untracked: true, paths: ['public/'], policy: 'pull-push' },
- variables: {},
+ variables: { 'VAR' => 'root' },
ignore: false,
after_script: ['make clean'],
only: { refs: %w[branches tags] },
@@ -141,7 +142,7 @@ describe Gitlab::Ci::Config::Entry::Root do
services: [{ name: 'postgres:9.1' }, { name: 'mysql:5.5' }],
stage: 'test',
cache: { key: 'k', untracked: true, paths: ['public/'], policy: 'pull-push' },
- variables: {},
+ variables: { 'VAR' => 'root' },
ignore: false,
after_script: ['make clean'],
only: { refs: %w[branches tags] },
@@ -157,7 +158,7 @@ describe Gitlab::Ci::Config::Entry::Root do
services: [{ name: "postgres:9.1" }, { name: "mysql:5.5" }],
cache: { key: "k", untracked: true, paths: ["public/"], policy: "pull-push" },
only: { refs: %w(branches tags) },
- variables: {},
+ variables: { 'VAR' => 'job' },
after_script: [],
ignore: false,
scheduling_type: :stage }
@@ -175,11 +176,11 @@ describe Gitlab::Ci::Config::Entry::Root do
image: 'ruby:2.1',
services: ['postgres:9.1', 'mysql:5.5']
},
- variables: { VAR: 'value' },
+ variables: { VAR: 'root' },
stages: %w(build pages),
cache: { key: 'k', untracked: true, paths: ['public/'] },
rspec: { script: %w[rspec ls] },
- spinach: { before_script: [], variables: { VAR: 'AA' }, script: 'spinach' } }
+ spinach: { before_script: [], variables: { VAR: 'job' }, script: 'spinach' } }
end
context 'when composed' do
@@ -203,7 +204,7 @@ describe Gitlab::Ci::Config::Entry::Root do
services: [{ name: 'postgres:9.1' }, { name: 'mysql:5.5' }],
stage: 'test',
cache: { key: 'k', untracked: true, paths: ['public/'], policy: "pull-push" },
- variables: {},
+ variables: { 'VAR' => 'root' },
ignore: false,
after_script: ['make clean'],
only: { refs: %w[branches tags] },
@@ -215,7 +216,7 @@ describe Gitlab::Ci::Config::Entry::Root do
services: [{ name: 'postgres:9.1' }, { name: 'mysql:5.5' }],
stage: 'test',
cache: { key: 'k', untracked: true, paths: ['public/'], policy: "pull-push" },
- variables: { 'VAR' => 'AA' },
+ variables: { 'VAR' => 'job' },
ignore: false,
after_script: ['make clean'],
only: { refs: %w[branches tags] },
diff --git a/spec/lib/gitlab/ci/config/external/file/artifact_spec.rb b/spec/lib/gitlab/ci/config/external/file/artifact_spec.rb
new file mode 100644
index 00000000000..a8eb13c47bc
--- /dev/null
+++ b/spec/lib/gitlab/ci/config/external/file/artifact_spec.rb
@@ -0,0 +1,167 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Ci::Config::External::File::Artifact do
+ let(:parent_pipeline) { create(:ci_pipeline) }
+ let(:context) do
+ Gitlab::Ci::Config::External::Context.new(parent_pipeline: parent_pipeline)
+ end
+
+ let(:external_file) { described_class.new(params, context) }
+
+ describe '#matching?' do
+ context 'when params contain artifact location' do
+ let(:params) { { artifact: 'generated.yml' } }
+
+ it 'returns true' do
+ expect(external_file).to be_matching
+ end
+ end
+
+ context 'when params does not contain artifact location' do
+ let(:params) { {} }
+
+ it 'returns false' do
+ expect(external_file).not_to be_matching
+ end
+ end
+ end
+
+ describe '#valid?' do
+ shared_examples 'is invalid' do
+ it 'is not valid' do
+ expect(external_file).not_to be_valid
+ end
+
+ it 'sets the expected error' do
+ expect(external_file.errors)
+ .to contain_exactly(expected_error)
+ end
+ end
+
+ describe 'when used in non child pipeline context' do
+ let(:parent_pipeline) { nil }
+ let(:params) { { artifact: 'generated.yml' } }
+
+ let(:expected_error) do
+ 'Including configs from artifacts is only allowed when triggering child pipelines'
+ end
+
+ it_behaves_like 'is invalid'
+ end
+
+ context 'when used in child pipeline context' do
+ let(:parent_pipeline) { create(:ci_pipeline) }
+
+ context 'when job is not provided' do
+ let(:params) { { artifact: 'generated.yml' } }
+
+ let(:expected_error) do
+ 'Job must be provided when including configs from artifacts'
+ end
+
+ it_behaves_like 'is invalid'
+ end
+
+ context 'when job is provided' do
+ let(:params) { { artifact: 'generated.yml', job: 'generator' } }
+
+ context 'when job does not exist in the parent pipeline' do
+ let(:expected_error) do
+ 'Job `generator` not found in parent pipeline or does not have artifacts!'
+ end
+
+ it_behaves_like 'is invalid'
+ end
+
+ context 'when job exists in the parent pipeline' do
+ let!(:generator_job) { create(:ci_build, name: 'generator', pipeline: parent_pipeline) }
+
+ context 'when job does not have artifacts' do
+ let(:expected_error) do
+ 'Job `generator` not found in parent pipeline or does not have artifacts!'
+ end
+
+ it_behaves_like 'is invalid'
+ end
+
+ context 'when job has archive artifacts' do
+ let!(:artifacts) do
+ create(:ci_job_artifact, :archive,
+ job: generator_job,
+ file: fixture_file_upload(Rails.root.join('spec/fixtures/pages.zip'), 'application/zip'))
+ end
+
+ let(:expected_error) do
+ 'Job `generator` has missing artifacts metadata and cannot be extracted!'
+ end
+
+ it_behaves_like 'is invalid'
+
+ context 'when job has artifacts exceeding the max allowed size' do
+ let(:expected_error) do
+ "Artifacts archive for job `generator` is too large: max 1 KB"
+ end
+
+ before do
+ stub_const("#{Gitlab::Ci::ArtifactFileReader}::MAX_ARCHIVE_SIZE", 1.kilobyte)
+ end
+
+ it_behaves_like 'is invalid'
+ end
+
+ context 'when job has artifacts metadata' do
+ let!(:metadata) do
+ create(:ci_job_artifact, :metadata, job: generator_job)
+ end
+
+ let(:expected_error) do
+ 'Path `generated.yml` does not exist inside the `generator` artifacts archive!'
+ end
+
+ it_behaves_like 'is invalid'
+
+ context 'when file is found in metadata' do
+ let!(:artifacts) { create(:ci_job_artifact, :archive, job: generator_job) }
+ let!(:metadata) { create(:ci_job_artifact, :metadata, job: generator_job) }
+
+ context 'when file is empty' do
+ before do
+ allow_next_instance_of(Gitlab::Ci::ArtifactFileReader) do |reader|
+ allow(reader).to receive(:read).and_return('')
+ end
+ end
+
+ let(:expected_error) do
+ 'File `generated.yml` is empty!'
+ end
+
+ it_behaves_like 'is invalid'
+ end
+
+ context 'when file is not empty' do
+ it 'is valid' do
+ expect(external_file).to be_valid
+ expect(external_file.content).to be_present
+ end
+
+ it 'propagates parent_pipeline to nested includes' do
+ expected_attrs = {
+ parent_pipeline: parent_pipeline,
+ project: anything,
+ sha: anything,
+ user: anything
+ }
+ expect(context).to receive(:mutate).with(expected_attrs).and_call_original
+ external_file.content
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
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 53205a18762..c9851239859 100644
--- a/spec/lib/gitlab/ci/config/external/file/local_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/file/local_spec.rb
@@ -6,10 +6,19 @@ describe Gitlab::Ci::Config::External::File::Local do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:user) { create(:user) }
let(:sha) { '12345' }
- 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) }
+ let(:parent_pipeline) { double(:parent_pipeline) }
+
+ let(:context_params) do
+ {
+ project: project,
+ sha: sha,
+ user: user,
+ parent_pipeline: parent_pipeline
+ }
+ end
before do
allow_any_instance_of(Gitlab::Ci::Config::External::Context)
@@ -117,7 +126,11 @@ describe Gitlab::Ci::Config::External::File::Local do
subject { local_file.send(:expand_context_attrs) }
it 'inherits project, user and sha' do
- is_expected.to include(user: user, project: project, sha: sha)
+ is_expected.to include(
+ user: user,
+ project: project,
+ sha: sha,
+ parent_pipeline: parent_pipeline)
end
end
diff --git a/spec/lib/gitlab/ci/config/external/file/project_spec.rb b/spec/lib/gitlab/ci/config/external/file/project_spec.rb
index 77a71f9972b..b2924ae9d91 100644
--- a/spec/lib/gitlab/ci/config/external/file/project_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/file/project_spec.rb
@@ -7,10 +7,19 @@ describe Gitlab::Ci::Config::External::File::Project do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:user) { create(:user) }
let(:context_user) { user }
- let(:context_params) { { project: context_project, sha: '12345', user: context_user } }
+ let(:parent_pipeline) { double(:parent_pipeline) }
let(:context) { Gitlab::Ci::Config::External::Context.new(**context_params) }
let(:project_file) { described_class.new(params, context) }
+ let(:context_params) do
+ {
+ project: context_project,
+ sha: '12345',
+ user: context_user,
+ parent_pipeline: parent_pipeline
+ }
+ end
+
before do
project.add_developer(user)
@@ -152,7 +161,11 @@ describe Gitlab::Ci::Config::External::File::Project do
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)
+ is_expected.to include(
+ user: user,
+ project: project,
+ sha: project.commit('master').id,
+ parent_pipeline: parent_pipeline)
end
end
diff --git a/spec/lib/gitlab/ci/config_spec.rb b/spec/lib/gitlab/ci/config_spec.rb
index 525335cfea9..82ca8a29c5a 100644
--- a/spec/lib/gitlab/ci/config_spec.rb
+++ b/spec/lib/gitlab/ci/config_spec.rb
@@ -376,23 +376,6 @@ describe Gitlab::Ci::Config do
end
end
- context 'when context expansion timeout is disabled' do
- before do
- allow_next_instance_of(Gitlab::Ci::Config::External::Context) do |instance|
- allow(instance).to receive(:check_execution_time!).and_call_original
- end
-
- allow(Feature)
- .to receive(:enabled?)
- .with(:ci_limit_yaml_expansion, project, default_enabled: true)
- .and_return(false)
- end
-
- it 'does not raises errors' do
- expect { config }.not_to raise_error
- end
- end
-
describe 'external file version' do
context 'when external local file SHA is defined' do
it 'is using a defined value' do
@@ -541,5 +524,76 @@ describe Gitlab::Ci::Config do
end
end
end
+
+ context 'when including file from artifact' do
+ let(:config) do
+ described_class.new(
+ gitlab_ci_yml,
+ project: nil,
+ sha: nil,
+ user: nil,
+ parent_pipeline: parent_pipeline)
+ end
+
+ let(:gitlab_ci_yml) do
+ <<~HEREDOC
+ include:
+ - artifact: generated.yml
+ job: rspec
+ HEREDOC
+ end
+
+ let(:parent_pipeline) { nil }
+
+ context 'when used in the context of a child pipeline' do
+ # This job has ci_build_artifacts.zip artifact archive which
+ # contains generated.yml
+ let!(:job) { create(:ci_build, :artifacts, name: 'rspec', pipeline: parent_pipeline) }
+ let(:parent_pipeline) { create(:ci_pipeline) }
+
+ it 'returns valid config' do
+ expect(config).to be_valid
+ end
+
+ context 'when job key is missing' do
+ let(:gitlab_ci_yml) do
+ <<~HEREDOC
+ include:
+ - artifact: generated.yml
+ HEREDOC
+ end
+
+ it 'raises an error' do
+ expect { config }.to raise_error(
+ described_class::ConfigError,
+ 'Job must be provided when including configs from artifacts'
+ )
+ end
+ end
+
+ context 'when artifact key is missing' do
+ let(:gitlab_ci_yml) do
+ <<~HEREDOC
+ include:
+ - job: rspec
+ HEREDOC
+ end
+
+ it 'raises an error' do
+ expect { config }.to raise_error(
+ described_class::ConfigError,
+ /needs to match exactly one accessor!/
+ )
+ end
+ end
+ end
+
+ it 'disallows the use in parent pipelines' do
+ expect { config }.to raise_error(
+ described_class::ConfigError,
+ 'Including configs from artifacts is only allowed when triggering child pipelines'
+ )
+ 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 e303557bd00..5c85a136972 100644
--- a/spec/lib/gitlab/ci/yaml_processor_spec.rb
+++ b/spec/lib/gitlab/ci/yaml_processor_spec.rb
@@ -509,28 +509,44 @@ module Gitlab
describe "before_script" do
context "in global context" do
- let(:config) do
- {
- before_script: ["global script"],
- test: { script: ["script"] }
- }
+ using RSpec::Parameterized::TableSyntax
+
+ where(:inherit, :result) do
+ nil | ["global script"]
+ { default: false } | nil
+ { default: true } | ["global script"]
end
- it "return commands with scripts concatenated" do
- expect(subject[:options][:before_script]).to eq(["global script"])
+ with_them do
+ let(:config) do
+ {
+ before_script: ["global script"],
+ test: { script: ["script"], inherit: inherit }
+ }
+ end
+
+ it { expect(subject[:options][:before_script]).to eq(result) }
end
end
context "in default context" do
- let(:config) do
- {
- default: { before_script: ["global script"] },
- test: { script: ["script"] }
- }
+ using RSpec::Parameterized::TableSyntax
+
+ where(:inherit, :result) do
+ nil | ["global script"]
+ { default: false } | nil
+ { default: true } | ["global script"]
end
- it "return commands with scripts concatenated" do
- expect(subject[:options][:before_script]).to eq(["global script"])
+ with_them do
+ let(:config) do
+ {
+ default: { before_script: ["global script"] },
+ test: { script: ["script"], inherit: inherit }
+ }
+ end
+
+ it { expect(subject[:options][:before_script]).to eq(result) }
end
end
@@ -793,7 +809,7 @@ module Gitlab
context 'when job and global variables are defined' do
let(:global_variables) do
- { 'VAR1' => 'global1', 'VAR3' => 'global3' }
+ { 'VAR1' => 'global1', 'VAR3' => 'global3', 'VAR4' => 'global4' }
end
let(:job_variables) do
{ 'VAR1' => 'value1', 'VAR2' => 'value2' }
@@ -802,16 +818,32 @@ module Gitlab
{
before_script: ['pwd'],
variables: global_variables,
- rspec: { script: 'rspec', variables: job_variables }
+ rspec: { script: 'rspec', variables: job_variables, inherit: inherit }
}
end
- it 'returns all unique variables' do
- expect(subject).to contain_exactly(
- { key: 'VAR3', value: 'global3', public: true },
- { key: 'VAR1', value: 'value1', public: true },
- { key: 'VAR2', value: 'value2', public: true }
- )
+ context 'when no inheritance is specified' do
+ let(:inherit) { }
+
+ it 'returns all unique variables' do
+ expect(subject).to contain_exactly(
+ { key: 'VAR4', value: 'global4', public: true },
+ { key: 'VAR3', value: 'global3', public: true },
+ { key: 'VAR1', value: 'value1', public: true },
+ { key: 'VAR2', value: 'value2', public: true }
+ )
+ end
+ end
+
+ context 'when inheritance is disabled' do
+ let(:inherit) { { variables: false } }
+
+ it 'does not inherit variables' do
+ expect(subject).to contain_exactly(
+ { key: 'VAR1', value: 'value1', public: true },
+ { key: 'VAR2', value: 'value2', public: true }
+ )
+ end
end
end
diff --git a/spec/lib/gitlab/config/entry/attributable_spec.rb b/spec/lib/gitlab/config/entry/attributable_spec.rb
index bc29a194181..64a4670f483 100644
--- a/spec/lib/gitlab/config/entry/attributable_spec.rb
+++ b/spec/lib/gitlab/config/entry/attributable_spec.rb
@@ -59,7 +59,7 @@ describe Gitlab::Config::Entry::Attributable do
end
end
- expectation.to raise_error(ArgumentError, 'Method already defined: length')
+ expectation.to raise_error(ArgumentError, /Method 'length' already defined in/)
end
end
end