fastlane 2.212.1 → 2.219.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (227) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +100 -100
  3. data/deliver/lib/deliver/app_screenshot.rb +22 -12
  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 +10 -9
  10. data/deliver/lib/deliver/submit_for_review.rb +13 -0
  11. data/deliver/lib/deliver/sync_screenshots.rb +2 -2
  12. data/deliver/lib/deliver/upload_metadata.rb +60 -15
  13. data/deliver/lib/deliver/upload_price_tier.rb +2 -2
  14. data/deliver/lib/deliver/upload_screenshots.rb +3 -3
  15. data/fastlane/lib/assets/custom_action_template.rb +18 -12
  16. data/fastlane/lib/fastlane/action.rb +1 -1
  17. data/fastlane/lib/fastlane/actions/appledoc.rb +1 -1
  18. data/fastlane/lib/fastlane/actions/apteligent.rb +1 -1
  19. data/fastlane/lib/fastlane/actions/backup_xcarchive.rb +1 -1
  20. data/fastlane/lib/fastlane/actions/commit_github_file.rb +2 -2
  21. data/fastlane/lib/fastlane/actions/copy_artifacts.rb +1 -1
  22. data/fastlane/lib/fastlane/actions/create_app_online.rb +1 -1
  23. data/fastlane/lib/fastlane/actions/create_pull_request.rb +1 -1
  24. data/fastlane/lib/fastlane/actions/docs/build_app.md +2 -2
  25. data/fastlane/lib/fastlane/actions/docs/capture_android_screenshots.md +8 -8
  26. data/fastlane/lib/fastlane/actions/docs/check_app_store_metadata.md +3 -3
  27. data/fastlane/lib/fastlane/actions/docs/get_push_certificate.md +2 -2
  28. data/fastlane/lib/fastlane/actions/docs/sync_code_signing.md +6 -4
  29. data/fastlane/lib/fastlane/actions/docs/upload_to_app_store.md.erb +1 -1
  30. data/fastlane/lib/fastlane/actions/docs/upload_to_play_store.md +6 -2
  31. data/fastlane/lib/fastlane/actions/docs/upload_to_testflight.md +1 -1
  32. data/fastlane/lib/fastlane/actions/download_universal_apk_from_google_play.rb +124 -0
  33. data/fastlane/lib/fastlane/actions/ensure_git_status_clean.rb +44 -5
  34. data/fastlane/lib/fastlane/actions/ensure_xcode_version.rb +4 -0
  35. data/fastlane/lib/fastlane/actions/get_certificates.rb +1 -1
  36. data/fastlane/lib/fastlane/actions/get_github_release.rb +1 -1
  37. data/fastlane/lib/fastlane/actions/get_provisioning_profile.rb +1 -1
  38. data/fastlane/lib/fastlane/actions/git_branch.rb +1 -1
  39. data/fastlane/lib/fastlane/actions/github_api.rb +1 -1
  40. data/fastlane/lib/fastlane/actions/gradle.rb +1 -1
  41. data/fastlane/lib/fastlane/actions/install_on_device.rb +2 -2
  42. data/fastlane/lib/fastlane/actions/ipa.rb +1 -1
  43. data/fastlane/lib/fastlane/actions/jazzy.rb +1 -1
  44. data/fastlane/lib/fastlane/actions/nexus_upload.rb +1 -0
  45. data/fastlane/lib/fastlane/actions/notarize.rb +17 -2
  46. data/fastlane/lib/fastlane/actions/oclint.rb +3 -3
  47. data/fastlane/lib/fastlane/actions/opt_out_crash_reporting.rb +2 -2
  48. data/fastlane/lib/fastlane/actions/restore_file.rb +1 -1
  49. data/fastlane/lib/fastlane/actions/set_github_release.rb +1 -1
  50. data/fastlane/lib/fastlane/actions/slather.rb +18 -5
  51. data/fastlane/lib/fastlane/actions/sonar.rb +12 -3
  52. data/fastlane/lib/fastlane/actions/splunkmint.rb +1 -1
  53. data/fastlane/lib/fastlane/actions/spm.rb +76 -2
  54. data/fastlane/lib/fastlane/actions/update_info_plist.rb +1 -1
  55. data/fastlane/lib/fastlane/actions/update_urban_airship_configuration.rb +1 -1
  56. data/fastlane/lib/fastlane/actions/upload_symbols_to_crashlytics.rb +1 -0
  57. data/fastlane/lib/fastlane/actions/upload_symbols_to_sentry.rb +1 -1
  58. data/fastlane/lib/fastlane/actions/upload_to_testflight.rb +2 -2
  59. data/fastlane/lib/fastlane/actions/verify_build.rb +7 -4
  60. data/fastlane/lib/fastlane/actions/xcov.rb +1 -1
  61. data/fastlane/lib/fastlane/cli_tools_distributor.rb +1 -1
  62. data/fastlane/lib/fastlane/command_line_handler.rb +2 -4
  63. data/fastlane/lib/fastlane/commands_generator.rb +2 -2
  64. data/fastlane/lib/fastlane/fast_file.rb +1 -1
  65. data/fastlane/lib/fastlane/helper/dotenv_helper.rb +1 -1
  66. data/fastlane/lib/fastlane/helper/git_helper.rb +3 -0
  67. data/fastlane/lib/fastlane/helper/xcodes_helper.rb +0 -3
  68. data/fastlane/lib/fastlane/junit_generator.rb +1 -1
  69. data/fastlane/lib/fastlane/lane.rb +9 -1
  70. data/fastlane/lib/fastlane/lane_manager.rb +1 -2
  71. data/fastlane/lib/fastlane/new_action.rb +1 -1
  72. data/fastlane/lib/fastlane/plugins/plugin_info_collector.rb +3 -3
  73. data/fastlane/lib/fastlane/plugins/template/%gem_name%.gemspec.erb +1 -13
  74. data/fastlane/lib/fastlane/plugins/template/.rubocop.yml +9 -1
  75. data/fastlane/lib/fastlane/plugins/template/Gemfile.erb +27 -0
  76. data/fastlane/lib/fastlane/plugins/template/lib/fastlane/plugin/%plugin_name%/helper/%plugin_name%_helper.rb.erb +1 -1
  77. data/fastlane/lib/fastlane/runner.rb +2 -2
  78. data/fastlane/lib/fastlane/setup/setup.rb +1 -1
  79. data/fastlane/lib/fastlane/swift_lane_manager.rb +2 -5
  80. data/fastlane/lib/fastlane/swift_runner_upgrader.rb +7 -4
  81. data/fastlane/lib/fastlane/version.rb +2 -2
  82. data/fastlane/swift/Actions.swift +1 -1
  83. data/fastlane/swift/Appfile.swift +1 -1
  84. data/fastlane/swift/ArgumentProcessor.swift +1 -1
  85. data/fastlane/swift/Atomic.swift +1 -1
  86. data/fastlane/swift/ControlCommand.swift +1 -1
  87. data/fastlane/swift/Deliverfile.swift +2 -2
  88. data/fastlane/swift/DeliverfileProtocol.swift +4 -4
  89. data/fastlane/swift/Fastlane.swift +227 -36
  90. data/fastlane/swift/Gymfile.swift +2 -2
  91. data/fastlane/swift/GymfileProtocol.swift +2 -2
  92. data/fastlane/swift/LaneFileProtocol.swift +5 -5
  93. data/fastlane/swift/MainProcess.swift +1 -1
  94. data/fastlane/swift/Matchfile.swift +2 -2
  95. data/fastlane/swift/MatchfileProtocol.swift +22 -2
  96. data/fastlane/swift/OptionalConfigValue.swift +1 -1
  97. data/fastlane/swift/Plugins.swift +1 -1
  98. data/fastlane/swift/Precheckfile.swift +2 -2
  99. data/fastlane/swift/PrecheckfileProtocol.swift +2 -2
  100. data/fastlane/swift/RubyCommand.swift +1 -1
  101. data/fastlane/swift/RubyCommandable.swift +1 -1
  102. data/fastlane/swift/Runner.swift +1 -1
  103. data/fastlane/swift/RunnerArgument.swift +1 -1
  104. data/fastlane/swift/Scanfile.swift +2 -2
  105. data/fastlane/swift/ScanfileProtocol.swift +6 -2
  106. data/fastlane/swift/Screengrabfile.swift +2 -2
  107. data/fastlane/swift/ScreengrabfileProtocol.swift +2 -2
  108. data/fastlane/swift/Snapshotfile.swift +2 -2
  109. data/fastlane/swift/SnapshotfileProtocol.swift +2 -2
  110. data/fastlane/swift/SocketClient.swift +1 -1
  111. data/fastlane/swift/SocketClientDelegateProtocol.swift +1 -1
  112. data/fastlane/swift/SocketResponse.swift +1 -1
  113. data/fastlane/swift/formatting/Brewfile.lock.json +31 -23
  114. data/fastlane/swift/main.swift +1 -1
  115. data/fastlane_core/lib/fastlane_core/build_watcher.rb +1 -1
  116. data/fastlane_core/lib/fastlane_core/cert_checker.rb +4 -9
  117. data/fastlane_core/lib/fastlane_core/configuration/configuration_file.rb +1 -1
  118. data/fastlane_core/lib/fastlane_core/device_manager.rb +17 -15
  119. data/fastlane_core/lib/fastlane_core/fastlane_pty.rb +34 -12
  120. data/fastlane_core/lib/fastlane_core/helper.rb +1 -1
  121. data/fastlane_core/lib/fastlane_core/itunes_transporter.rb +53 -16
  122. data/fastlane_core/lib/fastlane_core/project.rb +7 -2
  123. data/fastlane_core/lib/fastlane_core/queue_worker.rb +2 -2
  124. data/fastlane_core/lib/fastlane_core/string_filters.rb +6 -6
  125. data/fastlane_core/lib/fastlane_core/ui/fastlane_runner.rb +2 -2
  126. data/frameit/lib/frameit/device_types.rb +1 -1
  127. data/frameit/lib/frameit/editor.rb +4 -4
  128. data/frameit/lib/frameit/trim_box.rb +1 -1
  129. data/gym/lib/gym/error_handler.rb +1 -1
  130. data/gym/lib/gym/generators/build_command_generator.rb +1 -1
  131. data/gym/lib/gym/generators/package_command_generator_xcode7.rb +3 -3
  132. data/gym/lib/gym/module.rb +13 -2
  133. data/gym/lib/gym/options.rb +1 -1
  134. data/gym/lib/gym/runner.rb +1 -1
  135. data/gym/lib/gym/xcodebuild_fixes/README.md +1 -1
  136. data/match/lib/match/change_password.rb +3 -9
  137. data/match/lib/match/commands_generator.rb +3 -6
  138. data/match/lib/match/encryption.rb +1 -1
  139. data/match/lib/match/generator.rb +9 -1
  140. data/match/lib/match/importer.rb +3 -30
  141. data/match/lib/match/migrate.rb +6 -2
  142. data/match/lib/match/module.rb +2 -1
  143. data/match/lib/match/nuke.rb +3 -24
  144. data/match/lib/match/options.rb +25 -0
  145. data/match/lib/match/portal_cache.rb +106 -0
  146. data/match/lib/match/portal_fetcher.rb +72 -0
  147. data/match/lib/match/profile_includes.rb +120 -0
  148. data/match/lib/match/runner.rb +93 -209
  149. data/match/lib/match/setup.rb +1 -1
  150. data/match/lib/match/spaceship_ensure.rb +15 -11
  151. data/match/lib/match/storage/git_storage.rb +17 -4
  152. data/match/lib/match/storage/gitlab/client.rb +40 -14
  153. data/match/lib/match/storage/gitlab_secure_files.rb +18 -7
  154. data/match/lib/match/storage/interface.rb +1 -1
  155. data/match/lib/match/storage/s3_storage.rb +7 -1
  156. data/match/lib/match/storage.rb +56 -5
  157. data/match/lib/match.rb +3 -0
  158. data/pilot/lib/pilot/build_manager.rb +4 -4
  159. data/precheck/lib/precheck/rules/unreachable_urls_rule.rb +1 -1
  160. data/produce/lib/produce/itunes_connect.rb +1 -1
  161. data/scan/lib/scan/detect_values.rb +86 -21
  162. data/scan/lib/scan/options.rb +6 -1
  163. data/scan/lib/scan/runner.rb +1 -1
  164. data/scan/lib/scan/test_command_generator.rb +1 -1
  165. data/screengrab/lib/screengrab/runner.rb +1 -1
  166. data/sigh/lib/assets/resign.sh +10 -10
  167. data/sigh/lib/sigh/commands_generator.rb +1 -1
  168. data/sigh/lib/sigh/module.rb +98 -0
  169. data/sigh/lib/sigh/options.rb +55 -1
  170. data/sigh/lib/sigh/resign.rb +1 -1
  171. data/sigh/lib/sigh/runner.rb +36 -112
  172. data/snapshot/lib/assets/SnapshotHelper.swift +13 -9
  173. data/snapshot/lib/snapshot/latest_os_version.rb +2 -5
  174. data/snapshot/lib/snapshot/reports_generator.rb +48 -7
  175. data/snapshot/lib/snapshot/setup.rb +2 -2
  176. data/snapshot/lib/snapshot/simulator_launchers/simulator_launcher.rb +23 -22
  177. data/snapshot/lib/snapshot/simulator_launchers/simulator_launcher_base.rb +2 -2
  178. data/snapshot/lib/snapshot/test_command_generator.rb +1 -1
  179. data/spaceship/lib/spaceship/client.rb +1 -2
  180. data/spaceship/lib/spaceship/connect_api/api_client.rb +22 -3
  181. data/spaceship/lib/spaceship/connect_api/client.rb +4 -4
  182. data/spaceship/lib/spaceship/connect_api/models/app.rb +5 -4
  183. data/spaceship/lib/spaceship/connect_api/models/app_info.rb +15 -9
  184. data/spaceship/lib/spaceship/connect_api/models/app_preview_set.rb +2 -0
  185. data/spaceship/lib/spaceship/connect_api/models/app_screenshot.rb +2 -2
  186. data/spaceship/lib/spaceship/connect_api/models/app_screenshot_set.rb +7 -0
  187. data/spaceship/lib/spaceship/connect_api/models/app_store_version.rb +1 -0
  188. data/spaceship/lib/spaceship/connect_api/models/beta_group.rb +3 -1
  189. data/spaceship/lib/spaceship/connect_api/models/bundle_id.rb +5 -5
  190. data/spaceship/lib/spaceship/connect_api/models/certificate.rb +3 -3
  191. data/spaceship/lib/spaceship/connect_api/models/device.rb +83 -4
  192. data/spaceship/lib/spaceship/connect_api/models/profile.rb +5 -3
  193. data/spaceship/lib/spaceship/connect_api/models/user.rb +38 -0
  194. data/spaceship/lib/spaceship/connect_api/models/user_invitation.rb +5 -15
  195. data/spaceship/lib/spaceship/connect_api/provisioning/provisioning.rb +14 -8
  196. data/spaceship/lib/spaceship/connect_api/testflight/testflight.rb +8 -2
  197. data/spaceship/lib/spaceship/connect_api/tunes/tunes.rb +3 -6
  198. data/spaceship/lib/spaceship/connect_api/users/users.rb +34 -0
  199. data/spaceship/lib/spaceship/connect_api.rb +2 -0
  200. data/spaceship/lib/spaceship/portal/app.rb +1 -1
  201. data/spaceship/lib/spaceship/portal/app_group.rb +1 -1
  202. data/spaceship/lib/spaceship/test_flight/client.rb +1 -1
  203. data/spaceship/lib/spaceship/test_flight/tester.rb +1 -1
  204. data/spaceship/lib/spaceship/tunes/app_details.rb +2 -2
  205. data/spaceship/lib/spaceship/tunes/app_image.rb +1 -1
  206. data/spaceship/lib/spaceship/tunes/app_review_attachment.rb +1 -1
  207. data/spaceship/lib/spaceship/tunes/app_submission.rb +1 -1
  208. data/spaceship/lib/spaceship/tunes/app_version.rb +5 -5
  209. data/spaceship/lib/spaceship/tunes/build_details.rb +1 -1
  210. data/spaceship/lib/spaceship/tunes/iap.rb +3 -3
  211. data/spaceship/lib/spaceship/tunes/iap_detail.rb +2 -2
  212. data/spaceship/lib/spaceship/tunes/iap_families.rb +1 -1
  213. data/spaceship/lib/spaceship/tunes/iap_family_details.rb +2 -2
  214. data/spaceship/lib/spaceship/tunes/iap_family_list.rb +1 -1
  215. data/spaceship/lib/spaceship/tunes/tunes_client.rb +3 -3
  216. data/supply/lib/supply/client.rb +80 -21
  217. data/supply/lib/supply/generated_universal_apk.rb +24 -0
  218. data/supply/lib/supply/image_listing.rb +15 -0
  219. data/supply/lib/supply/options.rb +5 -0
  220. data/supply/lib/supply/setup.rb +2 -2
  221. data/supply/lib/supply/uploader.rb +60 -18
  222. data/supply/lib/supply.rb +2 -0
  223. data/trainer/lib/trainer/junit_generator.rb +1 -1
  224. data/trainer/lib/trainer/test_parser.rb +1 -1
  225. data/trainer/lib/trainer/xcresult.rb +1 -1
  226. metadata +205 -431
  227. data/fastlane/lib/fastlane/plugins/template/Gemfile +0 -6
