1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
|
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Ci::CreatePipelineService, feature_category: :pipeline_composition do
include RepoHelpers
context 'include:' do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:user) { project.first_owner }
let(:ref) { 'refs/heads/master' }
let(:variables_attributes) { [{ key: 'MYVAR', secret_value: 'hello' }] }
let(:source) { :push }
let(:service) { described_class.new(project, user, { ref: ref, variables_attributes: variables_attributes }) }
let(:pipeline) { service.execute(source).payload }
let(:file_location) { 'spec/fixtures/gitlab/ci/external_files/.gitlab-ci-template-1.yml' }
let(:project_files) do
{
'.gitlab-ci.yml' => config,
file_location => File.read(Rails.root.join(file_location))
}
end
around do |example|
create_and_delete_files(project, project_files) do
example.run
end
end
shared_examples 'not including the file' do
it 'does not include the job in the file' do
expect(pipeline).to be_created_successfully
expect(pipeline.processables.pluck(:name)).to contain_exactly('job')
end
end
shared_examples 'including the file' do
it 'includes the job in the file' do
expect(pipeline).to be_created_successfully
expect(pipeline.processables.pluck(:name)).to contain_exactly('job', 'rspec')
end
end
context 'with a local file' do
let(:config) do
<<~EOY
include: #{file_location}
job:
script: exit 0
EOY
end
it_behaves_like 'including the file'
end
context 'with a local file with rules with a project variable' do
let(:config) do
<<~EOY
include:
- local: #{file_location}
rules:
- if: $CI_PROJECT_ID == "#{project_id}"
job:
script: exit 0
EOY
end
context 'when the rules matches' do
let(:project_id) { project.id }
it_behaves_like 'including the file'
end
context 'when the rules does not match' do
let(:project_id) { non_existing_record_id }
it_behaves_like 'not including the file'
end
end
context 'with a local file with rules with a predefined pipeline variable' do
let(:config) do
<<~EOY
include:
- local: #{file_location}
rules:
- if: $CI_PIPELINE_SOURCE == "#{pipeline_source}"
job:
script: exit 0
EOY
end
context 'when the rules matches' do
let(:pipeline_source) { 'push' }
it_behaves_like 'including the file'
end
context 'when the rules does not match' do
let(:pipeline_source) { 'web' }
it_behaves_like 'not including the file'
end
end
context 'with a local file with rules with a run pipeline variable' do
let(:config) do
<<~EOY
include:
- local: #{file_location}
rules:
- if: $MYVAR == "#{my_var}"
job:
script: exit 0
EOY
end
context 'when the rules matches' do
let(:my_var) { 'hello' }
it_behaves_like 'including the file'
end
context 'when the rules does not match' do
let(:my_var) { 'mello' }
it_behaves_like 'not including the file'
end
end
context 'with a local file with rules:exists' do
let(:config) do
<<~YAML
include:
- local: file1.yml
rules:
- exists:
- 'docs/*.md' # does not match
- 'config/*.rb' # does not match
- local: file2.yml
rules:
- exists:
- 'docs/*.md' # does not match
- '**/app.rb' # does not match
- local: #{file_location}
rules:
- exists:
- '**/app.rb' # does not match
- spec/fixtures/gitlab/ci/*/.gitlab-ci-template-1.yml # matches
job:
script: exit 0
YAML
end
let(:number_of_files) { project.repository.ls_files(ref).size }
it_behaves_like 'including the file'
context 'on checking cache', :request_store do
it 'does not evaluate the same glob more than once' do
expect(File).to receive(:fnmatch?)
.with('docs/*.md', anything, anything)
.exactly(number_of_files).times # it iterates all files
.and_call_original
expect(File).to receive(:fnmatch?)
.with('config/*.rb', anything, anything)
.exactly(number_of_files).times # it iterates all files
.and_call_original
expect(File).to receive(:fnmatch?)
.with('**/app.rb', anything, anything)
.exactly(number_of_files).times # it iterates all files
.and_call_original
expect(File).to receive(:fnmatch?)
.with('spec/fixtures/gitlab/ci/*/.gitlab-ci-template-1.yml', anything, anything)
.exactly(39).times # it iterates files until it finds a match
.and_call_original
expect(pipeline).to be_created_successfully
expect(pipeline.processables.pluck(:name)).to contain_exactly('job', 'rspec')
end
end
end
end
end
|