diff options
Diffstat (limited to 'spec/lib/gitlab/ci/config/external/file')
6 files changed, 283 insertions, 63 deletions
diff --git a/spec/lib/gitlab/ci/config/external/file/artifact_spec.rb b/spec/lib/gitlab/ci/config/external/file/artifact_spec.rb index b59fc95a8cc..9da8d106862 100644 --- a/spec/lib/gitlab/ci/config/external/file/artifact_spec.rb +++ b/spec/lib/gitlab/ci/config/external/file/artifact_spec.rb @@ -4,8 +4,9 @@ require 'spec_helper' RSpec.describe Gitlab::Ci::Config::External::File::Artifact do let(:parent_pipeline) { create(:ci_pipeline) } + let(:variables) {} let(:context) do - Gitlab::Ci::Config::External::Context.new(parent_pipeline: parent_pipeline) + Gitlab::Ci::Config::External::Context.new(variables: variables, parent_pipeline: parent_pipeline) end let(:external_file) { described_class.new(params, context) } @@ -29,14 +30,15 @@ RSpec.describe Gitlab::Ci::Config::External::File::Artifact do end describe '#valid?' do - shared_examples 'is invalid' do - it 'is not valid' do - expect(external_file).not_to be_valid - end + subject(:valid?) do + external_file.validate! + external_file.valid? + end + shared_examples 'is invalid' do it 'sets the expected error' do - expect(external_file.errors) - .to contain_exactly(expected_error) + expect(valid?).to be_falsy + expect(external_file.errors).to contain_exactly(expected_error) end end @@ -148,7 +150,7 @@ RSpec.describe Gitlab::Ci::Config::External::File::Artifact do context 'when file is not empty' do it 'is valid' do - expect(external_file).to be_valid + expect(valid?).to be_truthy expect(external_file.content).to be_present end @@ -160,6 +162,7 @@ RSpec.describe Gitlab::Ci::Config::External::File::Artifact do user: anything } expect(context).to receive(:mutate).with(expected_attrs).and_call_original + external_file.validate! external_file.content end end @@ -168,6 +171,58 @@ RSpec.describe Gitlab::Ci::Config::External::File::Artifact do end end end + + context 'when job is provided as a variable' do + let(:variables) do + Gitlab::Ci::Variables::Collection.new([ + { key: 'VAR1', value: 'a_secret_variable_value', masked: true } + ]) + end + + let(:params) { { artifact: 'generated.yml', job: 'a_secret_variable_value' } } + + context 'when job does not exist in the parent pipeline' do + let(:expected_error) do + 'Job `xxxxxxxxxxxxxxxxxxxxxxx` not found in parent pipeline or does not have artifacts!' + end + + it_behaves_like 'is invalid' + end + end + end + end + + describe '#metadata' do + let(:params) { { artifact: 'generated.yml' } } + + subject(:metadata) { external_file.metadata } + + it { + is_expected.to eq( + context_project: nil, + context_sha: nil, + type: :artifact, + location: 'generated.yml', + extra: { job_name: nil } + ) + } + + context 'when job name includes a masked variable' do + let(:variables) do + Gitlab::Ci::Variables::Collection.new([{ key: 'VAR1', value: 'a_secret_variable_value', masked: true }]) + end + + let(:params) { { artifact: 'generated.yml', job: 'a_secret_variable_value' } } + + it { + is_expected.to eq( + context_project: nil, + context_sha: nil, + type: :artifact, + location: 'generated.yml', + extra: { job_name: 'xxxxxxxxxxxxxxxxxxxxxxx' } + ) + } end 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 536f48ecba6..280bebe1a7c 100644 --- a/spec/lib/gitlab/ci/config/external/file/base_spec.rb +++ b/spec/lib/gitlab/ci/config/external/file/base_spec.rb @@ -17,7 +17,7 @@ RSpec.describe Gitlab::Ci::Config::External::File::Base do end end - subject { test_class.new(location, context) } + subject(:file) { test_class.new(location, context) } before do allow_any_instance_of(test_class) @@ -32,7 +32,7 @@ RSpec.describe Gitlab::Ci::Config::External::File::Base do let(:location) { 'some-location' } it 'returns true' do - expect(subject).to be_matching + expect(file).to be_matching end end @@ -40,40 +40,45 @@ RSpec.describe Gitlab::Ci::Config::External::File::Base do let(:location) { nil } it 'returns false' do - expect(subject).not_to be_matching + expect(file).not_to be_matching end end end describe '#valid?' do + subject(:valid?) do + file.validate! + file.valid? + end + context 'when location is not a string' do let(:location) { %w(some/file.txt other/file.txt) } - it { is_expected.not_to be_valid } + it { is_expected.to be_falsy } end context 'when location is not a YAML file' do let(:location) { 'some/file.txt' } - it { is_expected.not_to be_valid } + it { is_expected.to be_falsy } end context 'when location has not a valid naming scheme' do let(:location) { 'some/file/.yml' } - it { is_expected.not_to be_valid } + it { is_expected.to be_falsy } end context 'when location is a valid .yml extension' do let(:location) { 'some/file/config.yml' } - it { is_expected.to be_valid } + it { is_expected.to be_truthy } end context 'when location is a valid .yaml extension' do let(:location) { 'some/file/config.yaml' } - it { is_expected.to be_valid } + it { is_expected.to be_truthy } end context 'when there are YAML syntax errors' do @@ -86,8 +91,8 @@ RSpec.describe Gitlab::Ci::Config::External::File::Base do end it 'is not a valid file' do - expect(subject).not_to be_valid - expect(subject.error_message).to eq('Included file `some/file/xxxxxxxxxxxxxxxx.yml` does not have valid YAML syntax!') + expect(valid?).to be_falsy + expect(file.error_message).to eq('Included file `some/file/xxxxxxxxxxxxxxxx.yml` does not have valid YAML syntax!') end end end @@ -103,8 +108,56 @@ RSpec.describe Gitlab::Ci::Config::External::File::Base do end it 'does expand hash to include the template' do - expect(subject.to_hash).to include(:before_script) + expect(file.to_hash).to include(:before_script) end end end + + describe '#metadata' do + let(:location) { 'some/file/config.yml' } + + subject(:metadata) { file.metadata } + + it { + is_expected.to eq( + context_project: nil, + context_sha: 'HEAD' + ) + } + end + + describe '#eql?' do + let(:location) { 'some/file/config.yml' } + + subject(:eql) { file.eql?(other_file) } + + context 'when the other file has the same params' do + let(:other_file) { test_class.new(location, context) } + + it { is_expected.to eq(true) } + end + + context 'when the other file has not the same params' do + let(:other_file) { test_class.new('some/other/file', context) } + + it { is_expected.to eq(false) } + end + end + + describe '#hash' do + let(:location) { 'some/file/config.yml' } + + subject(:filehash) { file.hash } + + context 'with a project' do + let(:project) { create(:project) } + let(:context_params) { { project: project, sha: 'HEAD', variables: variables } } + + it { is_expected.to eq([location, project.full_path, 'HEAD'].hash) } + end + + context 'without a project' do + it { is_expected.to eq([location, nil, 'HEAD'].hash) } + 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 b9314dfc44e..c0a0b0009ce 100644 --- a/spec/lib/gitlab/ci/config/external/file/local_spec.rb +++ b/spec/lib/gitlab/ci/config/external/file/local_spec.rb @@ -55,6 +55,11 @@ RSpec.describe Gitlab::Ci::Config::External::File::Local do end describe '#valid?' do + subject(:valid?) do + local_file.validate! + local_file.valid? + end + context 'when is a valid local path' do let(:location) { '/lib/gitlab/ci/templates/existent-file.yml' } @@ -62,25 +67,19 @@ RSpec.describe Gitlab::Ci::Config::External::File::Local do allow_any_instance_of(described_class).to receive(:fetch_local_content).and_return("image: 'ruby2:2'") end - it 'returns true' do - expect(local_file.valid?).to be_truthy - end + it { is_expected.to be_truthy } end context 'when it is not a valid local path' do let(:location) { '/lib/gitlab/ci/templates/non-existent-file.yml' } - it 'returns false' do - expect(local_file.valid?).to be_falsy - end + it { is_expected.to be_falsy } end context 'when it is not a yaml file' do let(:location) { '/config/application.rb' } - it 'returns false' do - expect(local_file.valid?).to be_falsy - end + it { is_expected.to be_falsy } end context 'when it is an empty file' do @@ -89,6 +88,7 @@ RSpec.describe Gitlab::Ci::Config::External::File::Local do it 'returns false and adds an error message about an empty file' do allow_any_instance_of(described_class).to receive(:fetch_local_content).and_return("") + local_file.validate! expect(local_file.errors).to include("Local file `/lib/gitlab/ci/templates/xxxxxx/existent-file.yml` is empty!") end end @@ -98,7 +98,7 @@ RSpec.describe Gitlab::Ci::Config::External::File::Local do let(:sha) { ':' } it 'returns false and adds an error message stating that included file does not exist' do - expect(local_file).not_to be_valid + expect(valid?).to be_falsy expect(local_file.errors).to include("Sha #{sha} is not valid!") end end @@ -140,6 +140,10 @@ RSpec.describe Gitlab::Ci::Config::External::File::Local do let(:location) { '/lib/gitlab/ci/templates/secret_file.yml' } let(:variables) { Gitlab::Ci::Variables::Collection.new([{ 'key' => 'GITLAB_TOKEN', 'value' => 'secret_file', 'masked' => true }]) } + before do + local_file.validate! + end + it 'returns an error message' do expect(local_file.error_message).to eq("Local file `/lib/gitlab/ci/templates/xxxxxxxxxxx.yml` does not exist!") end @@ -174,6 +178,8 @@ RSpec.describe Gitlab::Ci::Config::External::File::Local do allow(project.repository).to receive(:blob_data_at).with(sha, another_location) .and_return(another_content) + + local_file.validate! end it 'does expand hash to include the template' do @@ -181,4 +187,20 @@ RSpec.describe Gitlab::Ci::Config::External::File::Local do end end end + + describe '#metadata' do + let(:location) { '/lib/gitlab/ci/templates/existent-file.yml' } + + subject(:metadata) { local_file.metadata } + + it { + is_expected.to eq( + context_project: project.full_path, + context_sha: '12345', + type: :local, + location: location, + extra: {} + ) + } + 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 74720c0a3ca..5d3412a148b 100644 --- a/spec/lib/gitlab/ci/config/external/file/project_spec.rb +++ b/spec/lib/gitlab/ci/config/external/file/project_spec.rb @@ -66,6 +66,11 @@ RSpec.describe Gitlab::Ci::Config::External::File::Project do end describe '#valid?' do + subject(:valid?) do + project_file.validate! + project_file.valid? + end + context 'when a valid path is used' do let(:params) do { project: project.full_path, file: '/file.yml' } @@ -74,18 +79,16 @@ RSpec.describe Gitlab::Ci::Config::External::File::Project do let(:root_ref_sha) { project.repository.root_ref_sha } before do - stub_project_blob(root_ref_sha, '/file.yml') { 'image: ruby:2.7' } + stub_project_blob(root_ref_sha, '/file.yml') { 'image: image:1.0' } end - it 'returns true' do - expect(project_file).to be_valid - end + it { is_expected.to be_truthy } context 'when user does not have permission to access file' do let(:context_user) { create(:user) } it 'returns false' do - expect(project_file).not_to be_valid + expect(valid?).to be_falsy expect(project_file.error_message).to include("Project `#{project.full_path}` not found or access denied!") end end @@ -99,12 +102,10 @@ RSpec.describe Gitlab::Ci::Config::External::File::Project do let(:ref_sha) { project.commit('master').sha } before do - stub_project_blob(ref_sha, '/file.yml') { 'image: ruby:2.7' } + stub_project_blob(ref_sha, '/file.yml') { 'image: image:1.0' } end - it 'returns true' do - expect(project_file).to be_valid - end + it { is_expected.to be_truthy } end context 'when an empty file is used' do @@ -120,7 +121,7 @@ RSpec.describe Gitlab::Ci::Config::External::File::Project do end it 'returns false' do - expect(project_file).not_to be_valid + expect(valid?).to be_falsy expect(project_file.error_message).to include("Project `#{project.full_path}` file `/xxxxxxxxxxx.yml` is empty!") end end @@ -131,7 +132,7 @@ RSpec.describe Gitlab::Ci::Config::External::File::Project do end it 'returns false' do - expect(project_file).not_to be_valid + expect(valid?).to be_falsy expect(project_file.error_message).to include("Project `#{project.full_path}` reference `I-Do-Not-Exist` does not exist!") end end @@ -144,7 +145,7 @@ RSpec.describe Gitlab::Ci::Config::External::File::Project do end it 'returns false' do - expect(project_file).not_to be_valid + expect(valid?).to be_falsy expect(project_file.error_message).to include("Project `#{project.full_path}` file `/xxxxxxxxxxxxxxxxxxx.yml` does not exist!") end end @@ -155,10 +156,27 @@ RSpec.describe Gitlab::Ci::Config::External::File::Project do end it 'returns false' do - expect(project_file).not_to be_valid + expect(valid?).to be_falsy expect(project_file.error_message).to include('Included file `/invalid-file` does not have YAML extension!') end end + + context 'when non-existing project is used with a masked variable' do + let(:variables) do + Gitlab::Ci::Variables::Collection.new([ + { key: 'VAR1', value: 'a_secret_variable_value', masked: true } + ]) + end + + let(:params) do + { project: 'a_secret_variable_value', file: '/file.yml' } + end + + it 'returns false with masked project name' do + expect(valid?).to be_falsy + expect(project_file.error_message).to include("Project `xxxxxxxxxxxxxxxxxxxxxxx` not found or access denied!") + end + end end describe '#expand_context' do @@ -176,6 +194,45 @@ RSpec.describe Gitlab::Ci::Config::External::File::Project do end end + describe '#metadata' do + let(:params) do + { project: project.full_path, file: '/file.yml' } + end + + subject(:metadata) { project_file.metadata } + + it { + is_expected.to eq( + context_project: context_project.full_path, + context_sha: '12345', + type: :file, + location: '/file.yml', + extra: { project: project.full_path, ref: 'HEAD' } + ) + } + + context 'when project name and ref include masked variables' do + let(:variables) do + Gitlab::Ci::Variables::Collection.new([ + { key: 'VAR1', value: 'a_secret_variable_value1', masked: true }, + { key: 'VAR2', value: 'a_secret_variable_value2', masked: true } + ]) + end + + let(:params) { { project: 'a_secret_variable_value1', ref: 'a_secret_variable_value2', file: '/file.yml' } } + + it { + is_expected.to eq( + context_project: context_project.full_path, + context_sha: '12345', + type: :file, + location: '/file.yml', + extra: { project: 'xxxxxxxxxxxxxxxxxxxxxxxx', ref: 'xxxxxxxxxxxxxxxxxxxxxxxx' } + ) + } + end + end + private def stub_project_blob(ref, path) 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 2613bfbfdcf..5c07c87fd5a 100644 --- a/spec/lib/gitlab/ci/config/external/file/remote_spec.rb +++ b/spec/lib/gitlab/ci/config/external/file/remote_spec.rb @@ -54,22 +54,23 @@ RSpec.describe Gitlab::Ci::Config::External::File::Remote do end describe "#valid?" do + subject(:valid?) do + remote_file.validate! + remote_file.valid? + end + context 'when is a valid remote url' do before do stub_full_request(location).to_return(body: remote_file_content) end - it 'returns true' do - expect(remote_file.valid?).to be_truthy - end + it { is_expected.to be_truthy } end context 'with an irregular url' do let(:location) { 'not-valid://gitlab.com/gitlab-org/gitlab-foss/blob/1234/.gitlab-ci-1.yml' } - it 'returns false' do - expect(remote_file.valid?).to be_falsy - end + it { is_expected.to be_falsy } end context 'with a timeout' do @@ -77,25 +78,19 @@ RSpec.describe Gitlab::Ci::Config::External::File::Remote do allow(Gitlab::HTTP).to receive(:get).and_raise(Timeout::Error) end - it 'is falsy' do - expect(remote_file.valid?).to be_falsy - end + it { is_expected.to be_falsy } end context 'when is not a yaml file' do let(:location) { 'https://asdasdasdaj48ggerexample.com' } - it 'is falsy' do - expect(remote_file.valid?).to be_falsy - end + it { is_expected.to be_falsy } end context 'with an internal url' do let(:location) { 'http://localhost:8080' } - it 'is falsy' do - expect(remote_file.valid?).to be_falsy - end + it { is_expected.to be_falsy } end end @@ -142,7 +137,10 @@ RSpec.describe Gitlab::Ci::Config::External::File::Remote do end describe "#error_message" do - subject { remote_file.error_message } + subject(:error_message) do + remote_file.validate! + remote_file.error_message + end context 'when remote file location is not valid' do let(:location) { 'not-valid://gitlab.com/gitlab-org/gitlab-foss/blob/1234/?secret_file.yml' } @@ -201,4 +199,22 @@ RSpec.describe Gitlab::Ci::Config::External::File::Remote do is_expected.to be_empty end end + + describe '#metadata' do + before do + stub_full_request(location).to_return(body: remote_file_content) + end + + subject(:metadata) { remote_file.metadata } + + it { + is_expected.to eq( + context_project: nil, + context_sha: '12345', + type: :remote, + location: 'https://gitlab.com/gitlab-org/gitlab-foss/blob/1234/.xxxxxxxxxxx.yml', + extra: {} + ) + } + 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 66a06de3d28..4da9a933a9f 100644 --- a/spec/lib/gitlab/ci/config/external/file/template_spec.rb +++ b/spec/lib/gitlab/ci/config/external/file/template_spec.rb @@ -45,12 +45,15 @@ RSpec.describe Gitlab::Ci::Config::External::File::Template do end describe "#valid?" do + subject(:valid?) do + template_file.validate! + template_file.valid? + end + context 'when is a valid template name' do let(:template) { 'Auto-DevOps.gitlab-ci.yml' } - it 'returns true' do - expect(template_file).to be_valid - end + it { is_expected.to be_truthy } end context 'with invalid template name' do @@ -59,7 +62,7 @@ RSpec.describe Gitlab::Ci::Config::External::File::Template do let(:context_params) { { project: project, sha: '12345', user: user, variables: variables } } it 'returns false' do - expect(template_file).not_to be_valid + expect(valid?).to be_falsy expect(template_file.error_message).to include('`xxxxxxxxxxxxxx.yml` is not a valid location!') end end @@ -68,7 +71,7 @@ RSpec.describe Gitlab::Ci::Config::External::File::Template do let(:template) { 'I-Do-Not-Have-This-Template.gitlab-ci.yml' } it 'returns false' do - expect(template_file).not_to be_valid + expect(valid?).to be_falsy expect(template_file.error_message).to include('Included file `I-Do-Not-Have-This-Template.gitlab-ci.yml` is empty or does not exist!') end end @@ -111,4 +114,18 @@ RSpec.describe Gitlab::Ci::Config::External::File::Template do is_expected.to be_empty end end + + describe '#metadata' do + subject(:metadata) { template_file.metadata } + + it { + is_expected.to eq( + context_project: project.full_path, + context_sha: '12345', + type: :template, + location: template, + extra: {} + ) + } + end end |