@@ -89,7 +89,8 @@ module Deliver
89
89
  enabled_languages = detect_languages(options)
90
90
 
91
91
  app_store_version_localizations = verify_available_version_languages!(options, app, enabled_languages) unless options[:edit_live]
92
- app_info_localizations = verify_available_info_languages!(options, app, enabled_languages) unless options[:edit_live]
92
+ app_info = fetch_edit_app_info(app)
93
+ app_info_localizations = verify_available_info_languages!(options, app, app_info, enabled_languages) unless options[:edit_live] || !updating_localized_app_info?(options, app, app_info)
93
94
 
94
95
  if options[:edit_live]
95
96
  # not all values are editable when using live_version
@@ -211,18 +212,19 @@ module Deliver
211
212
  store_version_worker.start
212
213
 
213
214
  # Update app info localizations
214
- app_info_worker = FastlaneCore::QueueWorker.new do |app_info_localization|
215
- attributes = localized_info_attributes_by_locale[app_info_localization.locale]
216
- if attributes
217
- UI.message("Uploading metadata to App Store Connect for localized info '#{app_info_localization.locale}'")
218
- app_info_localization.update(attributes: attributes)
215
+ if app_info_localizations
216
+ app_info_worker = FastlaneCore::QueueWorker.new do |app_info_localization|
217
+ attributes = localized_info_attributes_by_locale[app_info_localization.locale]
218
+ if attributes
219
+ UI.message("Uploading metadata to App Store Connect for localized info '#{app_info_localization.locale}'")
220
+ app_info_localization.update(attributes: attributes)
221
+ end
219
222
  end
