fastlane 2.150.0.rc1 → 2.150.0.rc6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/deliver/lib/deliver/download_screenshots.rb +48 -26
  3. data/deliver/lib/deliver/runner.rb +0 -17
  4. data/deliver/lib/deliver/submit_for_review.rb +79 -32
  5. data/deliver/lib/deliver/upload_metadata.rb +92 -21
  6. data/deliver/lib/deliver/upload_price_tier.rb +9 -2
  7. data/deliver/lib/deliver/upload_screenshots.rb +61 -9
  8. data/fastlane/lib/fastlane/actions/.hockey.rb.swp +0 -0
  9. data/fastlane/lib/fastlane/actions/.slack.rb.swp +0 -0
  10. data/fastlane/lib/fastlane/actions/.update_project_provisioning.rb.swp +0 -0
  11. data/fastlane/lib/fastlane/actions/docs/upload_to_app_store.md.erb +78 -85
  12. data/fastlane/lib/fastlane/actions/set_changelog.rb +23 -20
  13. data/fastlane/lib/fastlane/version.rb +1 -1
  14. data/fastlane/swift/FastlaneSwiftRunner/FastlaneSwiftRunner.xcodeproj/project.xcworkspace/xcuserdata/josh.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  15. data/fastlane_core/lib/fastlane_core/build_watcher.rb +4 -4
  16. data/fastlane_core/lib/fastlane_core/itunes_transporter.rb +89 -52
  17. data/pilot/lib/pilot/.manager.rb.swp +0 -0
  18. data/produce/lib/produce/itunes_connect.rb +43 -5
  19. data/spaceship/lib/spaceship/client.rb +4 -3
  20. data/spaceship/lib/spaceship/connect_api.rb +5 -1
  21. data/spaceship/lib/spaceship/{.DS_Store → connect_api/.DS_Store} +0 -0
  22. data/spaceship/lib/spaceship/connect_api/client.rb +50 -20
  23. data/spaceship/lib/spaceship/connect_api/file_uploader.rb +98 -0
  24. data/spaceship/lib/spaceship/connect_api/models/age_rating_declaration.rb +6 -2
  25. data/spaceship/lib/spaceship/connect_api/models/app.rb +35 -13
  26. data/spaceship/lib/spaceship/connect_api/models/app_info.rb +4 -11
  27. data/spaceship/lib/spaceship/connect_api/models/app_preview.rb +129 -0
  28. data/spaceship/lib/spaceship/connect_api/models/app_preview_set.rb +71 -0
  29. data/spaceship/lib/spaceship/connect_api/models/app_review_attachment.rb +18 -28
  30. data/spaceship/lib/spaceship/connect_api/models/app_screenshot.rb +88 -59
  31. data/spaceship/lib/spaceship/connect_api/models/app_screenshot_set.rb +26 -2
  32. data/spaceship/lib/spaceship/connect_api/models/app_store_version.rb +1 -0
  33. data/spaceship/lib/spaceship/connect_api/models/app_store_version_localization.rb +16 -0
  34. data/spaceship/lib/spaceship/connect_api/models/territory.rb +27 -0
  35. data/spaceship/lib/spaceship/connect_api/models/user.rb +2 -1
  36. data/spaceship/lib/spaceship/connect_api/tunes/tunes.rb +215 -74
  37. data/spaceship/lib/spaceship/connect_api/users/users.rb +13 -0
  38. metadata +16 -7
@@ -91,10 +91,14 @@ module Spaceship
91
91
 
92
92
  def self.map_value_from_itc(key, value)
93
93
  if ["gamblingAndContests", "unrestrictedWebAccess"].include?(key)
94
- return LEGACY_BOOLEAN_VALUE_ITC_MAP[value]
94
+ new_value = LEGACY_BOOLEAN_VALUE_ITC_MAP[value]
95
+ return value if new_value.nil?
96
+ return new_value
95
97
  else
96
- return LEGACY_RATING_VALUE_ITC_MAP[value]
98
+ return LEGACY_RATING_VALUE_ITC_MAP[value] || value
97
99
  end
100
+
101
+ return value
98
102
  end
