fastlane 2.217.0 → 2.219.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (169) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +102 -102
  3. data/deliver/lib/deliver/app_screenshot.rb +2 -2
  4. data/deliver/lib/deliver/app_screenshot_iterator.rb +2 -2
  5. data/deliver/lib/deliver/detect_values.rb +1 -1
  6. data/deliver/lib/deliver/languages.rb +1 -1
  7. data/deliver/lib/deliver/loader.rb +2 -2
  8. data/deliver/lib/deliver/options.rb +4 -4
  9. data/deliver/lib/deliver/runner.rb +1 -1
  10. data/deliver/lib/deliver/sync_screenshots.rb +2 -2
  11. data/deliver/lib/deliver/upload_metadata.rb +4 -4
  12. data/deliver/lib/deliver/upload_price_tier.rb +1 -1
  13. data/deliver/lib/deliver/upload_screenshots.rb +3 -3
  14. data/fastlane/lib/fastlane/action.rb +1 -1
  15. data/fastlane/lib/fastlane/actions/appledoc.rb +1 -1
  16. data/fastlane/lib/fastlane/actions/apteligent.rb +1 -1
  17. data/fastlane/lib/fastlane/actions/backup_xcarchive.rb +1 -1
  18. data/fastlane/lib/fastlane/actions/commit_github_file.rb +2 -2
  19. data/fastlane/lib/fastlane/actions/copy_artifacts.rb +1 -1
  20. data/fastlane/lib/fastlane/actions/create_app_online.rb +1 -1
  21. data/fastlane/lib/fastlane/actions/create_pull_request.rb +1 -1
  22. data/fastlane/lib/fastlane/actions/get_certificates.rb +1 -1
  23. data/fastlane/lib/fastlane/actions/get_github_release.rb +1 -1
  24. data/fastlane/lib/fastlane/actions/get_provisioning_profile.rb +1 -1
  25. data/fastlane/lib/fastlane/actions/github_api.rb +1 -1
  26. data/fastlane/lib/fastlane/actions/gradle.rb +1 -1
  27. data/fastlane/lib/fastlane/actions/install_on_device.rb +1 -1
  28. data/fastlane/lib/fastlane/actions/ipa.rb +1 -1
  29. data/fastlane/lib/fastlane/actions/jazzy.rb +1 -1
  30. data/fastlane/lib/fastlane/actions/oclint.rb +3 -3
  31. data/fastlane/lib/fastlane/actions/opt_out_crash_reporting.rb +2 -2
  32. data/fastlane/lib/fastlane/actions/restore_file.rb +1 -1
  33. data/fastlane/lib/fastlane/actions/set_github_release.rb +1 -1
  34. data/fastlane/lib/fastlane/actions/slather.rb +1 -1
  35. data/fastlane/lib/fastlane/actions/sonar.rb +12 -3
  36. data/fastlane/lib/fastlane/actions/splunkmint.rb +1 -1
  37. data/fastlane/lib/fastlane/actions/spm.rb +76 -2
  38. data/fastlane/lib/fastlane/actions/update_info_plist.rb +1 -1
  39. data/fastlane/lib/fastlane/actions/update_urban_airship_configuration.rb +1 -1
  40. data/fastlane/lib/fastlane/actions/upload_symbols_to_crashlytics.rb +1 -0
  41. data/fastlane/lib/fastlane/actions/upload_symbols_to_sentry.rb +1 -1
  42. data/fastlane/lib/fastlane/actions/upload_to_testflight.rb +2 -2
  43. data/fastlane/lib/fastlane/actions/verify_build.rb +7 -4
  44. data/fastlane/lib/fastlane/actions/xcov.rb +1 -1
  45. data/fastlane/lib/fastlane/cli_tools_distributor.rb +1 -1
  46. data/fastlane/lib/fastlane/command_line_handler.rb +2 -4
  47. data/fastlane/lib/fastlane/commands_generator.rb +2 -2
  48. data/fastlane/lib/fastlane/fast_file.rb +1 -1
  49. data/fastlane/lib/fastlane/helper/dotenv_helper.rb +1 -1
  50. data/fastlane/lib/fastlane/junit_generator.rb +1 -1
  51. data/fastlane/lib/fastlane/lane_manager.rb +1 -2
  52. data/fastlane/lib/fastlane/plugins/template/%gem_name%.gemspec.erb +0 -11
  53. data/fastlane/lib/fastlane/plugins/template/.rubocop.yml +5 -1
  54. data/fastlane/lib/fastlane/plugins/template/Gemfile.erb +27 -0
  55. data/fastlane/lib/fastlane/runner.rb +1 -1
  56. data/fastlane/lib/fastlane/setup/setup.rb +1 -1
  57. data/fastlane/lib/fastlane/swift_lane_manager.rb +2 -5
  58. data/fastlane/lib/fastlane/swift_runner_upgrader.rb +7 -4
  59. data/fastlane/lib/fastlane/version.rb +1 -1
  60. data/fastlane/swift/Actions.swift +1 -1
  61. data/fastlane/swift/Appfile.swift +1 -1
  62. data/fastlane/swift/ArgumentProcessor.swift +1 -1
  63. data/fastlane/swift/Atomic.swift +1 -1
  64. data/fastlane/swift/ControlCommand.swift +1 -1
  65. data/fastlane/swift/Deliverfile.swift +2 -2
  66. data/fastlane/swift/DeliverfileProtocol.swift +4 -4
  67. data/fastlane/swift/Fastlane.swift +79 -27
  68. data/fastlane/swift/Gymfile.swift +2 -2
  69. data/fastlane/swift/GymfileProtocol.swift +2 -2
  70. data/fastlane/swift/LaneFileProtocol.swift +5 -5
  71. data/fastlane/swift/MainProcess.swift +1 -1
  72. data/fastlane/swift/Matchfile.swift +2 -2
  73. data/fastlane/swift/MatchfileProtocol.swift +2 -2
  74. data/fastlane/swift/OptionalConfigValue.swift +1 -1
  75. data/fastlane/swift/Plugins.swift +1 -1
  76. data/fastlane/swift/Precheckfile.swift +2 -2
  77. data/fastlane/swift/PrecheckfileProtocol.swift +2 -2
  78. data/fastlane/swift/RubyCommand.swift +1 -1
  79. data/fastlane/swift/RubyCommandable.swift +1 -1
  80. data/fastlane/swift/Runner.swift +1 -1
  81. data/fastlane/swift/RunnerArgument.swift +1 -1
  82. data/fastlane/swift/Scanfile.swift +2 -2
  83. data/fastlane/swift/ScanfileProtocol.swift +2 -2
  84. data/fastlane/swift/Screengrabfile.swift +2 -2
  85. data/fastlane/swift/ScreengrabfileProtocol.swift +2 -2
  86. data/fastlane/swift/Snapshotfile.swift +2 -2
  87. data/fastlane/swift/SnapshotfileProtocol.swift +2 -2
  88. data/fastlane/swift/SocketClient.swift +1 -1
  89. data/fastlane/swift/SocketClientDelegateProtocol.swift +1 -1
  90. data/fastlane/swift/SocketResponse.swift +1 -1
  91. data/fastlane/swift/formatting/Brewfile.lock.json +26 -18
  92. data/fastlane/swift/main.swift +1 -1
  93. data/fastlane_core/lib/fastlane_core/build_watcher.rb +1 -1
  94. data/fastlane_core/lib/fastlane_core/cert_checker.rb +2 -2
  95. data/fastlane_core/lib/fastlane_core/configuration/configuration_file.rb +1 -1
  96. data/fastlane_core/lib/fastlane_core/device_manager.rb +17 -15
  97. data/fastlane_core/lib/fastlane_core/fastlane_pty.rb +34 -12
  98. data/fastlane_core/lib/fastlane_core/helper.rb +1 -1
  99. data/fastlane_core/lib/fastlane_core/itunes_transporter.rb +5 -2
  100. data/fastlane_core/lib/fastlane_core/project.rb +3 -2
  101. data/fastlane_core/lib/fastlane_core/queue_worker.rb +1 -1
  102. data/fastlane_core/lib/fastlane_core/string_filters.rb +6 -6
  103. data/fastlane_core/lib/fastlane_core/ui/fastlane_runner.rb +2 -2
  104. data/frameit/lib/frameit/editor.rb +4 -4
  105. data/frameit/lib/frameit/trim_box.rb +1 -1
  106. data/gym/lib/gym/error_handler.rb +1 -1
  107. data/gym/lib/gym/generators/package_command_generator_xcode7.rb +3 -3
  108. data/gym/lib/gym/runner.rb +1 -1
  109. data/gym/lib/gym/xcodebuild_fixes/README.md +1 -1
  110. data/match/lib/match/generator.rb +9 -1
  111. data/match/lib/match/module.rb +2 -1
  112. data/match/lib/match/portal_cache.rb +106 -0
  113. data/match/lib/match/portal_fetcher.rb +72 -0
  114. data/match/lib/match/profile_includes.rb +120 -0
  115. data/match/lib/match/runner.rb +79 -175
  116. data/match/lib/match/spaceship_ensure.rb +15 -11
  117. data/match/lib/match/storage/git_storage.rb +8 -3
  118. data/match/lib/match/storage/gitlab/client.rb +1 -1
  119. data/match/lib/match/storage/gitlab_secure_files.rb +1 -1
  120. data/match/lib/match/storage/interface.rb +1 -1
  121. data/match/lib/match/storage/s3_storage.rb +1 -1
  122. data/match/lib/match.rb +3 -0
  123. data/produce/lib/produce/itunes_connect.rb +1 -1
  124. data/scan/lib/scan/detect_values.rb +78 -20
  125. data/scan/lib/scan/options.rb +1 -1
  126. data/scan/lib/scan/runner.rb +1 -1
  127. data/screengrab/lib/screengrab/runner.rb +1 -1
  128. data/sigh/lib/assets/resign.sh +10 -10
  129. data/sigh/lib/sigh/commands_generator.rb +1 -1
  130. data/sigh/lib/sigh/module.rb +98 -0
  131. data/sigh/lib/sigh/options.rb +55 -1
  132. data/sigh/lib/sigh/resign.rb +1 -1
  133. data/sigh/lib/sigh/runner.rb +36 -112
  134. data/snapshot/lib/snapshot/setup.rb +2 -2
  135. data/snapshot/lib/snapshot/simulator_launchers/simulator_launcher.rb +23 -22
  136. data/snapshot/lib/snapshot/simulator_launchers/simulator_launcher_base.rb +2 -2
  137. data/spaceship/lib/spaceship/client.rb +1 -1
  138. data/spaceship/lib/spaceship/connect_api/api_client.rb +1 -1
  139. data/spaceship/lib/spaceship/connect_api/client.rb +4 -4
  140. data/spaceship/lib/spaceship/connect_api/models/app_preview_set.rb +2 -0
  141. data/spaceship/lib/spaceship/connect_api/models/app_screenshot.rb +2 -2
  142. data/spaceship/lib/spaceship/connect_api/models/bundle_id.rb +2 -2
  143. data/spaceship/lib/spaceship/connect_api/models/certificate.rb +2 -2
  144. data/spaceship/lib/spaceship/connect_api/models/device.rb +82 -3
  145. data/spaceship/lib/spaceship/connect_api/models/profile.rb +3 -2
  146. data/spaceship/lib/spaceship/connect_api/tunes/tunes.rb +3 -3
  147. data/spaceship/lib/spaceship/connect_api.rb +2 -0
  148. data/spaceship/lib/spaceship/portal/app.rb +1 -1
  149. data/spaceship/lib/spaceship/portal/app_group.rb +1 -1
  150. data/spaceship/lib/spaceship/test_flight/client.rb +1 -1
  151. data/spaceship/lib/spaceship/test_flight/tester.rb +1 -1
  152. data/spaceship/lib/spaceship/tunes/app_details.rb +2 -2
  153. data/spaceship/lib/spaceship/tunes/app_image.rb +1 -1
  154. data/spaceship/lib/spaceship/tunes/app_review_attachment.rb +1 -1
  155. data/spaceship/lib/spaceship/tunes/app_submission.rb +1 -1
  156. data/spaceship/lib/spaceship/tunes/app_version.rb +5 -5
  157. data/spaceship/lib/spaceship/tunes/build_details.rb +1 -1
  158. data/spaceship/lib/spaceship/tunes/iap.rb +3 -3
  159. data/spaceship/lib/spaceship/tunes/iap_detail.rb +2 -2
  160. data/spaceship/lib/spaceship/tunes/iap_families.rb +1 -1
  161. data/spaceship/lib/spaceship/tunes/iap_family_details.rb +2 -2
  162. data/spaceship/lib/spaceship/tunes/iap_family_list.rb +1 -1
  163. data/spaceship/lib/spaceship/tunes/tunes_client.rb +2 -2
  164. data/supply/lib/supply/client.rb +1 -1
  165. data/supply/lib/supply/setup.rb +1 -1
  166. data/trainer/lib/trainer/junit_generator.rb +1 -1
  167. data/trainer/lib/trainer/test_parser.rb +1 -1
  168. metadata +45 -288
  169. data/fastlane/lib/fastlane/plugins/template/Gemfile +0 -6
