Skip to content

Commit

Permalink
[match] Add access token prompt for GitLab Secure Files Match (#21279)
Browse files Browse the repository at this point in the history
* Adding access token prompt for GitLab Secure Files Match

* Removing commented code
  • Loading branch information
darbyfrey committed Jul 3, 2023
1 parent 0495da3 commit ba801c7
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 30 deletions.
52 changes: 38 additions & 14 deletions match/lib/match/storage/gitlab/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,32 +69,56 @@ def upload_file(current_file, target_file)
"name" => target_file
)

response = execute_request(url, request)
execute_request(url, request, target_file)
end
end

def execute_request(url, request, target_file = nil)
request[authentication_key] = authentication_value

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = url.instance_of?(URI::HTTPS)

begin
response = http.request(request)
rescue Errno::ECONNREFUSED, SocketError => message
UI.user_error!("GitLab connection error: #{message}")
end

log_upload_error(response, target_file) if response.code != "201"
unless response.kind_of?(Net::HTTPSuccess)
handle_response_error(response, target_file)
end

response
end

def log_upload_error(response, target_file)
def handle_response_error(response, target_file = nil)
error_prefix = "GitLab storage error:"
file_debug_string = "File: #{target_file}" unless target_file.nil?
api_debug_string = "API: #{@api_v4_url}"
debug_info = "(#{[file_debug_string, api_debug_string].compact.join(', ')})"

begin
response_body = JSON.parse(response.body)
parsed = JSON.parse(response.body)
rescue JSON::ParserError
response_body = response.body
end

if response_body["message"] && (response_body["message"]["name"] == ["has already been taken"])
UI.error("#{target_file} already exists in GitLab project #{@project_id}, file not uploaded")
if parsed && parsed["message"] && (parsed["message"]["name"] == ["has already been taken"])
error_handler = :error
error = "#{target_file} already exists in GitLab project #{@project_id}, file not uploaded"
else
UI.error("Upload error for #{target_file}: #{response_body}")
error_handler = :user_error!
error = "#{response.code}: #{response.body}"
end
end
error_message = [error_prefix, error, debug_info].join(' ')

def execute_request(url, request)
request[authentication_key] = authentication_value
UI.send(error_handler, error_message)
end

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = url.instance_of?(URI::HTTPS)
http.request(request)
def prompt_for_access_token
unless authentication_key
@private_token = UI.input("Please supply a GitLab personal or project access token: ")
end
end
end
end
Expand Down
9 changes: 7 additions & 2 deletions match/lib/match/storage/gitlab_secure_files.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ def self.configure(params)
team_id: params[:team_id],
team_name: params[:team_name],
api_key_path: params[:api_key_path],
api_key: params[:api_key]
api_key: params[:api_key],
gitlab_host: params[:gitlab_host]
)
end

Expand All @@ -60,14 +61,16 @@ def initialize(api_v4_url: nil,
team_id: nil,
team_name: nil,
api_key_path: nil,
api_key: nil)
api_key: nil,
gitlab_host: nil)

@readonly = readonly
@username = username
@team_id = team_id
@team_name = team_name
@api_key_path = api_key_path
@api_key = api_key
@gitlab_host = gitlab_host

@job_token = job_token
@private_token = private_token
Expand Down Expand Up @@ -95,6 +98,8 @@ def prefixed_working_directory
end

def download
gitlab_client.prompt_for_access_token

# Check if we already have a functional working_directory
return if @working_directory

Expand Down
96 changes: 82 additions & 14 deletions match/spec/storage/gitlab/client_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -127,41 +127,109 @@
end
end

describe '#log_upload_error' do
it 'logs a custom error message when the file name has already been taken' do
expect_any_instance_of(FastlaneCore::Shell).to receive(:error).with("foo already exists in GitLab project sample/project, file not uploaded")
describe '#prompt_for_access_token' do
it 'prompts the users for an access token if authentication is not supplied' do
client = described_class.new(
api_v4_url: 'https://gitlab.example.com/api/v4',
project_id: 'sample/project'
)
expect(UI).to receive(:input).with('Please supply a GitLab personal or project access token: ')
client.prompt_for_access_token
end

