fastlane 2.152.0 → 2.153.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +76 -76
  3. data/deliver/lib/deliver/app_screenshot.rb +1 -1
  4. data/deliver/lib/deliver/commands_generator.rb +7 -4
  5. data/deliver/lib/deliver/detect_values.rb +9 -3
  6. data/deliver/lib/deliver/download_screenshots.rb +1 -3
  7. data/deliver/lib/deliver/runner.rb +5 -10
  8. data/deliver/lib/deliver/setup.rb +94 -3
  9. data/deliver/lib/deliver/submit_for_review.rb +1 -3
  10. data/deliver/lib/deliver/upload_metadata.rb +25 -22
  11. data/deliver/lib/deliver/upload_price_tier.rb +1 -3
  12. data/deliver/lib/deliver/upload_screenshots.rb +75 -44
  13. data/{deliver/lib/deliver/.commands_generator.rb.swp → fastlane/lib/fastlane/.erb_template_helper.rb.swp} +0 -0
  14. data/fastlane/lib/fastlane/actions/.git_commit.rb.swp +0 -0
  15. data/fastlane/lib/fastlane/actions/docs/frame_screenshots.md +3 -1
  16. data/fastlane/lib/fastlane/actions/docs/upload_to_app_store.md.erb +1 -1
  17. data/fastlane/lib/fastlane/actions/download_dsyms.rb +4 -2
  18. data/fastlane/lib/fastlane/actions/erb.rb +10 -2
  19. data/fastlane/lib/fastlane/runner.rb +3 -1
  20. data/fastlane/lib/fastlane/version.rb +1 -1
  21. data/fastlane/swift/Deliverfile.swift +1 -1
  22. data/fastlane/swift/DeliverfileProtocol.swift +1 -1
  23. data/fastlane/swift/Fastlane.swift +7 -4
  24. data/fastlane/swift/Gymfile.swift +1 -1
  25. data/fastlane/swift/GymfileProtocol.swift +1 -1
  26. data/fastlane/swift/Matchfile.swift +1 -1
  27. data/fastlane/swift/MatchfileProtocol.swift +1 -1
  28. data/fastlane/swift/Precheckfile.swift +1 -1
  29. data/fastlane/swift/PrecheckfileProtocol.swift +1 -1
  30. data/fastlane/swift/Scanfile.swift +1 -1
  31. data/fastlane/swift/ScanfileProtocol.swift +1 -1
  32. data/fastlane/swift/Screengrabfile.swift +1 -1
  33. data/fastlane/swift/ScreengrabfileProtocol.swift +1 -1
  34. data/fastlane/swift/Snapshotfile.swift +1 -1
  35. data/fastlane/swift/SnapshotfileProtocol.swift +1 -1
  36. data/fastlane_core/lib/fastlane_core/device_manager.rb +20 -6
  37. data/frameit/lib/frameit/editor.rb +8 -5
  38. data/scan/lib/scan/runner.rb +19 -6
  39. data/spaceship/lib/spaceship/connect_api.rb +1 -0
  40. data/spaceship/lib/spaceship/connect_api/client.rb +2 -2
  41. data/spaceship/lib/spaceship/connect_api/model.rb +10 -0
  42. data/spaceship/lib/spaceship/connect_api/models/.app_screenshot.rb.swp +0 -0
  43. data/spaceship/lib/spaceship/connect_api/models/age_rating_declaration.rb +1 -0
  44. data/spaceship/lib/spaceship/connect_api/models/app.rb +40 -2
  45. data/spaceship/lib/spaceship/connect_api/models/app_info_localization.rb +1 -0
  46. data/spaceship/lib/spaceship/connect_api/models/app_preview.rb +1 -0
  47. data/spaceship/lib/spaceship/connect_api/models/app_screenshot.rb +44 -5
  48. data/spaceship/lib/spaceship/connect_api/models/app_store_review_detail.rb +1 -0
  49. data/spaceship/lib/spaceship/connect_api/models/app_store_version.rb +10 -0
  50. data/spaceship/lib/spaceship/connect_api/models/app_store_version_localization.rb +1 -0
  51. data/spaceship/lib/spaceship/connect_api/models/app_store_version_release_request.rb +12 -0
  52. data/spaceship/lib/spaceship/connect_api/models/build.rb +1 -0
  53. data/spaceship/lib/spaceship/connect_api/models/idfa_declaration.rb +1 -0
  54. data/spaceship/lib/spaceship/connect_api/tunes/tunes.rb +32 -1
  55. metadata +34 -59
  56. data/deliver/lib/deliver/.submit_for_review.rb.swp +0 -0
  57. data/deliver/lib/deliver/.upload_metadata.rb.swp +0 -0