@@ -14,7 +14,7 @@ module Sigh
14
14
  # returns the path the newly created provisioning profile (in /tmp usually)
15
15
  def run
16
16
  FastlaneCore::PrintTable.print_values(config: Sigh.config,
17
- hide_keys: [:output_path],
17
+ hide_keys: [:output_path, :cached_certificates, :cached_devices, :cached_bundle_ids, :cached_profiles],
18
18
  title: "Summary for sigh #{Fastlane::VERSION}")
19
19
 
20
20
  if (api_token = Spaceship::ConnectAPI::Token.from(hash: Sigh.config[:api_key], filepath: Sigh.config[:api_key_path]))
@@ -48,7 +48,7 @@ module Sigh
48
48
  profile = create_profile!
49
49
  end
50
50
  else
51
- UI.user_error!("No matching provisioning profile found and can not create a new one because you enabled `readonly`") if Sigh.config[:readonly]
51
+ UI.user_error!("No matching provisioning profile found and cannot create a new one because you enabled `readonly`") if Sigh.config[:readonly]
52
52
  UI.important("No existing profiles found, that match the certificates you have installed locally! Creating a new provisioning profile for you")
53
53
  ensure_app_exists!
54
54
  profile = create_profile!
@@ -69,28 +69,7 @@ module Sigh
69
69
  def profile_type