it 'does not prompt the user for an access token when a job token is supplied' do
client = described_class.new(
api_v4_url: 'https://gitlab.example.com/api/v4',
project_id: 'sample/project',
job_token: 'abc123'
)
expect(UI).not_to receive(:input)
client.prompt_for_access_token
end

it 'does not prompt the user for an access token when a private token is supplied' do
client = described_class.new(
api_v4_url: 'https://gitlab.example.com/api/v4',
project_id: 'sample/project',
private_token: 'xyz123'
)
expect(UI).not_to receive(:input)
client.prompt_for_access_token
end
end

def error_response_formatter(string, file = nil)
if file
"GitLab storage error: #{string} (File: #{file}, API: https://gitlab.example.com/api/v4)"
else
"GitLab storage error: #{string} (API: https://gitlab.example.com/api/v4)"
end
end

describe '#handle_response_error' do
it 'returns a non-fatal error message when the file name has already been taken' do
expected_error = "foo already exists in GitLab project sample/project, file not uploaded"
expected_error_type = :error

response_body = { message: { name: ["has already been taken" ] } }.to_json
response = OpenStruct.new(code: "400", body: response_body)
target_file = 'foo'
subject.log_upload_error(response, target_file)

expect(UI).to receive(expected_error_type).with(error_response_formatter(expected_error, target_file))

subject.handle_response_error(response, target_file)
end

it 'logs the returned error message when an unexpected JSON response is returned' do
expect_any_instance_of(FastlaneCore::Shell).to receive(:error).with("Upload error for foo: {\"message\"=>{\"bar\"=>\"baz\"}}")
it 'returns a fatal error message when an unexpected JSON response is supplied with a target file' do
expected_error = "500: {\"message\":{\"bar\":\"baz\"}}"
expected_error_type = :user_error!

response_body = { message: { bar: "baz" } }.to_json
response = OpenStruct.new(code: "500", body: response_body)
target_file = 'foo'
subject.log_upload_error(response, target_file)

expect(UI).to receive(expected_error_type).with(error_response_formatter(expected_error, target_file))

subject.handle_response_error(response, target_file)
end

it 'logs the returned error message when an unexpected JSON response is returned' do
expect_any_instance_of(FastlaneCore::Shell).to receive(:error).with("Upload error for foo: {\"foo\"=>{\"bar\"=>\"baz\"}}")
it 'returns a fatal error message when an unexpected JSON response is supplied without a target file' do
expected_error = "500: {\"message\":{\"bar\":\"baz\"}}"
expected_error_type = :user_error!

response_body = { foo: { bar: "baz" } }.to_json
response_body = { message: { bar: "baz" } }.to_json
response = OpenStruct.new(code: "500", body: response_body)
target_file = 'foo'
subject.log_upload_error(response, target_file)

expect(UI).to receive(expected_error_type).with(error_response_formatter(expected_error))

subject.handle_response_error(response)
end

it 'returns a fatal error message when a non-JSON response is supplied with a target file' do
expected_error = "500: a generic error message"
expected_error_type = :user_error!

response = OpenStruct.new(code: "500", body: "a generic error message")
target_file = 'foo'

expect(UI).to receive(expected_error_type).with(error_response_formatter(expected_error, target_file))

subject.handle_response_error(response, target_file)
end

it 'logs the returned error message when a non-JSON response is returned' do
expect_any_instance_of(FastlaneCore::Shell).to receive(:error).with("Upload error for foo: a generic error message")
it 'returns a fatal error message when a non-JSON response is supplied without a target file' do
expected_error = "500: a generic error message"
expected_error_type = :user_error!

response = OpenStruct.new(code: "500", body: "a generic error message")
target_file = 'foo'
subject.log_upload_error(response, target_file)

expect(UI).to receive(expected_error_type).with(error_response_formatter(expected_error))

subject.handle_response_error(response)
end

end
end
end

0 comments on commit ba801c7

Please sign in to comment.