223
+ app_info_worker.batch_enqueue(app_info_localizations)
224
+ app_info_worker.start
220
225
  end
221
- app_info_worker.batch_enqueue(app_info_localizations)
222
- app_info_worker.start
223
226
 
224
227
  # Update categories
225
- app_info = fetch_edit_app_info(app)
226
228
  if app_info
227
229
  category_id_map = {}
228
230
 
@@ -235,7 +237,7 @@ module Deliver
235
237
 
236
238
  mapped_values = {}
237
239
 
238
- # Only update primary and secondar category if explicitly set
240
+ # Only update primary and secondary category if explicitly set
239
241
  unless primary_category.empty?
240
242
  mapped = Spaceship::ConnectAPI::AppCategory.map_category_from_itc(
241
243
  primary_category
@@ -437,6 +439,12 @@ module Deliver
437
439
  end
438
440
  end
439
441
 
442
+ def fetch_live_app_info(app, wait_time: 10)
443
+ retry_if_nil("Cannot find live app info", wait_time: wait_time) do
444
+ app.fetch_live_app_info
445
+ end
446
+ end
447
+
440
448
  def retry_if_nil(message, tries: 5, wait_time: 10)
441
449
  loop do
442
450
  tries -= 1
@@ -451,12 +459,49 @@ module Deliver
451
459
  end
452
460
  end
453
461
 
454
- # Finding languages to enable
455
- def verify_available_info_languages!(options, app, languages)
456
- app_info = fetch_edit_app_info(app)
462
+ # Checking if the metadata to update includes localised App Info
463
+ def updating_localized_app_info?(options, app, app_info)
464
+ app_info ||= fetch_live_app_info(app)
465
+ unless app_info
466
+ UI.important("Can't find edit or live App info. Skipping upload.")
467
+ return false
468
+ end
469
+ localizations = app_info.get_app_info_localizations
470
+
471
+ LOCALISED_APP_VALUES.each do |key, localized_key|
472
+ current = options[key]
473
+ next unless current
474
+
475
+ unless current.kind_of?(Hash)
476
+ UI.error("Error with provided '#{key}'. Must be a hash, the key being the language.")
477
+ next
478
+ end
479
+
480
+ current.each do |language, value|
481
+ strip_value = value.to_s.strip
482
+ next if strip_value.empty?
483
+
484
+ app_info_locale = localizations.find { |l| l.locale == language }
485
+ next if app_info_locale.nil?
457
486
 
487
+ begin
488
+ current_value = app_info_locale.public_send(localized_key.to_sym)
489
+ rescue NoMethodError
490
+ next
491
+ end
492
+
493
+ return true if current_value != strip_value
494
+ end
495
+ end
496
+
497
+ UI.message('No changes to localized App Info detected. Skipping upload.')
498
+ return false
499
+ end
500
+
501
+ # Finding languages to enable
502
+ def verify_available_info_languages!(options, app, app_info, languages)
458
503
  unless app_info
459
- UI.user_error!("Cannot update languages - could not find an editable info")
504
+ UI.user_error!("Cannot update languages - could not find an editable 'App Info'. Verify that your app is in one of the editable states in App Store Connect")
460
505
  return
461
506
  end
462
507
 
@@ -654,7 +699,7 @@ module Deliver
654
699
  end
655
700
  UI.message("Setting the app's age rating...")
656
701
 
657
- # Maping from legacy ITC values to App Store Connect Values
702
+ # Mapping from legacy ITC values to App Store Connect Values
658
703
  mapped_values = {}
659
704
  attributes = {}
660
705
  json.each do |k, v|
@@ -19,9 +19,9 @@ module Deliver
19
19
  # As of 2020-09-14:
20
20
  # Official App Store Connect does not have an endpoint to get app prices for an app
21
21
  # Need to get prices from the app's relationships
22
- # Prices from app's relationship doess not have price tier so need to fetch app price with price tier relationship
22
+ # Prices from app's relationship does not have price tier so need to fetch app price with price tier relationship
23
23
  app_prices = app.prices
24
- if app_prices.first
24
+ if app_prices&.first
25
25
  app_price = Spaceship::ConnectAPI.get_app_price(app_price_id: app_prices.first.id, includes: "priceTier").first
26
26
  old_price = app_price.price_tier.id
27
27
  else
@@ -85,7 +85,7 @@ module Deliver
85
85
  # Only delete screenshots if trying to upload
86
86
  next unless screenshots_per_language.keys.include?(localization.locale)
87
87
 
88
- UI.verbose("Queued delete sceeenshot set job for #{localization.locale} #{app_screenshot_set.screenshot_display_type}")
88
+ UI.verbose("Queued delete screenshot set job for #{localization.locale} #{app_screenshot_set.screenshot_display_type}")
89
89
  worker.enqueue(DeleteScreenshotSetJob.new(app_screenshot_set, localization))
90
90
  end
91
91
 
@@ -145,7 +145,7 @@ module Deliver
145
145
  if duplicate
146
146
  UI.message("Previous uploaded. Skipping '#{screenshot.path}'...")
147
147
  else
148
- UI.verbose("Queued upload sceeenshot job for #{localization.locale} #{app_screenshot_set.screenshot_display_type} #{screenshot.path}")
148
+ UI.verbose("Queued upload screenshot job for #{localization.locale} #{app_screenshot_set.screenshot_display_type} #{screenshot.path}")
149
149
  worker.enqueue(UploadScreenshotJob.new(app_screenshot_set, screenshot.path))
150
150
  number_of_screenshots_per_set[app_screenshot_set] += 1
151
151
  end
@@ -258,7 +258,7 @@ module Deliver
258
258
  # helper method so Spaceship::Tunes.client.available_languages is easier to test
259
259
  def self.available_languages
260
260
  # 2020-08-24 - Available locales are not available as an endpoint in App Store Connect
261
- # Update with Spaceship::Tunes.client.available_languages.sort (as long as endpoint is avilable)
261
+ # Update with Spaceship::Tunes.client.available_languages.sort (as long as endpoint is available)
262
262
  Deliver::Languages::ALL_LANGUAGES
263
263
  end
264
264
 
@@ -7,7 +7,7 @@ module Fastlane
7
7
  class [[NAME_CLASS]] < Action
8
8
  def self.run(params)
9
9
  # fastlane will take care of reading in the parameter and fetching the environment variable:
10
- UI.message "Parameter API Token: #{params[:api_token]}"
10
+ UI.message("Parameter API Token: #{params[:api_token]}")
11
11
 
12
12
  # sh "shellcommand ./path"
13
13
 
@@ -19,13 +19,13 @@ module Fastlane
19
19
  #####################################################
20
20
 
21
21
  def self.description
22
- "A short description with <= 80 characters of what this action does"
22
+ 'A short description with <= 80 characters of what this action does'
23
23
  end
24
24
 
25
25
  def self.details
26
26
  # Optional:
27
27
  # this is your chance to provide a more detailed description of this action
28
- "You can use this action to do cool things..."
28
+ 'You can use this action to do cool things...'
29
29
  end
30
30
 
31
31
  def self.available_options
@@ -34,17 +34,23 @@ module Fastlane
34
34
  # Below a few examples
35
35
  [
36
36
  FastlaneCore::ConfigItem.new(key: :api_token,
37
- env_name: "FL_[[NAME_UP]]_API_TOKEN", # The name of the environment variable
38
- description: "API Token for [[NAME_CLASS]]", # a short description of this parameter
37
+ # The name of the environment variable
38
+ env_name: 'FL_[[NAME_UP]]_API_TOKEN',
39
+ # a short description of this parameter
40
+ description: 'API Token for [[NAME_CLASS]]',
39
41
  verify_block: proc do |value|
40
- UI.user_error!("No API token for [[NAME_CLASS]] given, pass using `api_token: 'token'`") unless (value and not value.empty?)
41
- # UI.user_error!("Couldn't find file at path '#{value}'") unless File.exist?(value)
42
+ unless value && !value.empty?
43
+ UI.user_error!("No API token for [[NAME_CLASS]] given, pass using `api_token: 'token'`")
44
+ end
45
+ # UI.user_error!("Couldn't find file at path '#{value}'") unless File.exist?(value)
42
46
  end),
43
47
  FastlaneCore::ConfigItem.new(key: :development,
44
- env_name: "FL_[[NAME_UP]]_DEVELOPMENT",
45
- description: "Create a development certificate instead of a distribution one",
46
- is_string: false, # true: verifies the input is a string, false: every kind of value
47
- default_value: false) # the default value if the user didn't provide one
48
+ env_name: 'FL_[[NAME_UP]]_DEVELOPMENT',
49
+ description: 'Create a development certificate instead of a distribution one',
50
+ # true: verifies the input is a string, false: every kind of value
51
+ is_string: false,
52
+ # the default value if the user didn't provide one
53
+ default_value: false)
48
54
  ]