99
103
 
100
104
  #
@@ -54,16 +54,24 @@ module Spaceship
54
54
  end
55
55
  end
56
56
 
57
- def self.create(name: nil, version_string: nil, sku: nil, primary_locale: nil, bundle_id: nil, platforms: nil)
58
- Spaceship::ConnectAPI.post_app(name: name, version_string: version_string, sku: sku, primary_locale: primary_locale, bundle_id: bundle_id, platforms: platforms)
57
+ def self.create(name: nil, version_string: nil, sku: nil, primary_locale: nil, bundle_id: nil, platforms: nil, company_name: nil)
58
+ Spaceship::ConnectAPI.post_app(
59
+ name: name,
60
+ version_string: version_string,
61
+ sku: sku,
62
+ primary_locale: primary_locale,
63
+ bundle_id: bundle_id,
64
+ platforms: platforms,
65
+ company_name: company_name
66
+ )
59
67
  end
60
68
 
61
69
  def self.get(app_id: nil, includes: "appStoreVersions")
62
70
  return Spaceship::ConnectAPI.get_app(app_id: app_id, includes: includes).first
63
71
  end
64
72
 
65
- def update(attributes: nil)
66
- return Spaceship::ConnectAPI.patch_app(app_id: id, attributes: attributes)
73
+ def update(attributes: nil, app_price_tier_id: nil, territory_ids: nil)
74
+ return Spaceship::ConnectAPI.patch_app(app_id: id, attributes: attributes, app_price_tier_id: app_price_tier_id, territory_ids: territory_ids)
67
75
  end
68
76
 
69
77
  #
@@ -75,10 +83,13 @@ module Spaceship
75
83
  Spaceship::ConnectAPI::AppInfo::AppStoreState::PREPARE_FOR_SUBMISSION,
76
84
  Spaceship::ConnectAPI::AppInfo::AppStoreState::DEVELOPER_REJECTED,
77
85
  Spaceship::ConnectAPI::AppInfo::AppStoreState::REJECTED,
78
- Spaceship::ConnectAPI::AppInfo::AppStoreState::METADATA_REJECTED
86
+ Spaceship::ConnectAPI::AppInfo::AppStoreState::METADATA_REJECTED,
87
+ Spaceship::ConnectAPI::AppInfo::AppStoreState::WAITING_FOR_REVIEW,
88
+ Spaceship::ConnectAPI::AppInfo::AppStoreState::INVALID_BINARY
79
89
  ]
80
90
 
81
- resp = Spaceship::ConnectAPI.get_app_infos(app_id: id)
91
+ filter = { app: id }
92
+ resp = Spaceship::ConnectAPI.get_app_infos(filter: filter)
82
93
  return resp.to_models.select do |model|
83
94
  states.include?(model.app_store_state)
84
95
  end.first
@@ -95,11 +106,6 @@ module Spaceship
95
106
  return resp.to_models
96
107
  end
97
108
 
98
- def update_app_price_tier(app_price_tier_id: nil)
99
- resp = Spaceship::ConnectAPI.patch_app_app_prices(app_id: id, app_price_tier_id: app_price_tier_id)
100
- return resp.first
101
- end
102
-
103
109
  #
104
110
  # App Store Versions
105
111
  #
@@ -142,11 +148,17 @@ module Spaceship
142
148
  Spaceship::ConnectAPI::AppStoreVersion::AppStoreState::PREPARE_FOR_SUBMISSION,
143
149
  Spaceship::ConnectAPI::AppStoreVersion::AppStoreState::DEVELOPER_REJECTED,
144
150
  Spaceship::ConnectAPI::AppStoreVersion::AppStoreState::REJECTED,
145
- Spaceship::ConnectAPI::AppStoreVersion::AppStoreState::METADATA_REJECTED
151
+ Spaceship::ConnectAPI::AppStoreVersion::AppStoreState::METADATA_REJECTED,
152
+ Spaceship::ConnectAPI::AppStoreVersion::AppStoreState::WAITING_FOR_REVIEW,
153
+ Spaceship::ConnectAPI::AppStoreVersion::AppStoreState::INVALID_BINARY
146
154
  ].join(","),