70
70
  return @profile_type if @profile_type
71
71
 
72
- case Sigh.config[:platform]
73
- when "ios"
74
- @profile_type = Spaceship::ConnectAPI::Profile::ProfileType::IOS_APP_STORE
75
- @profile_type = Spaceship::ConnectAPI::Profile::ProfileType::IOS_APP_INHOUSE if Spaceship::ConnectAPI.client.in_house?
76
- @profile_type = Spaceship::ConnectAPI::Profile::ProfileType::IOS_APP_ADHOC if Sigh.config[:adhoc]
77
- @profile_type = Spaceship::ConnectAPI::Profile::ProfileType::IOS_APP_DEVELOPMENT if Sigh.config[:development]
78
- when "tvos"
79
- @profile_type = Spaceship::ConnectAPI::Profile::ProfileType::TVOS_APP_STORE
80
- @profile_type = Spaceship::ConnectAPI::Profile::ProfileType::TVOS_APP_INHOUSE if Spaceship::ConnectAPI.client.in_house?
81
- @profile_type = Spaceship::ConnectAPI::Profile::ProfileType::TVOS_APP_ADHOC if Sigh.config[:adhoc]
82
- @profile_type = Spaceship::ConnectAPI::Profile::ProfileType::TVOS_APP_DEVELOPMENT if Sigh.config[:development]
83
- when "macos"
84
- @profile_type = Spaceship::ConnectAPI::Profile::ProfileType::MAC_APP_STORE
85
- @profile_type = Spaceship::ConnectAPI::Profile::ProfileType::MAC_APP_INHOUSE if Spaceship::ConnectAPI.client.in_house?
86
- @profile_type = Spaceship::ConnectAPI::Profile::ProfileType::MAC_APP_DEVELOPMENT if Sigh.config[:development]
87
- @profile_type = Spaceship::ConnectAPI::Profile::ProfileType::MAC_APP_DIRECT if Sigh.config[:developer_id]
88
- when "catalyst"
89
- @profile_type = Spaceship::ConnectAPI::Profile::ProfileType::MAC_CATALYST_APP_STORE
90
- @profile_type = Spaceship::ConnectAPI::Profile::ProfileType::MAC_CATALYST_APP_INHOUSE if Spaceship::ConnectAPI.client.in_house?
91
- @profile_type = Spaceship::ConnectAPI::Profile::ProfileType::MAC_CATALYST_APP_DEVELOPMENT if Sigh.config[:development]
92
- @profile_type = Spaceship::ConnectAPI::Profile::ProfileType::MAC_CATALYST_APP_DIRECT if Sigh.config[:developer_id]
93
- end
72
+ @profile_type = Sigh.profile_type_for_config(platform: Sigh.config[:platform], in_house: Spaceship::ConnectAPI.client.in_house?, config: Sigh.config)
94
73
 
95
74
  @profile_type
96
75
  end
@@ -99,10 +78,20 @@ module Sigh
99
78
  def fetch_profiles
100
79
  UI.message("Fetching profiles...")
101
80
 