49
55
  end
50
56
 
@@ -62,7 +68,7 @@ module Fastlane
62
68
 
63
69
  def self.authors
64
70
  # So no one will ever forget your contribution to fastlane :) You are awesome btw!
65
- ["Your GitHub/Twitter Name"]
71
+ ['Your GitHub/Twitter Name']
66
72
  end
67
73
 
68
74
  def self.is_supported?(platform)
@@ -179,7 +179,7 @@ class String
179
179
 
180
180
  def markdown_clean_heredoc!
181
181
  self.chomp! # remove the last new line added by the heredoc
182
- self.dedent! # remove the leading whitespace (similar to the squigly heredoc `<<~`)
182
+ self.dedent! # remove the leading whitespace (similar to the squiggly heredoc `<<~`)
183
183
  end
184
184
 
185
185
  def dedent!
@@ -214,7 +214,7 @@ module Fastlane
214
214
  ],
215
215
  ignore: [
216
216
  "ignore/path/1",
217
- "ingore/path/2"
217
+ "ignore/path/2"
218
218
  ],
219
219
  options: "--keep-intermediate-files --search-undocumented-doc",
220
220
  warnings: "--warn-missing-output-path --warn-missing-company-id"
@@ -8,7 +8,7 @@ module Fastlane
8
8
  command << upload_url(params[:app_id].shellescape)
