Class: Mysigner::Upload::AscRestUploader

Inherits:
Object
  • Object
show all
Defined in:
lib/mysigner/upload/asc_rest_uploader.rb

Defined Under Namespace

Classes: BuildVersionConflictError

Constant Summary collapse

TERMINAL_APPLE_STATES =
%w[COMPLETE FAILED INVALIDATED].freeze
POLL_INTERVAL =
10
POLL_TIMEOUT =
600
CHUNK_RETRIES =
2

Instance Method Summary collapse

Constructor Details

#initialize(client:, organization_id:, ipa_path:, apple_app_id:, cf_bundle_version:, cf_bundle_short_version_string:, platform: 'IOS', poll_interval: POLL_INTERVAL, poll_timeout: POLL_TIMEOUT) ⇒ AscRestUploader

Returns a new instance of AscRestUploader.



20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/mysigner/upload/asc_rest_uploader.rb', line 20

def initialize(client:, organization_id:, ipa_path:, apple_app_id:,
               cf_bundle_version:, cf_bundle_short_version_string:,
               platform: 'IOS', poll_interval: POLL_INTERVAL, poll_timeout: POLL_TIMEOUT)
  @client = client
  @org_id = organization_id
  @ipa_path = ipa_path
  @apple_app_id = apple_app_id
  @cf_bundle_version = cf_bundle_version
  @cf_bundle_short_version_string = cf_bundle_short_version_string
  @platform = platform
  @poll_interval = poll_interval
  @poll_timeout = poll_timeout
end

Instance Method Details

#callObject



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/mysigner/upload/asc_rest_uploader.rb', line 34

def call
  begin
    resp = @client.post(
      "/api/v1/organizations/#{@org_id}/builds/asc_upload",
      body: {
        apple_app_id: @apple_app_id,
        cf_bundle_version: @cf_bundle_version,
        cf_bundle_short_version_string: @cf_bundle_short_version_string,
        platform: @platform,
        file_name: File.basename(@ipa_path),
        file_size: File.size(@ipa_path)
      }
    )
  rescue StandardError => e
    # Apple returns 409 from /v1/buildUploads when a build with the
    # same CFBundleVersion already exists for this app. Surface a
    # useful message instead of letting the caller print the raw
    # "ASC /v1/buildUploads returned 409" string.
    if e.message =~ /\b(409|buildUploads returned 409|duplicate)/i
      raise BuildVersionConflictError,
            "Apple refused the upload: build #{@cf_bundle_version} already exists for this app (CFBundleVersion must be unique). " \
            'Bump CFBundleVersion in your Xcode project and re-archive, then retry.'
    end
    raise
  end
  data = resp[:data]
  build_upload_id = data['build_upload_id']
  ops             = data['upload_operations']

  File.open(@ipa_path, 'rb') do |f|
    ops.each { |op| put_chunk_with_retry(f, op) }
  end

  md5 = Digest::MD5.file(@ipa_path).hexdigest
  sha = Digest::SHA256.file(@ipa_path).hexdigest

  @client.patch(
    "/api/v1/organizations/#{@org_id}/builds/asc_upload/#{build_upload_id}",
    body: { uploaded: true, source_file_checksums: { md5: md5, sha256: sha } }
  )

  final = poll_until_terminal(build_upload_id)
  { build_upload_id: build_upload_id, final_state: final }
end