102
- # Filtering on 'profileType' seems to be undocumented as of 2020-07-30
103
- # but works on both web session and official API
104
- results = Spaceship::ConnectAPI::Profile.all(filter: { profileType: profile_type }, includes: "bundleId,certificates").select do |profile|
105
- profile.bundle_id.identifier == Sigh.config[:app_identifier]
81
+ filter = { profileType: profile_type }
82
+ # We can greatly speed up the search by filtering on the provisioning profile name
83
+ filter[:name] = Sigh.config[:provisioning_name] if Sigh.config[:provisioning_name].to_s.length > 0
84
+
85
+ includes = 'bundleId'
86
+
87
+ unless Sigh.config[:skip_certificate_verification] || Sigh.config[:include_all_certificates]
88
+ includes += ',certificates'
89
+ end
90
+
91
+ results = Sigh.config[:cached_profiles]
92
+ results ||= Spaceship::ConnectAPI::Profile.all(filter: filter, includes: includes)
93
+ results.select! do |profile|
94
+ profile.bundle_id&.identifier == Sigh.config[:app_identifier]
106
95
  end
107
96
 
108
97
  results = results.find_all do |current_profile|
@@ -166,7 +155,9 @@ module Sigh
166
155
  name = Sigh.config[:provisioning_name] || [app_identifier, profile_type_pretty_type].join(' ')
167
156
 
168
157
  unless Sigh.config[:skip_fetch_profiles]
169
- profile = Spaceship::ConnectAPI::Profile.all.find { |p| p.name == name }
158
+ # We can greatly speed up the search by filtering on the provisioning profile name
159
+ # It seems that there's no way to search for exact match using the API, so we'll need to run additional checks afterwards
160
+ profile = Spaceship::ConnectAPI::Profile.all(filter: { name: name }).find { |p| p.name == name }
170
161
  if profile
171
162
  UI.user_error!("The name '#{name}' is already taken, and fail_on_name_taken is true") if Sigh.config[:fail_on_name_taken]
172
163
  UI.error("The name '#{name}' is already taken, using another one.")
@@ -174,7 +165,9 @@ module Sigh
174
165
  end
175
166
  end
176
167
 
177
- bundle_id = Spaceship::ConnectAPI::BundleId.find(app_identifier)
168
+ bundle_ids = Sigh.config[:cached_bundle_ids]
169
+ bundle_id = bundle_ids.detect { |e| e.identifier == app_identifier } if bundle_ids
170
+ bundle_id ||= Spaceship::ConnectAPI::BundleId.find(app_identifier)
178
171
  unless bundle_id
179
172
  UI.user_error!("Could not find App with App Identifier '#{Sigh.config[:app_identifier]}'")
180
173
  end
@@ -207,67 +200,15 @@ module Sigh
207
200
  filter = {
208
201
  certificateType: certificate_types.join(',')
209
202
  }
210
- return Spaceship::ConnectAPI::Certificate.all(filter: filter)
203
+
204
+ certificates = Sigh.config[:cached_certificates]
205
+ certificates ||= Spaceship::ConnectAPI::Certificate.all(filter: filter)
206
+
207
+ return certificates
211
208
  end
212
209
 
213
210
  def certificates_for_profile_and_platform
214
- types = []
215
-
216
- case Sigh.config[:platform].to_s
217
- when 'ios', 'tvos'
218
- if profile_type == Spaceship::ConnectAPI::Profile::ProfileType::IOS_APP_DEVELOPMENT || profile_type == Spaceship::ConnectAPI::Profile::ProfileType::TVOS_APP_DEVELOPMENT
219
- types = [
220
- Spaceship::ConnectAPI::Certificate::CertificateType::DEVELOPMENT,
221
- Spaceship::ConnectAPI::Certificate::CertificateType::IOS_DEVELOPMENT
222
- ]
223
- elsif profile_type == Spaceship::ConnectAPI::Profile::ProfileType::IOS_APP_INHOUSE || profile_type == Spaceship::ConnectAPI::Profile::ProfileType::TVOS_APP_INHOUSE
224
- # Enterprise accounts don't have access to Apple Distribution certificates
225
- types = [
226
- Spaceship::ConnectAPI::Certificate::CertificateType::IOS_DISTRIBUTION
227
- ]
228
- # handles case where the desired certificate type is adhoc but the account is an enterprise account
229
- # the apple dev portal api has a weird quirk in it where if you query for distribution certificates
230
- # for enterprise accounts, you get nothing back even if they exist.
231
- elsif (profile_type == Spaceship::ConnectAPI::Profile::ProfileType::IOS_APP_ADHOC || profile_type == Spaceship::ConnectAPI::Profile::ProfileType::TVOS_APP_ADHOC) && Spaceship::ConnectAPI.client && Spaceship::ConnectAPI.client.in_house?
232
- # Enterprise accounts don't have access to Apple Distribution certificates
233
- types = [
234
- Spaceship::ConnectAPI::Certificate::CertificateType::IOS_DISTRIBUTION
235
- ]
236
- else
237
- types = [
238
- Spaceship::ConnectAPI::Certificate::CertificateType::DISTRIBUTION,
239
- Spaceship::ConnectAPI::Certificate::CertificateType::IOS_DISTRIBUTION
240
- ]
241
- end
242
-
243
- when 'macos', 'catalyst'
244
- if profile_type == Spaceship::ConnectAPI::Profile::ProfileType::MAC_APP_DEVELOPMENT || profile_type == Spaceship::ConnectAPI::Profile::ProfileType::MAC_CATALYST_APP_DEVELOPMENT
245
- types = [
246
- Spaceship::ConnectAPI::Certificate::CertificateType::DEVELOPMENT,
247
- Spaceship::ConnectAPI::Certificate::CertificateType::MAC_APP_DEVELOPMENT
248
- ]
249
- elsif profile_type == Spaceship::ConnectAPI::Profile::ProfileType::MAC_APP_STORE || profile_type == Spaceship::ConnectAPI::Profile::ProfileType::MAC_CATALYST_APP_STORE
250
- types = [
251
- Spaceship::ConnectAPI::Certificate::CertificateType::DISTRIBUTION,
252
- Spaceship::ConnectAPI::Certificate::CertificateType::MAC_APP_DISTRIBUTION
253
- ]
254
- elsif profile_type == Spaceship::ConnectAPI::Profile::ProfileType::MAC_APP_DIRECT || profile_type == Spaceship::ConnectAPI::Profile::ProfileType::MAC_CATALYST_APP_DIRECT
255
- types = [
256
- Spaceship::ConnectAPI::Certificate::CertificateType::DEVELOPER_ID_APPLICATION,
257
- Spaceship::ConnectAPI::Certificate::CertificateType::DEVELOPER_ID_APPLICATION_G2
258
- ]
259
- elsif profile_type == Spaceship::ConnectAPI::Profile::ProfileType::MAC_APP_INHOUSE || profile_type == Spaceship::ConnectAPI::Profile::ProfileType::MAC_CATALYST_APP_INHOUSE
260
- # Enterprise accounts don't have access to Apple Distribution certificates
261
- types = [
262
- Spaceship::ConnectAPI::Certificate::CertificateType::MAC_APP_DISTRIBUTION
263
- ]
264
- else
265
- types = [
266
- Spaceship::ConnectAPI::Certificate::CertificateType::DISTRIBUTION,
267
- Spaceship::ConnectAPI::Certificate::CertificateType::MAC_APP_DISTRIBUTION
268
- ]
269
- end
270
- end
211
+ types = Sigh.certificate_types_for_profile_and_platform(platform: Sigh.config[:platform], profile_type: profile_type)
271
212
 