9
9
 
10
10
  # Fastlane::Actions.sh has buffering issues, no progress bar is shown in real time
11
- # will reanable it when it is fixed
11
+ # will reenable it when it is fixed
12
12
  # result = Fastlane::Actions.sh(command.join(' '), log: false)
13
13
  shell_command = command.join(' ')
14
14
  return shell_command if Helper.test?
@@ -15,7 +15,7 @@ module Fastlane
15
15
  zip_filename = params[:zip_filename]
16
16
  versioned = params[:versioned]
17
17
 
18
- # Prepare destionation folder
18
+ # Prepare destination folder
19
19
  full_destination = base_destination
20
20
 
21
21
  if versioned
@@ -45,7 +45,7 @@ module Fastlane
45
45
  error = if json['message'] == "Invalid request.\n\n\"sha\" wasn't supplied."
46
46
  "File already exists - please remove from repo before uploading or rename this upload"
47
47
  else
48
- "Uprocessable error"
48
+ "Unprocessable error"
49
49
  end
50
50
  UI.user_error!(error)
51
51
  end
@@ -115,7 +115,7 @@ module Fastlane
115
115
  env_name: "FL_COMMIT_GITHUB_FILE_API_BEARER",
116
116
  sensitive: true,
117
117
  code_gen_sensitive: true,
