summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGrzegorz Bizon <grzesiek.bizon@gmail.com>2017-09-04 14:09:03 +0200
committerGrzegorz Bizon <grzesiek.bizon@gmail.com>2017-09-04 14:09:03 +0200
commitf3f1ad3992c039563188a84787b1e916e367d702 (patch)
tree656de5d453bd96fef6049a8f77bab9dc08d9c62a
parentebbbc7ef52fbd1d3339e2e21be967d313a074a28 (diff)
downloadgitlab-ce-f3f1ad3992c039563188a84787b1e916e367d702.tar.gz
Add API endpoint for downloading single job artifact
-rw-r--r--lib/api/jobs.rb19
-rw-r--r--spec/requests/api/jobs_spec.rb57
2 files changed, 76 insertions, 0 deletions
diff --git a/lib/api/jobs.rb b/lib/api/jobs.rb
index 5bab96398fd..41b3b28037c 100644
--- a/lib/api/jobs.rb
+++ b/lib/api/jobs.rb
@@ -85,6 +85,25 @@ module API
present_artifacts!(build.artifacts_file)
end
+ desc 'Download a specific file from artifacts archive' do
+ detail 'This feature was introduced in GitLab 10.0'
+ end
+ params do
+ requires :job_id, type: Integer, desc: 'The ID of a job'
+ requires :artifact_path, type: String, desc: 'Artifact path'
+ end
+ get ':id/jobs/:job_id/artifacts/*artifact_path', format: false do
+ authorize_read_builds!
+
+ build = get_build!(params[:job_id])
+ not_found! unless build.artifacts?
+
+ entry = build.artifacts_metadata_entry(params[:artifact_path])
+ not_found! unless entry.exists?
+
+ Gitlab::Workhorse.send_artifacts_entry(build, entry)
+ end
+
desc 'Download the artifacts file from a job' do
detail 'This feature was introduced in GitLab 8.10'
end
diff --git a/spec/requests/api/jobs_spec.rb b/spec/requests/api/jobs_spec.rb
index f56baf9663d..f90ee4016d0 100644
--- a/spec/requests/api/jobs_spec.rb
+++ b/spec/requests/api/jobs_spec.rb
@@ -188,6 +188,63 @@ describe API::Jobs do
end
end
+ describe 'GET /projects/:id/jobs/:job_id/artifacts/:artifact_path' do
+ context 'when job has artifacts' do
+ let(:job) { create(:ci_build, :artifacts, pipeline: pipeline) }
+
+ let(:artifact) do
+ 'other_artifacts_0.1.2/another-subdirectory/banana_sample.gif'
+ end
+
+ context 'when user is not unauthorized' do
+ let(:api_user) { nil }
+
+ it 'does not return specific job artifacts' do
+ get_artifact_file(artifact)
+
+ expect(response).to have_http_status(401)
+ end
+ end
+
+ context 'when user is authorized' do
+ 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_http_status(200)
+ expect(response.body)
+ .to include 'Gitlab-Workhorse-Send-Data', 'artifacts-entry'
+ expect(response.headers)
+ .to include('Content-Type' => 'application/json')
+ end
+ end
+
+ context 'when request path is invalid' do
+ it 'does not find artifact file' do
+ get_artifact_file('invalid/path')
+
+ expect(response).to have_http_status(404)
+ end
+ end
+ end
+
+ context 'when job does not have artifacts' do
+ it 'does not return job artifact file' do
+ get_artifact_file('some/artifact')
+
+ expect(response).to have_http_status(404)
+ end
+ end
+
+ def get_artifact_file(artifact_path)
+ get api("/projects/#{project.id}/jobs/#{job.id}/" \
+ "artifacts/#{artifact_path}", api_user)
+ end
+ end
+
describe 'GET /projects/:id/jobs/:job_id/artifacts' do
before do
get api("/projects/#{project.id}/jobs/#{job.id}/artifacts", api_user)