272
213
  fetch_certificates(types)
273
214
  end
@@ -276,30 +217,13 @@ module Sigh
276
217
  # Only use devices if development or adhoc
277
218
  return [] if !Sigh.config[:development] && !Sigh.config[:adhoc]
278
219
 
279
- device_classes = case Sigh.config[:platform].to_s
280
- when 'ios'
281
- [
282
- Spaceship::ConnectAPI::Device::DeviceClass::APPLE_WATCH,
283
- Spaceship::ConnectAPI::Device::DeviceClass::IPAD,
284
- Spaceship::ConnectAPI::Device::DeviceClass::IPHONE,
285
- Spaceship::ConnectAPI::Device::DeviceClass::IPOD
286
- ]
287
- when 'tvos'
288
- [Spaceship::ConnectAPI::Device::DeviceClass::APPLE_TV]
289
- when 'macos', 'catalyst'
290
- [Spaceship::ConnectAPI::Device::DeviceClass::MAC]
291
- end
292
- if Sigh.config[:platform].to_s == 'ios' && Sigh.config[:include_mac_in_profiles]
293
- device_classes += [Spaceship::ConnectAPI::Device::DeviceClass::APPLE_SILICON_MAC]
294
- end
295
- if Spaceship::ConnectAPI.token
296
- return Spaceship::ConnectAPI::Device.all.select do |device|
297
- device_classes.include?(device.device_class)
298
- end
299
- else
300
- filter = { deviceClass: device_classes.join(",") }
301
- return Spaceship::ConnectAPI::Device.all(filter: filter)
302
- end
220
+ devices = Sigh.config[:cached_devices]
221
+ devices ||= Spaceship::ConnectAPI::Device.devices_for_platform(
222
+ platform: Sigh.config[:platform],
223
+ include_mac_in_profiles: Sigh.config[:include_mac_in_profiles]
224
+ )
225
+
226
+ return devices
303
227
  end
304
228
 
305
229
  # Certificate to use based on the current distribution mode
@@ -19,7 +19,7 @@ module Snapshot
19
19
 
20
20
  if File.exist?(snapfile_path)
21
21
  if print_instructions_on_failure
22
- print_instructions(snapshot_helper_filename: snapshot_helper_filename, snapfile_path: snapfile_path)
22
+ print_instructions(snapshot_helper_filename: snapshot_helper_filename)
23
23
  return
24
24
  else
25
25
  UI.user_error!("Snapfile already exists at path '#{snapfile_path}'. Run 'fastlane snapshot' to generate screenshots.")
@@ -37,7 +37,7 @@ module Snapshot
37
37
  print_instructions(snapshot_helper_filename: snapshot_helper_filename, snapfile_path: snapfile_path)
38
38
  end
39
39
 
40
- def self.print_instructions(snapshot_helper_filename: nil, snapfile_path: nil)
40
+ def self.print_instructions(snapshot_helper_filename: nil)
41
41
  puts("Open your Xcode project and make sure to do the following:".yellow)
42
42
  puts("1) Add a new UI Test target to your project".yellow)
43
43
  puts("2) Add the ./fastlane/#{snapshot_helper_filename} to your UI Test target".yellow)
@@ -109,33 +109,34 @@ module Snapshot
109
109
  end
110
110
  }
111
111
  ]
112
+ error_proc = proc do |output, return_code|
113
+ self.collected_errors.concat(failed_devices.map do |device, messages|
114
+ "#{device}: #{messages.join(', ')}"
115
+ end)
116
+
117
+ cleanup_after_failure(devices, language, locale, launch_args, return_code)
118
+
119
+ # no exception raised... that means we need to retry
120
+ UI.error("Caught error... #{return_code}")
121
+
122
+ self.current_number_of_retries_due_to_failing_simulator += 1
123
+ if self.current_number_of_retries_due_to_failing_simulator < 20 && return_code != 65
124
+ # If the return code is not 65, we should assume its a simulator failure and retry
125
+ launch_simultaneously(devices, language, locale, launch_args)
126
+ elsif retries < launcher_config.number_of_retries
127
+ # If there are retries remaining, run the tests again
128
+ retry_tests(retries, command, language, locale, launch_args, devices)
129
+ else
130
+ # It's important to raise an error, as we don't want to collect the screenshots
131
+ UI.crash!("Too many errors... no more retries...") if launcher_config.stop_after_first_error
132
+ end
133
+ end
112
134
  FastlaneCore::CommandExecutor.execute(command: command,
113
135
  print_all: true,
114
136
  print_command: true,
115
137
  prefix: prefix_hash,
116
138
  loading: "Loading...",
117
- error: proc do |output, return_code|
118
- self.collected_errors.concat(failed_devices.map do |device, messages|
119
- "#{device}: #{messages.join(', ')}"
120
- end)
121
-
122
- cleanup_after_failure(devices, language, locale, launch_args, return_code)
123
-
124
- # no exception raised... that means we need to retry
125
- UI.error("Caught error... #{return_code}")
126
-
127
- self.current_number_of_retries_due_to_failing_simulator += 1
128
- if self.current_number_of_retries_due_to_failing_simulator < 20 && return_code != 65
129
- # If the return code is not 65, we should assume its a simulator failure and retry
130
- launch_simultaneously(devices, language, locale, launch_args)
131
- elsif retries < launcher_config.number_of_retries
132
- # If there are retries remaining, run the tests again
133
- retry_tests(retries, command, language, locale, launch_args, devices)
134
- else
135
- # It's important to raise an error, as we don't want to collect the screenshots
136
- UI.crash!("Too many errors... no more retries...") if launcher_config.stop_after_first_error
137
- end
138
- end)
139
+ error: error_proc)
139
140
  end