118
- description: "Use a Bearer authorization token. Usually generated by Github Apps, e.g. GitHub Actions GITHUB_TOKEN environment variable",
118
+ description: "Use a Bearer authorization token. Usually generated by GitHub Apps, e.g. GitHub Actions GITHUB_TOKEN environment variable",
119
119
  conflicting_options: [:api_token],
120
120
  optional: true,
121
121
  default_value: nil),
@@ -25,7 +25,7 @@ module Fastlane
25
25
  missing = artifacts.reject { |a| File.exist?(a) }
26
26
  UI.user_error!("Not all files were present in copy artifacts. Missing #{missing.join(', ')}") unless missing.empty?
27
27
  else
28
- # If we don't fail on non-existent files, don't try to copy non-existent files
28
+ # If we don't fail on nonexistent files, don't try to copy nonexistent files
29
29
  artifacts.select! { |artifact| File.exist?(artifact) }
30
30
  end
31
31
 
@@ -10,7 +10,7 @@ module Fastlane
10
10
 
11
11
  return if Helper.test?
12
12
 
13
- Produce.config = params # we alread have the finished config
13
+ Produce.config = params # we already have the finished config
14
14
 
15
15
  Dir.chdir(FastlaneCore::FastlaneFolder.path || Dir.pwd) do
16
16
  # This should be executed in the fastlane folder
@@ -169,7 +169,7 @@ module Fastlane
169
169
  optional: true),
