From 3210fd3f44d5c54fe41e59c5789d36630e77b74e Mon Sep 17 00:00:00 2001 From: shoshoi Date: Sat, 25 Mar 2023 16:44:47 +0900 Subject: [PATCH] Add project export API --- lib/gitlab/client/project_exports.rb | 54 ++++++++++++++ .../fixtures/exported_project_download.tar.gz | Bin 0 -> 136 bytes spec/fixtures/project_export.json | 1 + spec/fixtures/project_export_status.json | 1 + spec/gitlab/client/projects_export_spec.rb | 68 ++++++++++++++++++ spec/spec_helper.rb | 2 +- 6 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 lib/gitlab/client/project_exports.rb create mode 100644 spec/fixtures/exported_project_download.tar.gz create mode 100644 spec/fixtures/project_export.json create mode 100644 spec/fixtures/project_export_status.json create mode 100644 spec/gitlab/client/projects_export_spec.rb diff --git a/lib/gitlab/client/project_exports.rb b/lib/gitlab/client/project_exports.rb new file mode 100644 index 000000000..4570d9e8f --- /dev/null +++ b/lib/gitlab/client/project_exports.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: true + +class Gitlab::Client + # Defines methods related to project exports. + # @see https://docs.gitlab.com/ce/api/project_import_export.html + module ProjectExports + # Start a new export + # + # @example + # Gitlab.export_project(2) + # + # @param [Integer, String] id The ID or path of a project. + # @param [Hash] options A customizable set of options. + # @option options [String] description(optional) Overrides the project description + # @option options [hash] upload(optional) Hash that contains the information to upload the exported project to a web server + # @option options [String] upload[url] TThe URL to upload the project + # @option options [String] upload[http_method](optional) The HTTP method to upload the exported project. Only PUT and POST methods allowed. Default is PUT + # @return [Gitlab::ObjectifiedHash] + def export_project(id, options = {}) + post("/projects/#{url_encode id}/export", body: options) + end + + # Get the status of export + # + # @example + # Gitlab.export_project_status(2) + # + # @param [Integer, String] id The ID or path of a project. + # @return [Gitlab::ObjectifiedHash] + def export_project_status(id) + get("/projects/#{url_encode id}/export") + end + + # Download the finished export + # + # @example + # Gitlab.exported_project_download(2) + # + # @param [Integer, String] id The ID or path of a project. + # @return [Gitlab::FileResponse] + def exported_project_download(id) + get("/projects/#{url_encode id}/export/download", + 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 + end +end diff --git a/spec/fixtures/exported_project_download.tar.gz b/spec/fixtures/exported_project_download.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..e09006331a04f2241e15a13930245fa2c26a6d74 GIT binary patch literal 136 zcmb2|=3q!TA(z6y{Pv%%qGU6ziXS0w!(IL2^@X?dly^v56VmDbc_)BGdf zxZOjH|B~)ogT1@cqb5CBv^pR(I_mA$8P>rY7wMf^5U1M_m3goGa!xPbvl+Mgi-mp{ i&b|Kf?)ty;v%dYefA@}&0U7Lg#(lkI^?e2n1_l5nEID-m literal 0 HcmV?d00001 diff --git a/spec/fixtures/project_export.json b/spec/fixtures/project_export.json new file mode 100644 index 000000000..c2a050fc0 --- /dev/null +++ b/spec/fixtures/project_export.json @@ -0,0 +1 @@ +{"message": "202 Accepted"} \ No newline at end of file diff --git a/spec/fixtures/project_export_status.json b/spec/fixtures/project_export_status.json new file mode 100644 index 000000000..8fbfc7226 --- /dev/null +++ b/spec/fixtures/project_export_status.json @@ -0,0 +1 @@ +{"export_status": "none"} \ No newline at end of file diff --git a/spec/gitlab/client/projects_export_spec.rb b/spec/gitlab/client/projects_export_spec.rb new file mode 100644 index 000000000..61a12e5a5 --- /dev/null +++ b/spec/gitlab/client/projects_export_spec.rb @@ -0,0 +1,68 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Client do + describe '.export_project' do + before do + stub_post('/projects/1/export', 'project_export') + @export_project = Gitlab.export_project(1, { description: 'test_description-path', upload: { url: 'https://example.com/', http_method: 'POST' } }) + end + + it 'gets the correct resource' do + expect(a_post('/projects/1/export') + .with(body: { description: 'test_description-path', upload: { url: 'https://example.com/', http_method: 'POST' } })).to have_been_made + end + + it 'returns information about the project export request' do + expect(@export_project.message).to eq('202 Accepted') + end + end + + describe '.project_export_status' do + before do + stub_get('/projects/1/export', 'project_export_status') + @export_project = Gitlab.export_project_status(1) + end + + it 'gets the correct resource' do + expect(a_get('/projects/1/export')).to have_been_made + end + + it 'returns information about the project export status' do + expect(@export_project.export_status).to eq('none') + end + end + + describe '.exported_project_download' do + context 'when successful request' do + before do + fixture = load_fixture('exported_project_download.tar.gz') + fixture.set_encoding(Encoding::ASCII_8BIT) + stub_request(:get, "#{Gitlab.endpoint}/projects/1/export/download") + .with(headers: { 'PRIVATE-TOKEN' => Gitlab.private_token }) + .to_return(body: fixture.read, headers: { 'Content-Disposition' => 'attachment; filename=exported_project_download.tar.gz' }) + @exported_project = Gitlab.exported_project_download(1) + end + + it 'gets the correct resource' do + expect(a_get('/projects/1/export/download')).to have_been_made + end + + it 'returns a FileResponse' do + expect(@exported_project).to be_a Gitlab::FileResponse + end + + it 'returns a file with filename' do + expect(@exported_project.filename).to eq 'exported_project_download.tar.gz' + end + end + + context 'when bad request' do + it 'throws an exception' do + stub_get('/projects/1/export/download', 'error_project_not_found', 404) + expect { Gitlab.exported_project_download(1) }.to raise_error(Gitlab::Error::NotFound, "Server responded with code 404, message: 404 Project Not Found. Request URI: #{Gitlab.endpoint}/projects/1/export/download") + end + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 479e1b00c..bc0698238 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -7,7 +7,7 @@ require File.expand_path('../lib/gitlab/cli', __dir__) def load_fixture(name) - name, extension = name.split('.') + name, extension = name.split('.', 2) File.new(File.dirname(__FILE__) + "/fixtures/#{name}.#{extension || 'json'}") end