@@ -33,4 +33,4 @@ extension PrecheckfileProtocol {
33
33
 
34
34
  // Please don't remove the lines below
35
35
  // They are used to detect outdated files
36
- // FastlaneRunnerAPIVersion [0.9.21]
36
+ // FastlaneRunnerAPIVersion [0.9.22]
@@ -14,4 +14,4 @@ class Scanfile: ScanfileProtocol {
14
14
  // during the `init` process, and you won't see this message
15
15
  }
16
16
 
17
- // Generated with fastlane 2.152.0
17
+ // Generated with fastlane 2.153.0
@@ -257,4 +257,4 @@ extension ScanfileProtocol {
257
257
 
258
258
  // Please don't remove the lines below
259
259
  // They are used to detect outdated files
260
- // FastlaneRunnerAPIVersion [0.9.33]
260
+ // FastlaneRunnerAPIVersion [0.9.34]
@@ -14,4 +14,4 @@ class Screengrabfile: ScreengrabfileProtocol {
14
14
  // during the `init` process, and you won't see this message
15
15
  }
16
16
 
17
- // Generated with fastlane 2.152.0
17
+ // Generated with fastlane 2.153.0
@@ -93,4 +93,4 @@ extension ScreengrabfileProtocol {
93
93
 
94
94
  // Please don't remove the lines below
95
95
  // They are used to detect outdated files
96
- // FastlaneRunnerAPIVersion [0.9.23]
96
+ // FastlaneRunnerAPIVersion [0.9.24]
@@ -14,4 +14,4 @@ class Snapshotfile: SnapshotfileProtocol {
14
14
  // during the `init` process, and you won't see this message
15
15
  }
16
16
 
17
- // Generated with fastlane 2.152.0
17
+ // Generated with fastlane 2.153.0
@@ -173,4 +173,4 @@ extension SnapshotfileProtocol {
173
173
 
174
174
  // Please don't remove the lines below
175
175
  // They are used to detect outdated files
176
- // FastlaneRunnerAPIVersion [0.9.17]
176
+ // FastlaneRunnerAPIVersion [0.9.18]
@@ -199,18 +199,32 @@ module FastlaneCore
199
199
  self.name
200
200
  end
201
201
 
202
+ def boot
203
+ return unless is_simulator
204
+ return unless os_type == "iOS"
205
+
206
+ UI.message("Booting #{self}")
207
+ `xcrun simctl boot #{self.udid}` unless self.state == "Booted"
208
+ end
209
+
210
+ def shutdown
211
+ return unless is_simulator
212
+ return unless os_type == "iOS"
213
+
214
+ UI.message("Shutting down #{self.udid}")
215
+ `xcrun simctl shutdown #{self.udid}` if self.state == "Booted"
216
+ end
217
+
202
218
  def reset
203
219
  UI.message("Resetting #{self}")
204
- `xcrun simctl shutdown #{self.udid}` if self.state == "Booted"
220
+ shutdown
205
221
  `xcrun simctl erase #{self.udid}`
206
- return
207
222
  end
208
223
 
209
224
  def delete
210
225
  UI.message("Deleting #{self}")
211
- `xcrun simctl shutdown #{self.udid}` unless self.state == "Shutdown"
226
+ shutdown
212
227
  `xcrun simctl delete #{self.udid}`
213
- return
214
228
  end
215
229
 
216
230
  def disable_slide_to_type
@@ -324,10 +338,10 @@ module FastlaneCore
324
338
  def copy_logarchive(device, log_identity, logs_destination_dir)
325
339
  require 'shellwords'
326
340
 
327
- logarchive_dst = File.join(logs_destination_dir, "system_logs-#{log_identity}.logarchive").shellescape
341
+ logarchive_dst = File.join(logs_destination_dir, "system_logs-#{log_identity}.logarchive")
328
342
  FileUtils.rm_rf(logarchive_dst)
329
343
  FileUtils.mkdir_p(File.expand_path("..", logarchive_dst))
330
- command = "xcrun simctl spawn --standalone #{device.udid} log collect --output #{logarchive_dst} 2>/dev/null"
344
+ command = "xcrun simctl spawn #{device.udid} log collect --output #{logarchive_dst.shellescape} 2>/dev/null"
331
345
  FastlaneCore::CommandExecutor.execute(command: command, print_all: false, print_command: true)
332
346
  end
333
347
  end
@@ -298,7 +298,7 @@ module Frameit
298
298
  resize_text(keyword)
299
299
 
300
300
  vertical_padding = vertical_frame_padding # assign padding to variable
301
- spacing_between_title_and_keyword = (actual_font_size / 2)
301
+ spacing_between_title_and_keyword = (actual_font_size('keyword') / 2)
302
302
  title_left_space = (background.width / 2.0 - title.width / 2.0).round
303
303
  keyword_left_space = (background.width / 2.0 - keyword.width / 2.0).round
304
304
 
@@ -359,7 +359,7 @@ module Frameit
359
359
  vertical_padding = vertical_frame_padding # assign padding to variable
360
360
  left_space = (background.width / 2.0 - sum_width / 2.0).round
361
361
 
362
- self.space_to_device += actual_font_size + vertical_padding
362
+ self.space_to_device += actual_font_size('title') + vertical_padding
363
363
 
364
364
  if title_below_image
365
365
  title_top = background.height - effective_text_height / 2 - title.height / 2
@@ -385,7 +385,10 @@ module Frameit
385
385
  background
386
386
  end
387
387
 
388
- def actual_font_size
388
+ def actual_font_size(key)
389
+ font_size = @config[key.to_s]['font_size']
390
+ return font_size if !font_size.nil? && font_size > 0
391
+
389
392
  font_scale_factor = @config['font_scale_factor'] || 0.1
390
393
  UI.user_error!("Parameter 'font_scale_factor' can not be 0. Please provide a value larger than 0.0 (default = 0.1).") if font_scale_factor == 0.0
391
394
  [@image.width * font_scale_factor].max.round
@@ -393,7 +396,7 @@ module Frameit
393
396
 
394
397
  # The space between the keyword and the title
395
398
  def keyword_padding
396
- (actual_font_size / 3.0).round
399
+ (actual_font_size('keyword') / 3.0).round
397
400
  end
398
401
 
399
402
  # This will build up to 2 individual images with the title and optional keyword, which will then be added to the real image
@@ -427,7 +430,7 @@ module Frameit
427
430
  text_image.combine_options do |i|
428
431
  i.font(current_font) if current_font
429
432
  i.gravity("Center")
430
- i.pointsize(actual_font_size)
433
+ i.pointsize(actual_font_size(key))
431
434
  i.draw("text 0,0 '#{text}'")
432
435
  i.interline_spacing(interline_spacing) if interline_spacing
433
436
  i.fill(@config[key.to_s]['color'])
@@ -39,12 +39,7 @@ module Scan
39
39
  end
40
40
  end
41
41
 
42
- # We call this method, to be sure that all other simulators are killed
43
- # And a correct one is freshly launched. Switching between multiple simulator
44
- # in case the user specified multiple targets works with no issues
45
- # This way it's okay to just call it for the first simulator we're using for
46
- # the first test run
47
- FastlaneCore::Simulator.launch(Scan.devices.first) if Scan.devices && Scan.config[:prelaunch_simulator]
42
+ prelaunch_simulators
48
43
 
49
44
  if Scan.config[:reinstall_app]
50
45
  app_identifier = Scan.config[:app_identifier]
@@ -165,6 +160,24 @@ module Scan
165
160
  File.read(Scan.cache[:temp_junit_report])
166
161
  end
167
162
 
163
+ def prelaunch_simulators
164
+ return unless Scan.devices.to_a.size > 0 # no devices selected, no sims to launch
165
+
166
+ # Return early unless the user wants to prelaunch simulators. Or if the user wants simulator logs
167
+ # then we must prelaunch simulators because Xcode's headless
168
+ # mode launches and shutsdown the simulators before we can collect the logs.
169
+ return unless Scan.config[:prelaunch_simulator] || Scan.config[:include_simulator_logs]
170
+
171
+ devices_to_shutdown = []
172
+ Scan.devices.each do |device|
173
+ devices_to_shutdown << device if device.state == "Shutdown"
174
+ device.boot
175
+ end
176
+ at_exit do
177
+ devices_to_shutdown.each(&:shutdown)
178
+ end
179
+ end
180
+
168
181
  def copy_simulator_logs
169
182
  return unless Scan.config[:include_simulator_logs]
170
183
 
@@ -42,6 +42,7 @@ require 'spaceship/connect_api/models/app_price'
42
42
  require 'spaceship/connect_api/models/app_price_tier'
43
43
  require 'spaceship/connect_api/models/app_store_review_attachment'
44
44
  require 'spaceship/connect_api/models/app_store_review_detail'
45
+ require 'spaceship/connect_api/models/app_store_version_release_request'
45
46
  require 'spaceship/connect_api/models/app_store_version_submission'
46
47
  require 'spaceship/connect_api/models/app_screenshot_set'
47
48
  require 'spaceship/connect_api/models/app_screenshot'
@@ -88,8 +88,8 @@ module Spaceship
88
88
  handle_response(response)
89
89
  end
90
90
 
91
- def post(url_or_path, body)
92
- response = with_asc_retry do
91
+ def post(url_or_path, body, tries: 5)
92
+ response = with_asc_retry(tries) do
93
93
  request(:post) do |req|
94
94
  req.url(url_or_path)
95
95
  req.body = body.to_json
@@ -8,6 +8,7 @@ module Spaceship
8
8
  end
9
9
 
10
10
  attr_accessor :id
11
+ attr_accessor :reverse_attr_map
11
12
 
12
13
  def initialize(id, attributes)
13
14
  self.id = id
@@ -29,6 +30,7 @@ module Spaceship
29
30
  # Creates alias for :minOsVersion to :min_os_version
30
31
  #
31
32
  def attr_mapping(attr_map)
33
+ self.reverse_attr_map ||= attr_map.invert
32
34
  attr_map.each do |key, value|
33
35
  # Actual
34
36
  reader = value.to_sym
@@ -50,6 +52,14 @@ module Spaceship
50
52
  end
51
53
  end
52
54
 
55
+ def reverse_attr_mapping(attributes)
56
+ return nil if attributes.nil?
57
+ attributes.each_with_object({}) do |(k, v), memo|
58
+ key = self.class.reverse_attr_map[k] || k
59
+ memo[key] = v
60
+ end
61
+ end
62
+
53
63
  def to_json(*options)
54
64
  instance_variables.map do |var|
55
65
  [var.to_s[1..-1], instance_variable_get(var)]
@@ -106,6 +106,7 @@ module Spaceship
106
106
  #
107
107
 
108
108
  def update(attributes: nil)
109
+ attributes = reverse_attr_mapping(attributes)
109
110
  Spaceship::ConnectAPI.patch_age_rating_declaration(age_rating_declaration_id: id, attributes: attributes)
110
111
  end
111
112
  end
@@ -12,9 +12,8 @@ module Spaceship
12
12
  attr_accessor :primary_locale
13
13
  attr_accessor :removed
14
14
  attr_accessor :is_aag
15
-
15
+ attr_accessor :available_in_new_territories
16
16
  attr_accessor :content_rights_declaration
17
-
18
17
  attr_accessor :app_store_versions
19
18
 
20
19
  module ContentRightsDeclaration
@@ -29,6 +28,7 @@ module Spaceship
29
28
  "primaryLocale" => "primary_locale",
30
29
  "removed" => "removed",
31
30
  "isAAG" => "is_aag",
31
+ "availableInNewTerritories" => "available_in_new_territories",
32
32
 
33
33
  "contentRightsDeclaration" => "content_rights_declaration",
34
34
 
@@ -71,6 +71,7 @@ module Spaceship
71
71
  end
72
72
 
73
73
  def update(attributes: nil, app_price_tier_id: nil, territory_ids: nil)
74
+ attributes = reverse_attr_mapping(attributes)
74
75
  return Spaceship::ConnectAPI.patch_app(app_id: id, attributes: attributes, app_price_tier_id: app_price_tier_id, territory_ids: territory_ids)
75
76
  end
76
77
 
@@ -78,6 +79,21 @@ module Spaceship
78
79
  # App Info
79
80
  #
80
81
 
82
+ def fetch_live_app_info(includes: Spaceship::ConnectAPI::AppInfo::ESSENTIAL_INCLUDES)
83
+ states = [
84
+ Spaceship::ConnectAPI::AppInfo::AppStoreState::READY_FOR_SALE,
85
+ Spaceship::ConnectAPI::AppInfo::AppStoreState::PENDING_DEVELOPER_RELEASE,
86
+ Spaceship::ConnectAPI::AppInfo::AppStoreState::PROCESSING_FOR_APP_STORE,
87
+ Spaceship::ConnectAPI::AppInfo::AppStoreState::IN_REVIEW
88
+ ]
89
+
90
+ filter = { app: id }
91
+ resp = Spaceship::ConnectAPI.get_app_infos(filter: filter, includes: includes)
92
+ return resp.to_models.select do |model|
93
+ states.include?(model.app_store_state)
94
+ end.first
95
+ end
96
+
81
97
  def fetch_edit_app_info(includes: Spaceship::ConnectAPI::AppInfo::ESSENTIAL_INCLUDES)
82
98
  states = [
83
99
  Spaceship::ConnectAPI::AppInfo::AppStoreState::PREPARE_FOR_SUBMISSION,
@@ -95,6 +111,16 @@ module Spaceship
95
111
  end.first
96
112
  end
97
113
 
114
+ #
115
+ # Available Territories
116
+ #
117
+
118
+ def fetch_available_territories(filter: {}, includes: nil, limit: nil, sort: nil)
119
+ filter ||= {}
120
+ resps = Spaceship::ConnectAPI.get_available_territories(app_id: id, filter: filter, includes: includes, limit: limit, sort: sort).all_pages
121
+ return resps.flat_map(&:to_models)
122
+ end
123
+
98
124
  #
99
125
  # App Pricing
100
126
  #
@@ -152,6 +178,18 @@ module Spaceship
152
178
  end
153
179
  end
154
180
 
181
+ def get_latest_app_store_version(platform: nil, includes: nil)
182
+ platform ||= Spaceship::ConnectAPI::Platform::IOS
183
+ filter = {
184
+ platform: platform
185
+ }
186
+
187
+ # Get the latest version
188
+ return get_app_store_versions(filter: filter, includes: includes)
189
+ .sort_by { |v| Gem::Version.new(v.version_string) }
190
+ .last
191
+ end
192
+
155
193
  def get_live_app_store_version(platform: nil, includes: nil)
156
194
  platform ||= Spaceship::ConnectAPI::Platform::IOS
157
195
  filter = {
@@ -27,6 +27,7 @@ module Spaceship
27
27
  #
28
28
 
29
29
  def update(attributes: nil)
30
+ attributes = reverse_attr_mapping(attributes)
30
31
  Spaceship::ConnectAPI.patch_app_info_localization(app_info_localization_id: id, attributes: attributes)
31
32
  end
32
33
 
@@ -119,6 +119,7 @@ module Spaceship
119
119
  end
120
120
 
121
121
  def update(attributes: nil)
122
+ attributes = reverse_attr_mapping(attributes)
122
123
  Spaceship::ConnectAPI.patch_app_preview(app_preview_id: id, attributes: attributes).first
123
124
  end
124
125
 
@@ -1,5 +1,6 @@
1
1
  require_relative '../model'
2
2
  require_relative '../file_uploader'
3
+ require_relative './app_screenshot_set'
3
4
  require 'spaceship/globals'
4
5
 
5
6
  require 'digest/md5'
@@ -9,6 +10,7 @@ module Spaceship
9
10
  class AppScreenshot
10
11
  include Spaceship::ConnectAPI::Model
11
12
 
13
+ attr_accessor :file_size
12
14
  attr_accessor :file_name
13
15
  attr_accessor :source_file_checksum
14
16
  attr_accessor :image_asset
@@ -19,6 +21,7 @@ module Spaceship
19
21
  attr_accessor :uploaded
20
22
 
21
23
  attr_mapping({
24
+ "fileSize" => "file_size",
22
25
  "fileName" => "file_name",
23
26
  "sourceFileChecksum" => "source_file_checksum",
24
27
  "imageAsset" => "image_asset",
@@ -33,6 +36,10 @@ module Spaceship
33
36
  return "appScreenshots"
34
37
  end
35
38
 
39
+ def awaiting_upload?
40
+ (asset_delivery_state || {})["state"] == "AWAITING_UPLOAD"
41
+ end
42
+
36
43
  def complete?
37
44
  (asset_delivery_state || {})["state"] == "COMPLETE"
38
45
  end
@@ -84,11 +91,43 @@ module Spaceship
84
91
  fileName: filename
85
92
  }
86
93
 
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
94
+ # Create placeholder to upload screenshot
95
+ begin
96
+ screenshot = Spaceship::ConnectAPI.post_app_screenshot(
97
+ app_screenshot_set_id: app_screenshot_set_id,
98
+ attributes: post_attributes
99
+ ).first
100
+ rescue => error
101
+ # Sometimes creating a screenshot with the web session App Store Connect API
102
+ # will result in a false failure. The response will return a 503 but the database
103
+ # insert will eventually go through.
104
+ #
105
+ # When this is observed, we will poll until we find the matchin screenshot that
106
+ # is awaiting for upload and file size
107
+ #
108
+ # https://github.com/fastlane/fastlane/pull/16842
109
+ time = Time.now.to_i
110
+
111
+ timeout_minutes = (ENV["SPACESHIP_SCREENSHOT_UPLOAD_TIMEOUT"] || 20).to_i
112
+
113
+ loop do
114
+ puts("Waiting for screenshot to appear before uploading...")
115
+ sleep(30)
116
+
117
+ screenshots = Spaceship::ConnectAPI::AppScreenshotSet
118
+ .get(app_screenshot_set_id: app_screenshot_set_id)
119
+ .app_screenshots
120
+
121
+ screenshot = screenshots.find do |s|
122
+ s.awaiting_upload? && s.file_size == filesize
123
+ end
124
+
125
+ break if screenshot
126
+
127
+ time_diff = Time.now.to_i - time
128
+ raise error if time_diff >= (60 * timeout_minutes)
129
+ end
130
+ end
92
131
 
93
132
  # Upload the file
94
133
  upload_operations = screenshot.upload_operations
@@ -39,6 +39,7 @@ module Spaceship
39
39
  #
40
40
 
41
41
  def update(attributes: nil)
42
+ attributes = reverse_attr_mapping(attributes)
42
43
  return Spaceship::ConnectAPI.patch_app_store_review_detail(app_store_review_detail_id: id, attributes: attributes)
43
44
  end
44
45
 
@@ -85,6 +85,7 @@ module Spaceship
85
85
  end
86
86
 
87
87
  def update(attributes: nil)
88
+ attributes = reverse_attr_mapping(attributes)
88
89
  return Spaceship::ConnectAPI.patch_app_store_version(app_store_version_id: id, attributes: attributes).first
89
90
  end
90
91
 
@@ -155,6 +156,15 @@ module Spaceship
155
156
  return resp.to_models.first
156
157
  end
157
158
 
159
+ #
160
+ # App Store Version Release Requests
161
+ #
162
+
163
+ def create_app_store_version_release_request
164
+ resp = Spaceship::ConnectAPI.post_app_store_version_release_request(app_store_version_id: id)
165
+ return resp.to_models.first
166
+ end
167
+
158
168
  #
159
169
  # Build
160
170
  #