class Fastlane::Actions::XcodeServerGetAssetsAction::XcodeServer
def fetch_all_bots
def fetch_all_bots response = get_endpoint('/bots') raise "You are unauthorized to access data on #{@host}, please check that you're passing in a correct username and password.".red if response.status == 401 raise "Failed to fetch Bots from Xcode Server at #{@host}, response: #{response.status}: #{response.body}.".red if response.status != 200 JSON.parse(response.body)['results'] end
def fetch_assets(integration_id, target_folder, action)
def fetch_assets(integration_id, target_folder, action) # create a temp folder and a file, stream the download into it Dir.mktmpdir do |dir| temp_file = File.join(dir, "tmp_download.#{rand(1000000)}") f = open(temp_file, 'w') streamer = lambda do |chunk, remaining_bytes, total_bytes| if remaining_bytes && total_bytes Helper.log.info "Downloading: #{100 - (100 * remaining_bytes.to_f / total_bytes.to_f).to_i}%".yellow else Helper.log.error "#{chunk}".red end f.write(chunk) end response = self.get_endpoint("/integrations/#{integration_id}/assets", streamer) f.close raise "Integration doesn't have any assets (it probably never ran).".red if response.status == 500 raise "Failed to fetch Assets zip for Integration #{integration_id} from Xcode Server at #{@host}, response: #{response.status}: #{response.body}".red if response.status != 200 # unzip it, it's a .tar.gz file out_folder = File.join(dir, "out_#{rand(1000000)}") FileUtils.mkdir_p(out_folder) action.sh "cd \"#{out_folder}\"; cat \"#{temp_file}\" | gzip -d | tar -x" # then pull the real name from headers asset_filename = response.headers['Content-Disposition'].split(';')[1].split('=')[1].delete('"') asset_foldername = asset_filename.split('.')[0] # rename the folder in out_folder to asset_foldername found_folder = Dir.entries(out_folder).select { |item| item != '.' && item != '..' }[0] raise "Internal error, couldn't find unzipped folder".red if found_folder.nil? unzipped_folder_temp_name = File.join(out_folder, found_folder) unzipped_folder = File.join(out_folder, asset_foldername) # rename to destination name FileUtils.mv(unzipped_folder_temp_name, unzipped_folder) target_folder = File.absolute_path(target_folder) # create target folder if it doesn't exist FileUtils.mkdir_p(target_folder) # and move+rename it to the destination place FileUtils.cp_r(unzipped_folder, target_folder) out = File.join(target_folder, asset_foldername) return out end return nil end
def fetch_integrations(bot_id)
def fetch_integrations(bot_id) response = get_endpoint("/bots/#{bot_id}/integrations?limit=10") raise "Failed to fetch Integrations for Bot #{bot_id} from Xcode Server at #{@host}, response: #{response.status}: #{response.body}".red if response.status != 200 JSON.parse(response.body)['results'] end
def get_endpoint(endpoint, response_block = nil)
def get_endpoint(endpoint, response_block = nil) url = url_for_endpoint(endpoint) headers = self.headers || {} if response_block response = Excon.get(url, response_block: response_block, headers: headers) else response = Excon.get(url, headers: headers) end return response end
def headers
def headers require 'base64' headers = { 'User-Agent' => 'fastlane-xcode_server_get_assets', # XCS wants user agent. for some API calls. not for others. sigh. 'X-XCSAPIVersion' => 1 # XCS API version with this API, Xcode needs this otherwise it explodes in a 500 error fire. Currently Xcode 7 Beta 5 is on Version 5. } if @username and @password userpass = "#{@username}:#{@password}" headers['Authorization'] = "Basic #{Base64.strict_encode64(userpass)}" end return headers end
def initialize(host, username, password)
def initialize(host, username, password) @host = host.start_with?('https://') ? host : "https://#{host}" @username = username @password = password end
def url_for_endpoint(endpoint)
def url_for_endpoint(endpoint) "#{@host}:20343/api#{endpoint}" end