Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added missing methods and fixed existing ones with file download in job artifacts API #587

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/gitlab/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def inspect
#
# @return [String]
def url_encode(url)
url.to_s.b.gsub(/[^a-zA-Z0-9_\-.~]/n) { |m| sprintf('%%%02X', m.unpack1('C')) } # rubocop:disable Style/FormatString, Style/FormatStringToken
url.to_s.b.gsub(/[^a-zA-Z0-9_\-.~]/n) { |m| sprintf('%%%02X', m.unpack1('C')) } # rubocop:disable Style/FormatString
end

private
Expand Down
70 changes: 62 additions & 8 deletions lib/gitlab/client/jobs.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,70 @@ def job_artifacts(project_id, job_id)
# Gitlab.job_artifacts_download(1, "master", "release")
# Gitlab.job_artifacts_download("project", "master", "release")
#
# @param [Integer, String] id, The ID or name of a project.
# @param [String] ref, Ref Name
# @param [String] job, jobname
# @return [Array<Gitlab::ObjectifiedHash>]
# @param [Integer, String] project_id The ID or name of a project.
# @param [String] ref Ref Name
# @param [String] job jobname
# @return [Gitlab::FileResponse]
def job_artifacts_download(project_id, ref_name, job_name)
get("/projects/#{url_encode project_id}/jobs/artifacts/#{ref_name}/download", query: { job: job_name },
format: nil,
headers: { Accept: 'text/plain' },
parser: ::Gitlab::Request::Parser)
get("/projects/#{url_encode project_id}/jobs/artifacts/#{ref_name}/download",
query: { job: job_name },
format: nil,
headers: { Accept: 'application/octet-stream' },
parser: proc { |body, _|
if body.encoding == Encoding::ASCII_8BIT # binary response
::Gitlab::FileResponse.new StringIO.new(body, 'rb+')
else # error with json response
::Gitlab::Request.parse(body)
end
})
end

# Download a single artifact file by job ID
#
# @example
# Gitlab.download_job_artifact_file(1, 5, "some/release/file.pdf")
#
# @param [Integer, String] project_id(required) The ID or name of a project.
# @param [String] job_id(required) The unique job identifier.
# @param [String] artifact_path(required) Path to a file inside the artifacts archive.
# @return [Gitlab::FileResponse]
def download_job_artifact_file(project_id, job_id, artifact_path)
get("/projects/#{url_encode project_id}/jobs/#{job_id}/artifacts/#{artifact_path}",
format: nil,
headers: { Accept: 'application/octet-stream' },
parser: proc { |body, _|
if body.encoding == Encoding::ASCII_8BIT # binary response
::Gitlab::FileResponse.new StringIO.new(body, 'rb+')
else # error with json response
::Gitlab::Request.parse(body)
end
})
end

# Download a single artifact file from specific tag or branch
#
# @example
# Gitlab.download_branch_artifact_file(1, "master", "some/release/file.pdf", 'pdf')
#
# @param [Integer, String] project_id(required) The ID or name of a project.
# @param [String] ref_name(required) Branch or tag name in repository. HEAD or SHA references are not supported.
# @param [String] artifact_path(required) Path to a file inside the artifacts archive.
# @param [String] job(required) The name of the job.
# @return [Gitlab::FileResponse]
def download_branch_artifact_file(project_id, ref_name, artifact_path, job)
get("/projects/#{url_encode project_id}/jobs/artifacts/#{ref_name}/raw/#{artifact_path}",
query: { job: job },
format: nil,
headers: { Accept: 'application/octet-stream' },
parser: proc { |body, _|
if body.encoding == Encoding::ASCII_8BIT # binary response
::Gitlab::FileResponse.new StringIO.new(body, 'rb+')
else # error with json response
::Gitlab::Request.parse(body)
end
})
end
alias download_tag_artifact_file download_branch_artifact_file

# Get Job Trace
#
Expand Down
Binary file added spec/fixtures/job_artifacts.zip
Binary file not shown.
133 changes: 128 additions & 5 deletions spec/gitlab/client/jobs_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,136 @@
end

describe '.job_artifacts_download' do
before do
stub_get('/projects/1/jobs/artifacts/master/download?job=Release%20Build', 'job')
@projects = Gitlab.job_artifacts_download(1, 'master', 'Release Build')
context 'when successful request' do
before do
fixture = load_fixture('job_artifacts.zip')
fixture.set_encoding(Encoding::ASCII_8BIT)
stub_request(:get, "#{Gitlab.endpoint}/projects/3/jobs/artifacts/master/download")
.with(query: { job: 'test' }, headers: { 'PRIVATE-TOKEN' => Gitlab.private_token })
.to_return(body: fixture.read, headers: { 'Content-Disposition' => 'attachment; filename=job_artifacts.zip' })
@job_artifacts = Gitlab.job_artifacts_download(3, 'master', 'test')
end

it 'gets the correct resource' do
expect(a_get('/projects/3/jobs/artifacts/master/download')
.with(query: { job: 'test' })).to have_been_made
end

it 'returns a FileResponse' do
expect(@job_artifacts).to be_a Gitlab::FileResponse
end

it 'returns a file with filename' do
expect(@job_artifacts.filename).to eq 'job_artifacts.zip'
end
end