147
155
  platform: platform
148
156
  }
149
- return get_app_store_versions(filter: filter, includes: includes).first
157
+
158
+ # Get the latest version
159
+ return get_app_store_versions(filter: filter, includes: includes)
160
+ .sort_by { |v| Gem::Version.new(v.version_string) }
161
+ .last
150
162
  end
151
163
 
152
164
  def get_app_store_versions(filter: {}, includes: nil, limit: nil, sort: nil)
@@ -224,6 +236,16 @@ module Spaceship
224
236
  ).all_pages
225
237
  return resps.flat_map(&:to_models).first
226
238
  end
239
+
240
+ #
241
+ # Users
242
+ #
243
+
244
+ def add_users(user_ids: nil)
245
+ user_ids.each do |user_id|
246
+ Spaceship::ConnectAPI.add_user_visible_apps(user_id: user_id, app_ids: [id])
247
+ end
248
+ end
227
249
  end
228
250
  end
229
251
  end
@@ -16,6 +16,7 @@ module Spaceship
16
16
  REJECTED = "REJECTED"
17
17
  PREPARE_FOR_SUBMISSION = "PREPARE_FOR_SUBMISSION"
18
18
  METADATA_REJECTED = "METADATA_REJECTED"
19
+ INVALID_BINARY = "INVALID_BINARY"
19
20
  end
20
21
 
21
22
  module AppStoreAgeRating
@@ -38,19 +39,11 @@ module Spaceship
38
39
  #
39
40
 
40
41
  def update(filter: {}, includes: nil, limit: nil, sort: nil)
41
- Spaceship::ConnectAPI.patch_app_info(app_info_id: id)
42
+ Spaceship::ConnectAPI.patch_app_info(app_info_id: id).first
42
43
  end
43
44
 
44
- def update_categories(primary_category_id: nil, secondary_category_id: nil, primary_subcategory_one_id: nil, primary_subcategory_two_id: nil, secondary_subcategory_one_id: nil, secondary_subcategory_two_id: nil)
45
- Spaceship::ConnectAPI.patch_app_info_categories(
46
- app_info_id: id,
47
- primary_category_id: primary_category_id,
48
- secondary_category_id: secondary_category_id,
49
- primary_subcategory_one_id: primary_subcategory_one_id,
50
- primary_subcategory_two_id: primary_subcategory_two_id,
51
- secondary_subcategory_one_id: secondary_subcategory_one_id,
52
- secondary_subcategory_two_id: secondary_subcategory_two_id
53
- )
45
+ def update_categories(category_id_map: nil)
46
+ Spaceship::ConnectAPI.patch_app_info_categories(app_info_id: id, category_id_map: category_id_map).first
54
47
  end
55
48
 
56
49
  def delete!(filter: {}, includes: nil, limit: nil, sort: nil)