170
170
  FastlaneCore::ConfigItem.new(key: :api_bearer,
171
171
  env_name: "GITHUB_PULL_REQUEST_API_BEARER",
172
- description: "Use a Bearer authorization token. Usually generated by Github Apps, e.g. GitHub Actions GITHUB_TOKEN environment variable",
172
+ description: "Use a Bearer authorization token. Usually generated by GitHub Apps, e.g. GitHub Actions GITHUB_TOKEN environment variable",
173
173
  sensitive: true,
174
174
  code_gen_sensitive: true,
175
175
  conflicting_options: [:api_token],
@@ -42,8 +42,8 @@ fastlane gym
42
42
 
43
43
  _gym_ uses the latest APIs to build and sign your application which results in much faster build times.
44
44
 
45
- | | Gym Features |
46
- |----------|----------------|
45
+ | | _gym_ Features |
46
+ |----------|------------------|
47
47
  🚀 | _gym_ builds 30% faster than other build tools like [shenzhen](https://github.com/nomad/shenzhen)
48
48
  🏁 | Beautiful inline build output
49
49
  📖 | Helps you resolve common build errors like code signing issues
@@ -32,7 +32,7 @@ androidTestImplementation 'tools.fastlane:screengrab:x.x.x'
32
32
 
33
33
  The latest version is [ ![Download](https://maven-badges.herokuapp.com/maven-central/tools.fastlane/screengrab/badge.svg)](https://search.maven.org/artifact/tools.fastlane/screengrab)
34
34
 
35
- As of Screengrab version 2.0.0, all Android test dependencies are AndroidX dependencies. This means a device with API 18+, Android 4.3 or greater is required. If you wish to capture screenshots with an older Android OS, then you must use a 1.x.x version.
35
+ As of _screengrab_ version 2.0.0, all Android test dependencies are AndroidX dependencies. This means a device with API 18+, Android 4.3 or greater is required. If you wish to capture screenshots with an older Android OS, then you must use a 1.x.x version.
36
36
 
37
37
  ##### Configuring your Manifest Permissions
38
38
 
@@ -63,21 +63,21 @@ Ensure that the following permissions exist in your **src/debug/AndroidManifest.
63
63
  1. Add `LocaleTestRule` to your tests class to handle automatic switching of locales.
64
64
 
65
65
  If you're using Java use:
66
-
66
+
67
67
  ```java
68
68
  @ClassRule
69
69
  public static final LocaleTestRule localeTestRule = new LocaleTestRule();
70
70
  ```
71
-
71
+
72
72
  If you're using Kotlin use:
73
-
73
+
74
74
  ```kotlin
75
75
  @Rule @JvmField
76
76
  val localeTestRule = LocaleTestRule()
77
77
  ```
78
-
78
+
79
79
  The `@JvmField` annotation is important. It won't work like this:
80
-
80
+
81
81
  ```kotlin
82
82
  companion object {
83
83
  @get:ClassRule
@@ -87,7 +87,7 @@ Ensure that the following permissions exist in your **src/debug/AndroidManifest.
87
87
 
88
88
  2. To capture screenshots, add the following to your tests `Screengrab.screenshot("name_of_screenshot_here");` on the appropriate screens
89
89
 
90
- # Generating Screenshots with Screengrab
90
+ # Generating Screenshots with _screengrab_
91
91
  - Then, before running `fastlane screengrab` you'll need a debug and test apk
92
92
  - You can create your APKs manually with `./gradlew assembleDebug assembleAndroidTest`
93
93
  - You can also create a lane and use `build_android_app`:
@@ -228,7 +228,7 @@ When using JUnit 3 you'll need to add a bit more code:
228
228
 
229
229
  ## Clean Status Bar
230
230
 
231
- Screengrab can clean your status bar to make your screenshots even more beautiful.
231
+ _screengrab_ can clean your status bar to make your screenshots even more beautiful.
232
232
  It is simply a wrapper that allows configuring SystemUI DemoMode in your code.
233
233
  Note: the clean status bar feature is only supported on devices with *API level >= 23*.
234
234
 
@@ -2,7 +2,7 @@
2
2
  <img src="/img/actions/precheck.png" width="250">
3
3
  </p>
4
4
 
5
- Precheck
5
+ _precheck_
6
6
  ============
7
7
 
8
8
  ###### Check your app using a community driven set of App Store review rules to avoid being rejected
@@ -23,8 +23,8 @@ Apple rejects builds for many avoidable metadata issues like including swear wor
23
23
  # Features
24
24
 
25
25
 
26
- | | precheck Features |
27
- |----------|-----------------|
26
+ | | _precheck_ Features |
27
+ |----------|-----------------------|
28
28
  🐛 |  product bug mentions
29
29
  🙅 | Swear word checker
30
30
  🤖 | Mentioning other platforms
@@ -48,7 +48,7 @@ This does the following:
48
48
  - Downloads the certificate
49
49
  - Generates a new ```.pem``` file in the current working directory, which you can upload to your server
50
50
 
51
- Note that _pem_ will never revoke your existing certificates. _pem_ can't download any of your existing push certificates, as the private key is only available on the machine it was created on.
51
+ Note that _pem_ will never revoke your existing certificates. _pem_ can't download any of your existing push certificates, as the private key is only available on the machine it was created on.
52
52
 
53
53
  If you already have a push certificate enabled, which is active for at least 30 more days, _pem_ will not create a new certificate. If you still want to create one, use the `force`:
54
54
 
@@ -111,7 +111,7 @@ If you need the `p12` in your keychain, perhaps to test push with an app like [K
111
111
  Enter Import Password:
112
112
  <hit enter: the p12 has no password>
113
113
  MAC verified OK
114
- Enter PEM pass phrase:
114
+ Enter your pem passphrase:
115
115
  <enter a temporary password to encrypt the pem file>
116
116
 
117
117
  % openssl pkcs12 -export -in my.pem -out my-with-passphrase.p12
@@ -212,7 +212,7 @@ fastlane match development
212
212
 
213
213
  <img src="/img/actions/match_appstore_small.gif" width="550" />
214
214
 
215
- This will create a new certificate and provisioning profile (if required) and store them in your selected storage.
215
+ This will create a new certificate and provisioning profile (if required) and store them in your selected storage.
216
216
  If you previously ran _match_ with the configured storage it will automatically install the existing profiles from your storage.
217
217
 
218
218
  The provisioning profiles are installed in `~/Library/MobileDevice/Provisioning Profiles` while the certificates and private keys are installed in your Keychain.
@@ -400,7 +400,7 @@ By using the `force_for_new_devices` parameter, _match_ will check if the (enabl
400
400
 
401
401
  _**Important:** The `force_for_new_devices` parameter is ignored for App Store provisioning profiles since they don't contain any device information._
402
402
 
403
- If you're not using _fastlane_, you can also use the `force_for_new_devices` option from the command line:
403
+ If you're not using `Fastfile`, you can also use the `force_for_new_devices` option from the command line:
404
404
 
405
405
  ```no-highlight
406
406
  fastlane match adhoc --force_for_new_devices
@@ -408,7 +408,7 @@ fastlane match adhoc --force_for_new_devices
408
408
 
409
409
  ##### Templates (aka: custom entitlements)
410
410
 
411
- Match can generate profiles that contain custom entitlements by passing in the entitlement's name with the `template_name` parameter.
411
+ _match_ can generate profiles that contain custom entitlements by passing in the entitlement's name with the `template_name` parameter.
412
412
 
413
413
  ```
414
414
  match(type: "development",
@@ -512,9 +512,11 @@ Please be careful when using this option and ensure the certificates and profile
512
512
  If you want to manually decrypt a file you can.
513
513
 
514
514
  ```no-highlight
515
- openssl aes-256-cbc -k "<password>" -in "<fileYouWantToDecryptPath>" -out "<decryptedFilePath>" -a -d
515
+ openssl aes-256-cbc -k "<password>" -in "<fileYouWantToDecryptPath>" -out "<decryptedFilePath>" -a -d -md [md5|sha256]
516
516
  ```
517
517
 
518
+ _**Note:** You may need to swap double quotes `"` for single quotes `'` if your match password contains an exclamation mark `!`._
519
+
518
520
  #### Export Distribution Certificate and Private Key as Single .p12 File
519
521
 
520
522
  _match_ stores the certificate (`.cer`) and the private key (`.p12`) files separately. The following steps will repackage the separate certificate and private key into a single `.p12` file.
@@ -441,7 +441,7 @@ fastlane deliver submit_build --build_number 830 --submission_information "{\"ex
441
441
 
442
442
  ### App Privacy Details
443
443
 
444
- Starting on December 8, 2020, Apple announced that developers are required to provide app privacy details that will help users understand an app's privacy practies. _deliver_ does not allow for updating of this information but this can be done with the _upload_app_privacy_details_to_app_store_ action. More information on [Uploading App Privacy Details](https://docs.fastlane.tools/uploading-app-privacy-details)
444
+ Starting on December 8, 2020, Apple announced that developers are required to provide app privacy details that will help users understand an app's privacy practices. _deliver_ does not allow for updating of this information but this can be done with the _upload_app_privacy_details_to_app_store_ action. More information on [Uploading App Privacy Details](https://docs.fastlane.tools/uploading-app-privacy-details)
445
445
 
446
446
  # Credentials
447
447
 
@@ -179,6 +179,12 @@ This can be done using the `--track_promote_to` parameter. The `--track_promote_
179
179
  Before performing a new APK upload you may want to check existing track version codes or release names, or you may simply want to provide an informational lane that displays the currently promoted version codes or release name for the production track. You can use the `google_play_track_version_codes` action to retrieve existing version codes for a package and track. You can use the `google_play_track_release_names` action to retrieve existing release names for a package and track.
180
180
  For more information, see the `fastlane action google_play_track_version_codes` and `fastlane action google_play_track_release_names` help output.
181
181
 
182
+ ## Parallel uploads
183
+
184
+ By default _supply_ will spawn 10 threads to upload the metadata concurrently (_images, screenshots, texts_). If you want to change this, set either `DELIVER_NUMBER_OF_THREADS` or `FL_NUMBER_OF_THREADS` environment variable to any value between 1 and 10.
185
+
186
+ If you want _supply_ to upload with more than 10 threads in parallel then you need to **additionally** set `FL_MAX_NUMBER_OF_THREADS` environment variable to the max number of parallel upload threads you wish to have (**Warning ⚠️** use this at your own risk!).
187
+
182
188
  ## Migration from AndroidPublisherV2 to AndroidPublisherV3 in _fastlane_ 2.135.0
183
189
 
184
190
  ### New Options
@@ -200,5 +206,3 @@ For more information, see the `fastlane action google_play_track_version_codes`
200
206
  - Google Play will automatically remove releases that are superseded now
201
207
  - `:deactivate_on_promote`
202
208
  - Google Play will automatically deactivate a release from its previous track on promote
203
-
204
- :
@@ -4,7 +4,7 @@
4
4
 
5
5
  ###### The best way to manage your TestFlight testers and builds from your terminal
6
6
 
7
- Pilot makes it easier to manage your app on Apple’s TestFlight. You can:
7
+ _pilot_ makes it easier to manage your app on Apple’s TestFlight. You can:
8
8
 
9
9
  - Upload & distribute builds
10
10
  - Add & remove testers
@@ -0,0 +1,124 @@
1
+ require 'supply'
2
+ require 'supply/options'
3
+
4
+ module Fastlane
5
+ module Actions
6
+ class DownloadUniversalApkFromGooglePlayAction < Action
7
+ def self.run(params)
8
+ package_name = params[:package_name]
9
+ version_code = params[:version_code]
10
+ destination = params[:destination]
11
+ cert_sha = params[:certificate_sha256_hash]
12
+
13
+ client = Supply::Client.make_from_config(params: params)
14
+
15
+ UI.message("Fetching the list of generated APKs from the Google API...")
16
+ all_universal_apks = client.list_generated_universal_apks(package_name: package_name, version_code: version_code)
17
+ matching_apks = all_universal_apks.select { |apk| cert_sha.nil? || apk.certificate_sha256_hash&.casecmp?(cert_sha) }
18
+
19
+ all_certs_printable_list = all_universal_apks.map { |apk| " - #{apk.certificate_sha256_hash}" }
20
+ if matching_apks.count > 1
21
+ message = <<~ERROR
22
+ We found multiple Generated Universal APK, with the following `certificate_sha256_hash`:
23
+ #{all_certs_printable_list.join("\n")}
24
+
25
+ Use the `certificate_sha256_hash` parameter to specify which one to download.
26
+ ERROR
27
+ UI.user_error!(message)
28
+ elsif matching_apks.empty?
29
+ # NOTE: if no APK was found at all to begin with, the client would already have raised a user_error!('Google Api Error ...')
30
+ message = <<~ERROR
31
+ None of the Universal APK(s) found for this version code matched the `certificate_sha256_hash` of `#{cert_sha}`.
32
+
33
+ We found #{all_universal_apks.count} Generated Universal APK(s), but with a different `certificate_sha256_hash`:
34
+ #{all_certs_printable_list.join("\n")}
35
+ ERROR
36
+ UI.user_error!(message)
37
+ end
38
+
39
+ UI.message("Downloading Generated Universal APK to `#{destination}`...")
40
+ FileUtils.mkdir_p(File.dirname(destination))
41
+ client.download_generated_universal_apk(generated_universal_apk: matching_apks.first, destination: destination)
42
+
43
+ UI.success("Universal APK successfully downloaded to `#{destination}`.")
44
+ destination
45
+ end
46
+
47
+ #####################################################
48
+ # @!group Documentation
49
+ #####################################################
50
+
51
+ def self.description
52
+ "Download the Universal APK of a given version code from the Google Play Console"
53
+ end
54
+
55
+ def self.details
56
+ <<~DETAILS
57
+ Download the universal APK of a given version code from the Google Play Console.
58
+
59
+ This uses _fastlane_ `supply` (and the `AndroidPublisher` Google API) to download the Universal APK
60
+ generated by Google after you uploaded an `.aab` bundle to the Play Console.
61
+
62
+ See https://developers.google.com/android-publisher/api-ref/rest/v3/generatedapks/list
63
+ DETAILS
64
+ end
65
+
66
+ def self.available_options
67
+ # Only borrow _some_ of the ConfigItems from https://github.com/fastlane/fastlane/blob/master/supply/lib/supply/options.rb
68
+ # So we don't have to duplicate the name, env_var, type, description, and verify_block of those here.
69
+ supply_borrowed_options = Supply::Options.available_options.select do |o|
70
+ %i[package_name version_code json_key json_key_data root_url timeout].include?(o.key)
71
+ end
72
+ # Adjust the description for the :version_code ConfigItem for our action's use case
73
+ supply_borrowed_options.find { |o| o.key == :version_code }&.description = "The versionCode for which to download the generated APK"
74
+
75
+ [
76
+ *supply_borrowed_options,
77
+
78
+ # The remaining ConfigItems below are specific to this action
79
+ FastlaneCore::ConfigItem.new(key: :destination,
80
+ env_name: 'DOWNLOAD_UNIVERSAL_APK_DESTINATION',
81
+ optional: false,
82
+ type: String,
83
+ description: "The path on disk where to download the Generated Universal APK",
84
+ verify_block: proc do |value|
85
+ UI.user_error!("The 'destination' must be a file path with the `.apk` file extension") unless File.extname(value) == '.apk'
86
+ end),
87
+ FastlaneCore::ConfigItem.new(key: :certificate_sha256_hash,
88
+ env_name: 'DOWNLOAD_UNIVERSAL_APK_CERTIFICATE_SHA256_HASH',
89
+ optional: true,
90
+ type: String,
91
+ description: "The SHA256 hash of the signing key for which to download the Universal, Code-Signed APK for. " \
92
+ + "Use 'xx:xx:xx:…' format (32 hex bytes separated by colons), as printed by `keytool -list -keystore <keystorefile>`. " \
93
+ + "Only useful to provide if you have multiple signing keys configured on GPC, to specify which generated APK to download",
94
+ verify_block: proc do |value|
95
+ bytes = value.split(':')
96
+ next if bytes.length == 32 && bytes.all? { |byte| /^[0-9a-fA-F]{2}$/.match?(byte) }
97
+
98
+ UI.user_error!("When provided, the certificate sha256 must be in the 'xx:xx:xx:…:xx' (32 hex bytes separated by colons) format")
99
+ end)
100
+ ]
101
+ end
102
+
103
+ def self.output
104
+ # Define the shared values you are going to provide
105
+ end
106
+
107
+ def self.return_value
108
+ 'The path to the downloaded Universal APK. The action will raise an exception if it failed to find or download the APK in Google Play'
109
+ end
110
+
111
+ def self.authors
112
+ ['Automattic']
113
+ end
114
+
115
+ def self.category
116
+ :production
117
+ end
118
+
119
+ def self.is_supported?(platform)
120
+ platform == :android
121
+ end
122
+ end
123
+ end
124
+ end