gitlab-org--gitlab-foss/spec/services/ci/find_exposed_artifacts_service_spec.rb

219 lines
6.1 KiB
Ruby

# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Ci::FindExposedArtifactsService do
include Gitlab::Routing
let(:metadata) do
Gitlab::Ci::Build::Artifacts::Metadata
.new(metadata_file_stream, path, { recursive: true })
end
let(:metadata_file_stream) do
File.open(Rails.root + 'spec/fixtures/ci_build_artifacts_metadata.gz')
end
let_it_be(:project) { create(:project) }
let(:user) { nil }
after do
metadata_file_stream&.close
end
def create_job_with_artifacts(options)
create(:ci_build, pipeline: pipeline, options: options).tap do |job|
create(:ci_job_artifact, :metadata, job: job)
end
end
describe '#for_pipeline' do
shared_examples 'finds a single match' do
it 'returns the artifact with exact location' do
expect(subject).to eq([{
text: 'Exposed artifact',
url: file_project_job_artifacts_path(project, job, 'other_artifacts_0.1.2/doc_sample.txt'),
job_name: job.name,
job_path: project_job_path(project, job)
}])
end
end
shared_examples 'finds multiple matches' do
it 'returns the path to the artifacts browser' do
expect(subject).to eq([{
text: 'Exposed artifact',
url: browse_project_job_artifacts_path(project, job),
job_name: job.name,
job_path: project_job_path(project, job)
}])
end
end
shared_examples 'does not find any matches' do
it 'returns empty array' do
expect(subject).to eq []
end
end
let_it_be(:pipeline) { create(:ci_pipeline, project: project) }
subject { described_class.new(project, user).for_pipeline(pipeline) }
context 'with jobs having no exposed artifacts' do
let!(:job) do
create_job_with_artifacts(artifacts: {
paths: ['other_artifacts_0.1.2/doc_sample.txt', 'something-else.html']
})
end
it_behaves_like 'does not find any matches'
end
context 'with jobs having no artifacts (metadata)' do
let!(:job) do
create(:ci_build, pipeline: pipeline, options: {
artifacts: {
expose_as: 'Exposed artifact',
paths: ['other_artifacts_0.1.2/doc_sample.txt', 'something-else.html']
}
})
end
it_behaves_like 'does not find any matches'
end
context 'with jobs having at most 1 matching exposed artifact' do
let!(:job) do
create_job_with_artifacts(artifacts: {
expose_as: 'Exposed artifact',
paths: ['other_artifacts_0.1.2/doc_sample.txt', 'something-else.html']
})
end
it_behaves_like 'finds a single match'
end
context 'with jobs having more than 1 matching exposed artifacts' do
let!(:job) do
create_job_with_artifacts(artifacts: {
expose_as: 'Exposed artifact',
paths: [
'ci_artifacts.txt',
'other_artifacts_0.1.2/doc_sample.txt',
'something-else.html'
]
})
end
it_behaves_like 'finds multiple matches'
end
context 'with jobs having more than 1 matching exposed artifacts inside a directory' do
let!(:job) do
create_job_with_artifacts(artifacts: {
expose_as: 'Exposed artifact',
paths: ['tests_encoding/']
})
end
it_behaves_like 'finds multiple matches'
end
context 'with jobs having paths with glob expression' do
let!(:job) do
create_job_with_artifacts(artifacts: {
expose_as: 'Exposed artifact',
paths: ['other_artifacts_0.1.2/doc_sample.txt', 'tests_encoding/*.*']
})
end
it_behaves_like 'finds a single match' # because those with * are ignored
end
context 'limiting results' do
let!(:job1) do
create_job_with_artifacts(artifacts: {
expose_as: 'artifact 1',
paths: ['ci_artifacts.txt']
})
end
let!(:job2) do
create_job_with_artifacts(artifacts: {
expose_as: 'artifact 2',
paths: ['tests_encoding/']
})
end
let!(:job3) do
create_job_with_artifacts(artifacts: {
expose_as: 'should not be exposed',
paths: ['other_artifacts_0.1.2/doc_sample.txt']
})
end
subject { described_class.new(project, user).for_pipeline(pipeline, limit: 2) }
it 'returns first 2 results' do
expect(subject).to eq([
{
text: 'artifact 1',
url: file_project_job_artifacts_path(project, job1, 'ci_artifacts.txt'),
job_name: job1.name,
job_path: project_job_path(project, job1)
},
{
text: 'artifact 2',
url: browse_project_job_artifacts_path(project, job2),
job_name: job2.name,
job_path: project_job_path(project, job2)
}
])
end
end
context 'cross-project MR' do
let!(:foreign_project) { create(:project) }
let!(:pipeline) { create(:ci_pipeline, project: foreign_project) }
let!(:job_show) do
create_job_with_artifacts({
artifacts: {
expose_as: 'file artifact',
paths: ['ci_artifacts.txt']
}
})
end
let!(:job_browse) do
create_job_with_artifacts({
artifacts: {
expose_as: 'directory artifact',
paths: ['tests_encoding/']
}
})
end
subject { described_class.new(project, user).for_pipeline(pipeline, limit: 2) }
it 'returns the correct path for cross-project MRs' do
expect(subject).to eq([
{
text: 'file artifact',
url: file_project_job_artifacts_path(foreign_project, job_show, 'ci_artifacts.txt'),
job_name: job_show.name,
job_path: project_job_path(foreign_project, job_show)
},
{
text: 'directory artifact',
url: browse_project_job_artifacts_path(foreign_project, job_browse),
job_name: job_browse.name,
job_path: project_job_path(foreign_project, job_browse)
}
])
end
end
end
end