@@ -0,0 +1,129 @@
1
+ require_relative '../model'
2
+ require_relative '../file_uploader'
3
+ require 'spaceship/globals'
4
+
5
+ require 'digest/md5'
6
+
7
+ module Spaceship
8
+ class ConnectAPI
9
+ class AppPreview
10
+ include Spaceship::ConnectAPI::Model
11
+
12
+ attr_accessor :file_size
13
+ attr_accessor :file_name
14
+ attr_accessor :source_file_checksum
15
+ attr_accessor :preview_frame_time_code
16
+ attr_accessor :mime_type
17
+ attr_accessor :video_url
18
+ attr_accessor :preview_image
19
+ attr_accessor :upload_operations
20
+ attr_accessor :asset_deliver_state
21
+ attr_accessor :upload
22
+
23
+ attr_mapping({
24
+ "fileSize" => "file_size",
25
+ "fileName" => "file_name",
26
+ "sourceFileChecksum" => "source_file_checksum",
27
+ "previewFrameTimeCode" => "preview_frame_time_code",
28
+ "mimeType" => "mime_type",
29
+ "videoUrl" => "video_url",
30
+ "previewImage" => "preview_image",
31
+ "uploadOperations" => "upload_operations",
32
+ "assetDeliveryState" => "asset_delivery_state",
33
+ "uploaded" => "uploaded"
34
+ })
35
+
36
+ def self.type
37
+ return "appPreviews"
38
+ end
39
+
40
+ def complete?
41
+ (asset_delivery_state || {})["state"] == "COMPLETE"
42
+ end
43
+
44
+ #
45
+ # API
46
+ #
47
+
48
+ def self.get(app_preview_id: nil)
49
+ Spaceship::ConnectAPI.get_app_preview(app_preview_id: app_preview_id).first
50
+ end
51
+
52
+ # Creates an AppPreview in an AppPreviewSet
53
+ # Setting the optional frame_time_code will force polling until video is done processing
54
+ # @param app_preview_set_id The AppPreviewSet id
55
+ # @param path The path of the file
56
+ # @param frame_time_code The time code for the preview still frame (ex: "00:00:07:01")
57
+ def self.create(app_preview_set_id: nil, path: nil, frame_time_code: nil)
58
+ require 'faraday'
59
+
60
+ filename = File.basename(path)
61
+ filesize = File.size(path)
62
+ bytes = File.binread(path)
63
+
64
+ post_attributes = {
65
+ fileSize: filesize,
66
+ fileName: filename
67
+ }
68
+
69
+ # Create placeholder
70
+ preview = Spaceship::ConnectAPI.post_app_preview(
71
+ app_preview_set_id: app_preview_set_id,
72
+ attributes: post_attributes
73
+ ).to_models.first
74
+
75
+ # Upload the file
76
+ upload_operations = preview.upload_operations
77
+ Spaceship::ConnectAPI::FileUploader.upload(upload_operations, bytes)
78
+
79
+ # Update file uploading complete
80
+ patch_attributes = {
81
+ uploaded: true,
82
+ sourceFileChecksum: Digest::MD5.hexdigest(bytes)
83
+ }
84
+
85
+ begin
86
+ preview = Spaceship::ConnectAPI.patch_app_preview(
87
+ app_preview_id: preview.id,
88
+ attributes: patch_attributes
89
+ ).to_models.first
90
+ rescue => error
91
+ puts("Failed to patch app preview. Update may have gone through so verifying") if Spaceship::Globals.verbose?
92
+
93
+ preview = Spaceship::ConnectAPI::AppPreview.get(app_preview_id: preview.id)
94
+ raise error unless preview.complete?
95
+ end
96
+
97
+ # Poll for video processing completion to set still frame time
98
+ unless frame_time_code.nil?
99
+ loop do
100
+ unless preview.video_url.nil?
101
+ puts("Preview processing complete!") if Spaceship::Globals.verbose?
102
+ preview = preview.update(attributes: {
103
+ previewFrameTimeCode: frame_time_code
104
+ })
105
+ puts("Updated preview frame time code!") if Spaceship::Globals.verbose?
106
+ break
107
+ end
108
+
109
+ sleep_time = 30
110
+ puts("Waiting #{sleep_time} seconds before checking status of processing...") if Spaceship::Globals.verbose?
111
+ sleep(sleep_time)
112
+
113
+ preview = Spaceship::ConnectAPI::AppPreview.get(app_preview_id: preview.id)
114
+ end
115
+ end
116
+
117
+ preview
118
+ end
119
+
120
+ def update(attributes: nil)
121
+ Spaceship::ConnectAPI.patch_app_preview(app_preview_id: id, attributes: attributes)
122
+ end
123
+
124
+ def delete!(filter: {}, includes: nil, limit: nil, sort: nil)
125
+ Spaceship::ConnectAPI.delete_app_preview(app_preview_id: id)
126
+ end
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,71 @@
1
+ require_relative '../model'
2
+ require_relative './app_preview'
3
+
4
+ module Spaceship
5
+ class ConnectAPI
6
+ class AppPreviewSet
7
+ include Spaceship::ConnectAPI::Model
8
+
9
+ attr_accessor :preview_type
10
+
11
+ attr_accessor :app_previews
12
+
13
+ module PreviewType
14
+ IPHONE_35 = "IPHONE_35"
15
+ IPHONE_40 = "IPHONE_40"
16
+ IPHONE_47 = "IPHONE_47"
17
+ IPHONE_55 = "IPHONE_55"
18
+ IPHONE_58 = "IPHONE_58"
19
+ IPHONE_65 = "IPHONE_65"
20
+
21
+ IPAD_97 = "IPAD_97"
22
+ IPAD_105 = "IPAD_105"
23
+ IPAD_PRO_3GEN_11 = "IPAD_PRO_3GEN_11"
24
+ IPAD_PRO_129 = "IPAD_PRO_129"
25
+ IPAD_PRO_3GEN_129 = "IPAD_PRO_3GEN_129"
26
+
27
+ DESKTOP = "DESKTOP"
28
+
29
+ ALL = [
30
+ IPHONE_35,
31
+ IPHONE_40,
32
+ IPHONE_47,
33
+ IPHONE_55,
34
+ IPHONE_58,
35
+ IPHONE_65,
36
+
37
+ IPAD_97,
38
+ IPAD_105,
39
+ IPAD_PRO_3GEN_11,
40
+ IPAD_PRO_129,
41
+ IPAD_PRO_3GEN_129,
42
+
43
+ DESKTOP
44
+ ]
45
+ end
46
+
47
+ attr_mapping({
48
+ "previewType" => "preview_type",
49
+
50
+ "appPreviews" => "app_previews"
51
+ })
52
+
53
+ def self.type
54
+ return "appPreviewSets"
55
+ end
56
+
57
+ #
58
+ # API
59
+ #
60
+
61
+ def self.all(filter: {}, includes: nil, limit: nil, sort: nil)
62
+ resp = Spaceship::ConnectAPI.get_app_preview_sets(filter: filter, includes: includes, limit: limit, sort: sort)
63
+ return resp.to_models
64
+ end
65
+
66
+ def upload_preview(path: nil, frame_time_code: nil)
67
+ return Spaceship::ConnectAPI::AppPreview.create(app_preview_set_id: id, path: path, frame_time_code: frame_time_code)
68
+ end
69
+ end
70
+ end
71
+ end
@@ -1,4 +1,7 @@
1
1
  require_relative '../model'
