diff options
author | Steve Azzopardi <steveazz@outlook.com> | 2018-12-04 11:50:01 +0100 |
---|---|---|
committer | Steve Azzopardi <steveazz@outlook.com> | 2018-12-07 15:33:30 +0100 |
commit | 401f65c43aa12aa712daa8ddfb00a4fb731541c8 (patch) | |
tree | a47285f34754b7339225a1baf9db2caa0ea7b7bf /spec | |
parent | 62d971129da99936a3cdc04f3740d26f16a0c7a6 (diff) | |
download | gitlab-ce-401f65c43aa12aa712daa8ddfb00a4fb731541c8.tar.gz |
Add endpoint to download single artifact by ref
Add a new endpoint
`projects/:id/jobs/artifacts/:ref_name/raw/*artifact_path?job=name`
which is the close the web URL for consistency sake. This endpoint can
be used to download a single file from artifacts for the specified ref
and job.
closes https://gitlab.com/gitlab-org/gitlab-ce/issues/54626
Diffstat (limited to 'spec')
-rw-r--r-- | spec/models/project_spec.rb | 20 | ||||
-rw-r--r-- | spec/requests/api/jobs_spec.rb | 130 |
2 files changed, 145 insertions, 5 deletions
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 50920d9d1fc..2497f9c624d 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -1897,7 +1897,7 @@ describe Project do end end - describe '#latest_successful_builds_for' do + describe '#latest_successful_builds_for and #latest_successful_build_for' do def create_pipeline(status = 'success') create(:ci_pipeline, project: project, sha: project.commit.sha, @@ -1919,14 +1919,16 @@ describe Project do it 'gives the latest builds from latest pipeline' do pipeline1 = create_pipeline pipeline2 = create_pipeline - build1_p2 = create_build(pipeline2, 'test') create_build(pipeline1, 'test') create_build(pipeline1, 'test2') + build1_p2 = create_build(pipeline2, 'test') build2_p2 = create_build(pipeline2, 'test2') latest_builds = project.latest_successful_builds_for + single_build = project.latest_successful_build_for(build1_p2.name) expect(latest_builds).to contain_exactly(build2_p2, build1_p2) + expect(single_build).to eq(build1_p2) end end @@ -1936,16 +1938,22 @@ describe Project do context 'standalone pipeline' do it 'returns builds for ref for default_branch' do builds = project.latest_successful_builds_for + single_build = project.latest_successful_build_for(build.name) expect(builds).to contain_exactly(build) + expect(single_build).to eq(build) end - it 'returns empty relation if the build cannot be found' do + it 'returns empty relation if the build cannot be found for #latest_successful_builds_for' do builds = project.latest_successful_builds_for('TAIL') expect(builds).to be_kind_of(ActiveRecord::Relation) expect(builds).to be_empty end + + it 'returns exception if the build cannot be found for #latest_successful_build_for' do + expect { project.latest_successful_build_for(build.name, 'TAIL') }.to raise_error(ActiveRecord::RecordNotFound) + end end context 'with some pending pipeline' do @@ -1954,9 +1962,11 @@ describe Project do end it 'gives the latest build from latest pipeline' do - latest_build = project.latest_successful_builds_for + latest_builds = project.latest_successful_builds_for + last_single_build = project.latest_successful_build_for(build.name) - expect(latest_build).to contain_exactly(build) + expect(latest_builds).to contain_exactly(build) + expect(last_single_build).to eq(build) end end end diff --git a/spec/requests/api/jobs_spec.rb b/spec/requests/api/jobs_spec.rb index 8770365c893..cd4e480ca64 100644 --- a/spec/requests/api/jobs_spec.rb +++ b/spec/requests/api/jobs_spec.rb @@ -586,6 +586,136 @@ describe API::Jobs do end end + describe 'GET id/jobs/artifacts/:ref_name/raw/*artifact_path?job=name' do + context 'when job has artifacts' do + let(:job) { create(:ci_build, :artifacts, pipeline: pipeline, user: api_user) } + let(:artifact) { 'other_artifacts_0.1.2/another-subdirectory/banana_sample.gif' } + let(:visibility_level) { Gitlab::VisibilityLevel::PUBLIC } + let(:public_builds) { true } + + before do + stub_artifacts_object_storage + job.success + + project.update(visibility_level: visibility_level, + public_builds: public_builds) + + get_artifact_file(artifact) + end + + context 'when user is anonymous' do + let(:api_user) { nil } + + context 'when project is public' do + let(:visibility_level) { Gitlab::VisibilityLevel::PUBLIC } + let(:public_builds) { true } + + it 'allows to access artifacts' do + expect(response).to have_gitlab_http_status(200) + expect(response.headers.to_h) + .to include('Content-Type' => 'application/json', + 'Gitlab-Workhorse-Send-Data' => /artifacts-entry/) + end + end + + context 'when project is public with builds access disabled' do + let(:visibility_level) { Gitlab::VisibilityLevel::PUBLIC } + let(:public_builds) { false } + + it 'rejects access to artifacts' do + expect(response).to have_gitlab_http_status(403) + expect(json_response).to have_key('message') + expect(response.headers.to_h) + .not_to include('Gitlab-Workhorse-Send-Data' => /artifacts-entry/) + end + end + + context 'when project is private' do + let(:visibility_level) { Gitlab::VisibilityLevel::PRIVATE } + let(:public_builds) { true } + + it 'rejects access and hides existence of artifacts' do + expect(response).to have_gitlab_http_status(404) + expect(json_response).to have_key('message') + expect(response.headers.to_h) + .not_to include('Gitlab-Workhorse-Send-Data' => /artifacts-entry/) + end + end + end + + context 'when user is authorized' do + let(:visibility_level) { Gitlab::VisibilityLevel::PRIVATE } + let(:public_builds) { true } + + it 'returns a specific artifact file for a valid path' do + expect(Gitlab::Workhorse) + .to receive(:send_artifacts_entry) + .and_call_original + + get_artifact_file(artifact) + + expect(response).to have_gitlab_http_status(200) + expect(response.headers.to_h) + .to include('Content-Type' => 'application/json', + 'Gitlab-Workhorse-Send-Data' => /artifacts-entry/) + end + end + + context 'with branch name containing slash' do + before do + pipeline.reload + pipeline.update(ref: 'improve/awesome', + sha: project.commit('improve/awesome').sha) + end + + it 'returns a specific artifact file for a valid path' do + get_artifact_file(artifact, 'improve/awesome') + + expect(response).to have_gitlab_http_status(200) + expect(response.headers.to_h) + .to include('Content-Type' => 'application/json', + 'Gitlab-Workhorse-Send-Data' => /artifacts-entry/) + end + end + + context 'non-existing job' do + shared_examples 'not found' do + it { expect(response).to have_gitlab_http_status(:not_found) } + end + + context 'has no such ref' do + before do + get_artifact_file('some/artifact', 'wrong-ref') + end + + it_behaves_like 'not found' + end + + context 'has no such job' do + before do + get_artifact_file('some/artifact', pipeline.ref, 'wrong-job-name') + end + + it_behaves_like 'not found' + end + end + end + + context 'when job does not have artifacts' do + let(:job) { create(:ci_build, pipeline: pipeline, user: api_user) } + + it 'does not return job artifact file' do + get_artifact_file('some/artifact') + + expect(response).to have_gitlab_http_status(404) + end + end + + def get_artifact_file(artifact_path, ref = pipeline.ref, job_name = job.name) + get api("/projects/#{project.id}/jobs/artifacts/#{ref}/raw/#{artifact_path}", api_user), job: job_name + end + end + describe 'GET /projects/:id/jobs/:job_id/trace' do before do get api("/projects/#{project.id}/jobs/#{job.id}/trace", api_user) |