it 'gets the correct resource' do
expect(a_get('/projects/1/jobs/artifacts/master/download?job=Release%20Build')).to have_been_made
context 'when bad request' do
it 'throws an exception' do
stub_get('/projects/3/jobs/artifacts/master/download', 'error_project_not_found', 404)
.with(query: { job: 'test' })
expect { Gitlab.job_artifacts_download(3, 'master', 'test') }.to raise_error(Gitlab::Error::NotFound, "Server responded with code 404, message: 404 Project Not Found. Request URI: #{Gitlab.endpoint}/projects/3/jobs/artifacts/master/download")
end
end
end

describe '.download_job_artifact_file' do
context 'when successful request' do
before do
fixture = load_fixture('raw_file.txt')
fixture.set_encoding(Encoding::ASCII_8BIT)
stub_request(:get, "#{Gitlab.endpoint}/projects/3/jobs/5/artifacts/raw_file.txt")
.with(headers: { 'PRIVATE-TOKEN' => Gitlab.private_token })
.to_return(body: fixture.read, headers: { 'Content-Disposition' => 'attachment; filename=raw_file.txt' })
@job_artifact_file = Gitlab.download_job_artifact_file(3, 5, 'raw_file.txt')
end

it 'gets the correct resource' do
expect(a_get('/projects/3/jobs/5/artifacts/raw_file.txt')).to have_been_made
end

it 'returns a FileResponse' do
expect(@job_artifact_file).to be_a Gitlab::FileResponse
end

it 'returns a file with filename' do
expect(@job_artifact_file.filename).to eq 'raw_file.txt'
end
end

context 'when bad request' do
it 'throws an exception' do
stub_get('/projects/3/jobs/5/artifacts/raw_file.txt', 'error_project_not_found', 404)
expect { Gitlab.download_job_artifact_file(3, 5, 'raw_file.txt') }.to raise_error(Gitlab::Error::NotFound, "Server responded with code 404, message: 404 Project Not Found. Request URI: #{Gitlab.endpoint}/projects/3/jobs/5/artifacts/raw_file.txt")
end
end
end

describe '.download_branch_artifact_file' do
context 'when successful request' do
before do
fixture = load_fixture('raw_file.txt')
fixture.set_encoding(Encoding::ASCII_8BIT)
stub_request(:get, "#{Gitlab.endpoint}/projects/1/jobs/artifacts/master/raw/raw_file.txt")
.with(query: { job: 'txt' }, headers: { 'PRIVATE-TOKEN' => Gitlab.private_token })
.to_return(body: fixture.read, headers: { 'Content-Disposition' => 'attachment; filename=raw_file.txt' })
@branch_artifact_file = Gitlab.download_branch_artifact_file(1, 'master', 'raw_file.txt', 'txt')
end

it 'gets the correct resource' do
expect(a_get('/projects/1/jobs/artifacts/master/raw/raw_file.txt')
.with(query: { job: 'txt' })).to have_been_made
end

it 'returns a FileResponse' do
expect(@branch_artifact_file).to be_a Gitlab::FileResponse
end

it 'returns a file with filename' do
expect(@branch_artifact_file.filename).to eq 'raw_file.txt'
end
end

context 'when bad request' do
it 'throws an exception' do
stub_get('/projects/1/jobs/artifacts/master/raw/raw_file.txt', 'error_project_not_found', 404)
.with(query: { job: 'txt' })
expect { Gitlab.download_branch_artifact_file(1, 'master', 'raw_file.txt', 'txt') }.to raise_error(Gitlab::Error::NotFound, "Server responded with code 404, message: 404 Project Not Found. Request URI: #{Gitlab.endpoint}/projects/1/jobs/artifacts/master/raw/raw_file.txt")
end
end
end

describe '.download_tag_artifact_file' do
context 'when successful request' do
before do
fixture = load_fixture('raw_file.txt')
fixture.set_encoding(Encoding::ASCII_8BIT)
stub_request(:get, "#{Gitlab.endpoint}/projects/1/jobs/artifacts/release/raw/raw_file.txt")
.with(query: { job: 'txt' }, headers: { 'PRIVATE-TOKEN' => Gitlab.private_token })
.to_return(body: fixture.read, headers: { 'Content-Disposition' => 'attachment; filename=raw_file.txt' })
@branch_artifact_file = Gitlab.download_tag_artifact_file(1, 'release', 'raw_file.txt', 'txt')
end

it 'gets the correct resource' do
expect(a_get('/projects/1/jobs/artifacts/release/raw/raw_file.txt')
.with(query: { job: 'txt' })).to have_been_made
end

it 'returns a FileResponse' do
expect(@branch_artifact_file).to be_a Gitlab::FileResponse
end

it 'returns a file with filename' do
expect(@branch_artifact_file.filename).to eq 'raw_file.txt'
end
end

context 'when bad request' do
it 'throws an exception' do
stub_get('/projects/1/jobs/artifacts/release/raw/raw_file.txt', 'error_project_not_found', 404)
.with(query: { job: 'txt' })
expect { Gitlab.download_tag_artifact_file(1, 'release', 'raw_file.txt', 'txt') }.to raise_error(Gitlab::Error::NotFound, "Server responded with code 404, message: 404 Project Not Found. Request URI: #{Gitlab.endpoint}/projects/1/jobs/artifacts/release/raw/raw_file.txt")
end
end
end

Expand Down