2
+ require_relative '../file_uploader'
3
+ require 'digest/md5'
4
+
2
5
  module Spaceship
3
6
  class ConnectAPI
4
7
  class AppReviewAttachment
@@ -31,46 +34,33 @@ module Spaceship
31
34
 
32
35
  filename = File.basename(path)
33
36
  filesize = File.size(path)
34
- payload = File.binread(path)
37
+ bytes = File.binread(path)
35
38
 
36
39
  post_attributes = {
37
40
  fileSize: filesize,
38
41
  fileName: filename
39
42
  }
40
43
 
41
- post_resp = Spaceship::ConnectAPI.post_app_review_attachment(app_store_review_detail_id: app_store_review_detail_id, attributes: post_attributes).to_models.first
42
-
43
- # {
44
- # "method": "PUT",
45
- # "url": "https://some-url-apple-gives-us",
46
- # "length": 57365,
47
- # "offset": 0,
48
- # "requestHeaders": [
49
- # {
50
- # "name": "Content-Type",
51
- # "value": "image/png"
52
- # }
53
- # ]
54
- # }
55
- upload_operation = post_resp.upload_operations.first
56
-
57
- headers = {}
58
- upload_operation["requestHeaders"].each do |hash|
59
- headers[hash["name"]] = hash["value"]
60
- end
44
+ # Create placeholder
45
+ attachment = Spaceship::ConnectAPI.post_app_review_attachment(
46
+ app_store_review_detail_id: app_store_review_detail_id,
47
+ attributes: post_attributes
48
+ ).to_models.first
61
49
 
62
- Faraday.put(
63
- upload_operation["url"],
64
- payload,
65
- headers
66
- )
50
+ # Upload the file
51
+ upload_operations = attachment.upload_operations
52
+ Spaceship::ConnectAPI::FileUploader.upload(upload_operations, bytes)
67
53
 
