Class: Fastlane::Helper::AppDropperHelper

Inherits:
Object
  • Object
show all
Defined in:
lib/fastlane/plugin/app_dropper/helper/app_dropper_helper.rb

Overview

Talks to the App Dropper REST API over Ruby's standard library only.

Binaries never pass through the API: create_upload returns a Google Cloud Storage resumable session, send_binary streams the file straight there, and await_upload waits for the server to parse it. That is what keeps a 500 MB .ipa clear of the request-size ceilings every HTTP API has.

Constant Summary collapse

DEFAULT_API_URL =
"https://appdropper.io/api/v1".freeze
DEFAULT_TIMEOUT =

Matches the CLI: long enough for a large build to be parsed, short enough that a wedged lane eventually fails instead of hanging a CI job.

600

Instance Method Summary collapse

Constructor Details

#initialize(api_token:, api_url: nil) ⇒ AppDropperHelper

Returns a new instance of AppDropperHelper.



22
23
24
25
# File 'lib/fastlane/plugin/app_dropper/helper/app_dropper_helper.rb', line 22

def initialize(api_token:, api_url: nil)
  @api_token = api_token
  @api_url = (api_url || ENV['APPDROPPER_API_URL'] || DEFAULT_API_URL).chomp('/')
end

Instance Method Details

#await_upload(upload_id, timeout: DEFAULT_TIMEOUT) ⇒ Object

Long-polls the upload until it is parsed. The server holds the connection for wait seconds, so this is normally one request.



58
59
60
61
62
63
64
65
66
67
68
# File 'lib/fastlane/plugin/app_dropper/helper/app_dropper_helper.rb', line 58

def await_upload(upload_id, timeout: DEFAULT_TIMEOUT)
  deadline = Time.now + timeout
  loop do
    remaining = (deadline - Time.now).to_i
    wait = [[remaining, 120].min, 0].max
    result = get("/uploads/#{upload_id}?wait=#{wait}")
    status = result['status']
    return result if status == 'ready' || status == 'error'
    return result if Time.now >= deadline
  end
end

#create_upload(file_name:, file_size:, release_notes:, tag:) ⇒ Object



27
28
29
30
31
32
33
34
# File 'lib/fastlane/plugin/app_dropper/helper/app_dropper_helper.rb', line 27

def create_upload(file_name:, file_size:, release_notes:, tag:)
  post('/uploads', {
    file_name: file_name,
    file_size: file_size,
    release_notes: release_notes.to_s,
    tag: tag.to_s
  })
end

#send_binary(session_url, path, content_type) ⇒ Object

A single PUT of the whole file. Net::HTTP streams from the IO rather than reading the build into memory, which matters when the build is bigger than the runner's RAM budget.



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/fastlane/plugin/app_dropper/helper/app_dropper_helper.rb', line 39

def send_binary(session_url, path, content_type)
  uri = URI.parse(session_url)
  size = File.size(path)

  File.open(path, 'rb') do |io|
    request = Net::HTTP::Put.new(uri)
    request['Content-Type'] = content_type
    request['Content-Length'] = size.to_s
    request.body_stream = io

    response = http_for(uri, read_timeout: 900).request(request)
    unless response.is_a?(Net::HTTPSuccess)
      UI.user_error!("App Dropper: storage rejected the upload (HTTP #{response.code}). #{response.body.to_s[0, 300]}")
    end
  end
end

#whoamiObject



70
71
72
# File 'lib/fastlane/plugin/app_dropper/helper/app_dropper_helper.rb', line 70

def whoami
  get('/me')
end