140
141
 
141
142
  def cleanup_after_failure(devices, language, locale, launch_args, return_code)
@@ -107,7 +107,7 @@ module Snapshot
107
107
  output = Helper.backticks("xcrun simctl addmedia #{device_udid} #{path.shellescape} &> /dev/null")
108
108
 
109
109
  # Run legacy addphoto and addvideo if addmedia isn't found
110
- # Output will be empty strin gif it was a success
110
+ # Output will be empty string if it was a success
111
111
  # Output will contain "usage: simctl" if command not found
112
112
  if output.include?('usage: simctl')
113
113
  Helper.backticks("xcrun simctl add#{media_type} #{device_udid} #{path.shellescape} &> /dev/null")
@@ -124,7 +124,7 @@ module Snapshot
124
124
  Helper.backticks("xcrun simctl bootstatus #{device_udid} -b &> /dev/null")
125
125
 
126
126
  # "Booted" status is not enough for to adjust the status bar
127
- # Simulator could stil be booting with Apple logo
127
+ # Simulator could still be booting with Apple logo
128
128
  # Need to wait "some amount of time" until home screen shows
129
129
  boot_sleep = ENV["SNAPSHOT_SIMULATOR_WAIT_FOR_BOOT_TIMEOUT"].to_i || 10
130
130
  UI.message("Waiting #{boot_sleep} seconds for device to fully boot before overriding status bar... Set 'SNAPSHOT_SIMULATOR_WAIT_FOR_BOOT_TIMEOUT' environment variable to adjust timeout")
@@ -429,7 +429,7 @@ module Spaceship
429
429
  # which is common, as the session automatically invalidates after x hours (we don't know x)
430
430
  # In this case we don't actually care about the exact exception, and why it was failing
431
431
  # because either way, we'll have to do a fresh login, where we do the actual error handling
432
- puts("Available session is not valid any more. Continuing with normal login.")
432
+ puts("Available session is not valid anymore. Continuing with normal login.")
433
433
  end
434
434
  end
435
435
  #
@@ -65,7 +65,7 @@ module Spaceship
65
65
  end
66
66
 
67
67
  # Instance level hostname only used when creating
68
- # App Store Connect API Farady client.
68
+ # App Store Connect API Faraday client.
69
69
  # Forwarding to class level if using web session.
70
70
  def hostname
71
71
  if @token
@@ -84,13 +84,13 @@ module Spaceship
84
84
  # Extending this instance to add API endpoints from these modules
85
85
  # Each of these modules adds a new setter method for an instance
86
86
  # of an ConnectAPI::APIClient
87
- # These get set in set_indvidual_clients
87
+ # These get set in set_individual_clients
88
88
  self.extend(Spaceship::ConnectAPI::TestFlight::API)
89
89
  self.extend(Spaceship::ConnectAPI::Tunes::API)
90
90
  self.extend(Spaceship::ConnectAPI::Provisioning::API)
91
91
  self.extend(Spaceship::ConnectAPI::Users::API)
92
92
 