54
+ # Update file uploading complete
68
55
  patch_attributes = {
69
56
  uploaded: true,
70
- sourceFileChecksum: "checksum-holder"
57
+ sourceFileChecksum: Digest::MD5.hexdigest(bytes)
71
58
  }
72
59
 
73
- Spaceship::ConnectAPI.patch_app_review_attachment(app_review_attachment_id: post_resp.id, attributes: patch_attributes).to_models.first
60
+ Spaceship::ConnectAPI.patch_app_review_attachment(
61
+ app_review_attachment_id: attachment.id,
62
+ attributes: patch_attributes
63
+ ).to_models.first
74
64
  end
75
65
 
76
66
  def delete!(filter: {}, includes: nil, limit: nil, sort: nil)
@@ -1,4 +1,9 @@
1
1
  require_relative '../model'
2
+ require_relative '../file_uploader'
3
+ require 'spaceship/globals'
4
+
5
+ require 'digest/md5'
6
+
2
7
  module Spaceship
3
8
  class ConnectAPI
4
9
  class AppScreenshot
@@ -13,36 +18,6 @@ module Spaceship
13
18
  attr_accessor :asset_delivery_state
14
19
  attr_accessor :uploaded
15
20
 
16
- # "fileSize": 92542,
17
- # "fileName": "ftl_3241d62418767c0aa9b889b020c4f8db_45455763d4aaf7b18ee0045bc787f3de.png",
18
- # "sourceFileChecksum": "c237fd7852ed8f9285d16d9a28d2ec25",
19
- # "imageAsset": {
20
- # "templateUrl": "https://is4-ssl.mzstatic.com/image/thumb/Purple113/v4/61/18/68/61186886-b234-5bd0-1f4a-563124f18511/pr_source.png/{w}x{h}bb.{f}",
21
- # "width": 2048,
22
- # "height": 2732
23
- # },
24
- # "assetToken": "Purple113/v4/61/18/68/61186886-b234-5bd0-1f4a-563124f18511/pr_source.png",
25
- # "assetType": "SortedJ99ScreenShot",
26
- # "uploadOperations": null,
27
- # "assetDeliveryState": {
28
- # "errors": [],
29
- # "warnings": null,
30
- # "state": "COMPLETE"
31
- # },
32
- # "uploaded": null
33
-
34
- # "assetDeliveryState": {
35
- # "errors": [],
36
- # "warnings": null,
37
- # "state": "AWAITING_UPLOAD"
38
- # },
39
-
40
- # "assetDeliveryState": {
41
- # "errors": [],
42
- # "warnings": null,
43
- # "state": "UPLOAD_COMPLETE"
44
- # },
45
-
46
21
  attr_mapping({
47
22
  "fileName" => "file_name",
48
23
  "sourceFileChecksum" => "source_file_checksum",
@@ -58,55 +33,109 @@ module Spaceship
58
33
  return "appScreenshots"
59
34
  end
60
35
 
36
+ def complete?
37
+ (asset_delivery_state || {})["state"] == "COMPLETE"
38
+ end
39
+
40
+ def error?
41
+ (asset_delivery_state || {})["state"] == "FAILED"
42
+ end
43
+
44
+ def error_messages
45
+ errors = (asset_delivery_state || {})["errors"]
46
+ (errors || []).map do |error|
47
+ [error["code"], error["description"]].compact.join(" - ")
48
+ end
49
+ end
50
+
51
+ # This does not download the source image (exact image that was uploaded)
52
+ # This downloads a modified version.
53
+ # This image won't have the same checksums as source_file_checksum.
54
+ #
55
+ # There is an open radar for allowing downloading of source file.
56
+ # https://openradar.appspot.com/radar?id=4980344105205760
57
+ def image_asset_url(width: nil, height: nil, type: "png")
58
+ return nil if image_asset.nil?
59
+
60
+ template_url = image_asset["templateUrl"]
61
+ width ||= image_asset["width"]
62
+ height ||= image_asset["height"]
63
+
64
+ return template_url
65
+ .gsub("{w}", width.to_s)
66
+ .gsub("{h}", height.to_s)
67
+ .gsub("{f}", type)
68
+ end
69
+
61
70
  #
62
71
  # API
63
72
  #
73
+ #
64
74
 
65
- def self.create(app_screenshot_set_id: nil, path: nil)
75
+ def self.create(app_screenshot_set_id: nil, path: nil, wait_for_processing: true)
66
76
  require 'faraday'
67
77
 
68
78
  filename = File.basename(path)
69
79
  filesize = File.size(path)
70
- payload = File.binread(path)
80
+ bytes = File.binread(path)
71
81
 
72
82
  post_attributes = {
73
83
  fileSize: filesize,
74
84
  fileName: filename
75
85
  }
76
86
 
77
- post_resp = Spaceship::ConnectAPI.post_app_screenshot(app_screenshot_set_id: app_screenshot_set_id, attributes: post_attributes).to_models.first
78
-
79
- # {
80
- # "method": "PUT",
81
- # "url": "https://some-url-apple-gives-us",
82
- # "length": 57365,
83
- # "offset": 0,
84
- # "requestHeaders": [
85
- # {
86
- # "name": "Content-Type",
87
- # "value": "image/png"
88
- # }
89
- # ]
90
- # }
91
- upload_operation = post_resp.upload_operations.first
92
-
93
- headers = {}
94
- upload_operation["requestHeaders"].each do |hash|
95
- headers[hash["name"]] = hash["value"]
96
- end
87
+ # Create placeholder
88
+ screenshot = Spaceship::ConnectAPI.post_app_screenshot(
89
+ app_screenshot_set_id: app_screenshot_set_id,
90
+ attributes: post_attributes
91
+ ).first
97
92
 
98
- Faraday.put(
99
- upload_operation["url"],
100
- payload,
101
- headers
102
- )
93
+ # Upload the file
94
+ upload_operations = screenshot.upload_operations
95
+ Spaceship::ConnectAPI::FileUploader.upload(upload_operations, bytes)
103
96
 
97
+ # Update file uploading complete
104
98
  patch_attributes = {
105
99
  uploaded: true,
106
- sourceFileChecksum: "checksum-holder"
100
+ sourceFileChecksum: Digest::MD5.hexdigest(bytes)
107
101
  }
108
102
 
109
- Spaceship::ConnectAPI.patch_app_screenshot(app_screenshot_id: post_resp.id, attributes: patch_attributes).to_models.first
103
+ # Patch screenshot that file upload is complete
104
+ # Catch error if patch retries due to 504. Origal patch
105
+ # may go through by return response as 504.
106
+ begin
107
+ screenshot = Spaceship::ConnectAPI.patch_app_screenshot(
108
+ app_screenshot_id: screenshot.id,
109
+ attributes: patch_attributes
110
+ ).first
111
+ rescue => error
112
+ puts("Failed to patch app screenshot. Update may have gone through so verifying") if Spaceship::Globals.verbose?
113
+
114
+ screenshot = Spaceship::ConnectAPI.get_app_screenshot(app_screenshot_id: screenshot.id).first
115
+ raise error unless screenshot.complete?
116
+ end
117
+
118
+ # Wait for processing
119
+ if wait_for_processing
120
+ loop do
121
+ if screenshot.complete?
122
+ puts("Screenshot processing complete!") if Spaceship::Globals.verbose?
123
+ break
124
+ elsif screenshot.error?
125
+ messages = ["Error processing screenshot '#{screenshot.file_name}'"] + screenshot.error_messages
126
+ raise messages.join(". ")
127
+ end
128
+
129
+ # Poll every 2 seconds
130
+ sleep_time = 2
131
+ puts("Waiting #{sleep_time} seconds before checking status of processing...") if Spaceship::Globals.verbose?
132
+ sleep(sleep_time)
133
+
134
+ screenshot = Spaceship::ConnectAPI.get_app_screenshot(app_screenshot_id: screenshot.id).first
135
+ end
136
+ end
137
+
138
+ return screenshot
110
139
  end
111
140
 
112
141
  def delete!(filter: {}, includes: nil, limit: nil, sort: nil)