93
- set_indvidual_clients(
93
+ set_individual_clients(
94
94
  cookie: cookie,
95
95
  current_team_id: current_team_id,
96
96
  token: token,
@@ -155,7 +155,7 @@ module Spaceship
155
155
 
156
156
  # Updating the tunes and portal clients requires resetting
157
157
  # of the clients in the API modules
158
- set_indvidual_clients(
158
+ set_individual_clients(
159
159
  cookie: nil,
160
160
  current_team_id: nil,
161
161
  token: nil,
@@ -166,7 +166,7 @@ module Spaceship
166
166
 
167
167
  private
168
168
 
169
- def set_indvidual_clients(cookie: nil, current_team_id: nil, token: nil, tunes_client: nil, portal_client: nil)
169
+ def set_individual_clients(cookie: nil, current_team_id: nil, token: nil, tunes_client: nil, portal_client: nil)
170
170
  # This was added by Spaceship::ConnectAPI::TestFlight::API and is required
171
171
  # to be set for API methods to have a client to send request on
172
172
  if cookie || token || tunes_client
@@ -17,6 +17,7 @@ module Spaceship
17
17
  IPHONE_55 = "IPHONE_55"
18
18
  IPHONE_58 = "IPHONE_58"
19
19
  IPHONE_65 = "IPHONE_65"
20
+ IPHONE_67 = "IPHONE_67"
20
21
 
21
22
  IPAD_97 = "IPAD_97"
22
23
  IPAD_105 = "IPAD_105"
@@ -33,6 +34,7 @@ module Spaceship
33
34
  IPHONE_55,
34
35
  IPHONE_58,
35
36
  IPHONE_65,
37
+ IPHONE_67,
36
38
 
37
39
  IPAD_97,
38
40
  IPAD_105,
@@ -103,7 +103,7 @@ module Spaceship
103
103
  # will result in a false failure. The response will return a 503 but the database
104
104
  # insert will eventually go through.
105
105
  #
106
- # When this is observed, we will poll until we find the matchin screenshot that
106
+ # When this is observed, we will poll until we find the matching screenshot that
107
107
  # is awaiting for upload and file size
108
108
  #
109
109
  # https://github.com/fastlane/fastlane/pull/16842
@@ -143,7 +143,7 @@ module Spaceship
143
143
  }
144
144
 
145
145
  # Patch screenshot that file upload is complete
146
- # Catch error if patch retries due to 504. Origal patch
146
+ # Catch error if patch retries due to 504. Original patch
147
147
  # may go through by return response as 504.
148
148
  begin
149
149
  screenshot = Spaceship::ConnectAPI.patch_app_screenshot(
@@ -1,4 +1,4 @@
1
- require_relative '../model'
1
+ require_relative '../../connect_api'
2
2
  require_relative './bundle_id_capability'
3
3
  module Spaceship
4
4
  class ConnectAPI
@@ -39,7 +39,7 @@ module Spaceship
39
39
  # API
40
40
  #
41
41
 
42
- def self.all(client: nil, filter: {}, includes: nil, fields: nil, limit: nil, sort: nil)
42
+ def self.all(client: nil, filter: {}, includes: nil, fields: nil, limit: Spaceship::ConnectAPI::MAX_OBJECTS_PER_PAGE_LIMIT, sort: nil)
43
43
  client ||= Spaceship::ConnectAPI
44
44
  resps = client.get_bundle_ids(filter: filter, includes: includes, fields: fields, limit: nil, sort: nil).all_pages
45
45
  return resps.flat_map(&:to_models)
@@ -1,4 +1,4 @@
1
- require_relative '../model'
1
+ require_relative '../../connect_api'
2
2
 
3
3
  require 'openssl'
4
4
 
@@ -79,7 +79,7 @@ module Spaceship
79
79
  # API
80
80
  #
81
81
 
82
- def self.all(client: nil, filter: {}, includes: nil, fields: nil, limit: nil, sort: nil)
82
+ def self.all(client: nil, filter: {}, includes: nil, fields: nil, limit: Spaceship::ConnectAPI::MAX_OBJECTS_PER_PAGE_LIMIT, sort: nil)
83
83
  client ||= Spaceship::ConnectAPI
84
84
  resps = client.get_certificates(filter: filter, includes: includes, fields: fields, limit: limit, sort: sort).all_pages
85
85
  return resps.flat_map(&:to_models)
@@ -1,4 +1,5 @@
1
- require_relative '../model'
1
+ require_relative '../../connect_api'
2
+
2
3
  module Spaceship
3
4
  class ConnectAPI
4
5
  class Device
@@ -50,13 +51,91 @@ module Spaceship
50
51
  #
51
52
  # API
52
53
  #
53
-
54
- def self.all(client: nil, filter: {}, includes: nil, fields: nil, limit: nil, sort: nil)
54
+ def self.all(client: nil, filter: {}, includes: nil, fields: nil, limit: Spaceship::ConnectAPI::MAX_OBJECTS_PER_PAGE_LIMIT, sort: nil)
55
55
  client ||= Spaceship::ConnectAPI
56
56
  resps = client.get_devices(filter: filter, includes: includes, fields: fields, limit: limit, sort: sort).all_pages
57
57
  return resps.flat_map(&:to_models)
58
58
  end
59
59
 
60
+ # @param platform [String] The provisioning profile's platform (i.e. ios, tvos, macos, catalyst).
61
+ # @param include_mac_in_profiles [Bool] Whether to include macs in iOS provisioning profiles. false by default.
62
+ # @param client [ConnectAPI] ConnectAPI client.
63
+ # @return (Device) List of enabled devices.
64
+ def self.devices_for_platform(platform: nil, include_mac_in_profiles: false, client: nil)
65
+ platform = platform.to_sym
66
+ include_mac_in_profiles &&= platform == :ios
67
+
68
+ device_platform = case platform
69
+ when :osx, :macos, :mac
70
+ Spaceship::ConnectAPI::Platform::MAC_OS
71
+ when :ios
72
+ Spaceship::ConnectAPI::Platform::IOS
73
+ when :catalyst
74
+ Spaceship::ConnectAPI::Platform::MAC_OS
75
+ end
76
+
77
+ device_platforms = [
78
+ device_platform,
79
+ 'UNIVERSAL' # Universal Bundle ID platform is undocumented as of Oct 4, 2023.
80
+ ]
81
+
82
+ device_classes =
83
+ case platform
84
+ when :ios
85
+ [
86
+ Spaceship::ConnectAPI::Device::DeviceClass::IPAD,
87
+ Spaceship::ConnectAPI::Device::DeviceClass::IPHONE,
88
+ Spaceship::ConnectAPI::Device::DeviceClass::IPOD,
89
+ Spaceship::ConnectAPI::Device::DeviceClass::APPLE_WATCH
90
+ ]
91
+ when :tvos
92
+ [
93
+ Spaceship::ConnectAPI::Device::DeviceClass::APPLE_TV
94
+ ]
95
+ when :macos, :catalyst
96
+ [
97
+ Spaceship::ConnectAPI::Device::DeviceClass::MAC
98
+ ]
99
+ else
100
+ []
101
+ end
102
+
103
+ if include_mac_in_profiles
104
+ device_classes << Spaceship::ConnectAPI::Device::DeviceClass::APPLE_SILICON_MAC
105
+ device_platforms << Spaceship::ConnectAPI::Platform::MAC_OS
106
+ end
107
+
108
+ filter = {
109
+ status: Spaceship::ConnectAPI::Device::Status::ENABLED,
110
+ platform: device_platforms.uniq.join(',')
111
+ }
112
+
113
+ devices = Spaceship::ConnectAPI::Device.all(
114
+ client: client,
115
+ filter: filter
116
+ )
117
+
118
+ unless device_classes.empty?
119
+ devices.select! do |device|
120
+ # App Store Connect API return MAC in device_class instead of APPLE_SILICON_MAC for Silicon Macs.
121
+ # The difference between old MAC and APPLE_SILICON_MAC is provisioning uuid.
122
+ # Intel-based provisioning UUID: 01234567-89AB-CDEF-0123-456789ABCDEF.
123
+ # arm64-based provisioning UUID: 01234567-89ABCDEF12345678.
124
+ # Workaround is to include macs having:
125
+ # * 25 chars length and only one hyphen in provisioning UUID.
126
+ if include_mac_in_profiles &&
127
+ device.device_class == Spaceship::ConnectAPI::Device::DeviceClass::MAC
128
+
129
+ next device.udid.length == 25 && device.udid.count('-') == 1
130
+ end
131
+
132
+ device_classes.include?(device.device_class)
133
+ end
134
+ end
135
+
136
+ devices
137
+ end
138
+
60
139
  # @param client [ConnectAPI] ConnectAPI client.
61
140
  # @param platform [String] The platform of the device.
62
141
  # @param include_disabled [Bool] Whether to include disable devices. false by default.
@@ -1,4 +1,5 @@
1
- require_relative '../model'
1
+ require_relative '../../connect_api'
2
+
2
3
  module Spaceship
3
4
  class ConnectAPI
4
5
  class Profile
@@ -70,7 +71,7 @@ module Spaceship
70
71
  # API
71
72
  #
72
73
 
73
- def self.all(client: nil, filter: {}, includes: nil, fields: nil, limit: nil, sort: nil)
74
+ def self.all(client: nil, filter: {}, includes: nil, fields: nil, limit: Spaceship::ConnectAPI::MAX_OBJECTS_PER_PAGE_LIMIT, sort: nil)
74
75
  client ||= Spaceship::ConnectAPI
75
76
  resps = client.get_profiles(filter: filter, includes: includes, fields: fields, limit: limit, sort: sort).all_pages
76
77
  return resps.flat_map(&:to_models)
@@ -94,7 +94,7 @@ module Spaceship
94
94
  }
95
95
  end
96
96
 
97
- app_store_verions_data = platforms.map do |platform|
97
+ data_for_app_store_versions = platforms.map do |platform|
98
98
  {
99
99
  type: "appStoreVersions",
100
100
  id: "${store-version-#{platform}}"
@@ -103,7 +103,7 @@ module Spaceship
103
103
 
104
104
  relationships = {
105
105
  appStoreVersions: {
106
- data: app_store_verions_data
106
+ data: data_for_app_store_versions
107
107
  },
108
108
  appInfos: {
109
109
  data: [
@@ -1254,7 +1254,7 @@ module Spaceship
1254
1254
  # resolutionCenter
1255
1255
  #
1256
1256
  # As of 2022-11-11:
1257
- # This is not official available throught the App Store Connect API using an API Key.
1257
+ # This is not official available through the App Store Connect API using an API Key.
1258
1258
  # This is only works with Apple ID auth.
1259
1259
  #
1260
1260
 
@@ -76,6 +76,8 @@ require 'spaceship/connect_api/models/actor'
76
76
 
77
77
  module Spaceship
78
78
  class ConnectAPI
79
+ MAX_OBJECTS_PER_PAGE_LIMIT = 200
80
+
79
81
  # Defined in the App Store Connect API docs:
80
82
  # https://developer.apple.com/documentation/appstoreconnectapi/platform
81
83
  #
@@ -141,7 +141,7 @@ module Spaceship
141
141
 
142
142
  # Delete this App ID. This action will most likely fail if the App ID is already in the store
143
143
  # or there are active profiles
144
- # @return (App) The app you just deletd
144
+ # @return (App) The app you just deleted
145
145
  def delete!
146
146
  client.delete_app!(app_id, mac: mac?)
147
147
  self
@@ -63,7 +63,7 @@ module Spaceship
63
63
  end
64
64
 
65
65
  # Delete this app group
66
- # @return (AppGroup) The app group you just deletd
66
+ # @return (AppGroup) The app group you just deleted
67
67
  def delete!
68
68
  client.delete_app_group!(app_group_id)
69
69
  self
@@ -8,7 +8,7 @@ module Spaceship
8
8
  #
9
9
  # This client is solely responsible for the making HTTP requests and
10
10
  # parsing their responses. Parameters should be either named parameters, or
11
- # for large request data bodies, pass in anything that can resond to
11
+ # for large request data bodies, pass in anything that can respond to
12
12
  # `to_json`.
13
13
  #
14
14
  # Each request method should validate the required parameters. A required parameter is one that would result in 400-range response if it is not supplied.
@@ -94,7 +94,7 @@ module Spaceship
94
94
 
95
95
  # @return (Spaceship::TestFlight::Tester) Returns the testers matching the parameter.
96
96
  # ITC searches all fields, and is full text. The search results are the union of all words in the search text
97
- # @param text (String) (required): Value used to filter the tester, case insensitive
97
+ # @param text (String) (required): Value used to filter the tester, case-insensitive
98
98
  def self.search(app_id: nil, text: nil, is_email_exact_match: false)
99
99
  text = text.strip
100
100
  testers_matching_text = client.search_for_tester_in_app(app_id: app_id, text: text).map { |data| self.new(data) }
@@ -11,7 +11,7 @@ module Spaceship
11
11
  # Localized values
12
12
  ####
13
13
 
14
- # @return (Array) Raw access the all available languages. You shouldn't use it probbaly
14
+ # @return (Array) Raw access the all available languages. You shouldn't use it probably
15
15
  attr_accessor :languages
16
16
 
17
17
  # @return (Hash) A hash representing the app name in all languages
@@ -23,7 +23,7 @@ module Spaceship
23
23
  # @return (Hash) A hash representing the privacy URL in all languages
24
24
  attr_reader :privacy_url
25
25
 
26
- # @return (Hash) A hash prepresenting the privacy URL in all languages for Apple TV
26
+ # @return (Hash) A hash representing the privacy URL in all languages for Apple TV
27
27
  attr_reader :apple_tv_privacy_policy
28
28
 
29
29
  # Categories (e.g. MZGenre.Business)
@@ -35,7 +35,7 @@ module Spaceship
35
35
  end
36
36
 
37
37
  def setup
38
- # Since September 2015 we don't get the url any more, so we have to manually build it
38
+ # Since September 2015 we don't get the url anymore, so we have to manually build it
39
39
  self.url = "#{HOST_URL}/#{self.asset_token}/0x0ss.jpg"
40
40
  end
41
41