fastlane 2.141.0 → 2.146.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +1 -1
  3. data/README.md +82 -82
  4. data/credentials_manager/lib/credentials_manager/appfile_config.rb +4 -0
  5. data/deliver/lib/deliver/app_screenshot.rb +1 -0
  6. data/deliver/lib/deliver/options.rb +30 -1
  7. data/deliver/lib/deliver/setup.rb +4 -4
  8. data/fastlane/lib/fastlane/actions/.update_code_signing_settings.rb.swp +0 -0
  9. data/fastlane/lib/fastlane/actions/README.md +2 -0
  10. data/fastlane/lib/fastlane/actions/app_store_build_number.rb +13 -5
  11. data/fastlane/lib/fastlane/actions/automatic_code_signing.rb +7 -1
  12. data/fastlane/lib/fastlane/actions/clean_build_artifacts.rb +3 -0
  13. data/fastlane/lib/fastlane/actions/cocoapods.rb +2 -2
  14. data/fastlane/lib/fastlane/actions/crashlytics.rb +14 -2
  15. data/fastlane/lib/fastlane/actions/create_pull_request.rb +7 -1
  16. data/fastlane/lib/fastlane/actions/docs/capture_ios_screenshots.md +10 -4
  17. data/fastlane/lib/fastlane/actions/docs/frame_screenshots.md +22 -6
  18. data/fastlane/lib/fastlane/actions/docs/sync_code_signing.md +23 -7
  19. data/fastlane/lib/fastlane/actions/ensure_git_branch.rb +1 -1
  20. data/fastlane/lib/fastlane/actions/ensure_xcode_version.rb +35 -7
  21. data/fastlane/lib/fastlane/actions/frame_screenshots.rb +2 -1
  22. data/fastlane/lib/fastlane/actions/get_github_release.rb +3 -0
  23. data/fastlane/lib/fastlane/actions/get_version_number.rb +1 -1
  24. data/fastlane/lib/fastlane/actions/latest_testflight_build_number.rb +9 -3
  25. data/fastlane/lib/fastlane/actions/notarize.rb +183 -0
  26. data/fastlane/lib/fastlane/actions/pod_lib_lint.rb +7 -1
  27. data/fastlane/lib/fastlane/actions/s3.rb +5 -291
  28. data/fastlane/lib/fastlane/actions/setup_ci.rb +1 -1
  29. data/fastlane/lib/fastlane/actions/setup_jenkins.rb +11 -2
  30. data/fastlane/lib/fastlane/actions/slather.rb +1 -1
  31. data/fastlane/lib/fastlane/actions/spm.rb +8 -0
  32. data/fastlane/lib/fastlane/actions/swiftlint.rb +45 -9
  33. data/fastlane/lib/fastlane/actions/update_code_signing_settings.rb +198 -0
  34. data/fastlane/lib/fastlane/actions/upload_symbols_to_crashlytics.rb +14 -4
  35. data/fastlane/lib/fastlane/actions/verify_build.rb +1 -1
  36. data/fastlane/lib/fastlane/helper/adb_helper.rb +1 -1
  37. data/fastlane/lib/fastlane/helper/s3_client_helper.rb +61 -0
  38. data/fastlane/lib/fastlane/plugins/plugin_manager.rb +1 -1
  39. data/fastlane/lib/fastlane/server/socket_server_action_command_executor.rb +1 -1
  40. data/fastlane/lib/fastlane/version.rb +1 -1
  41. data/fastlane/swift/Deliverfile.swift +1 -1
  42. data/fastlane/swift/Fastlane.swift +201 -13
  43. data/fastlane/swift/Gymfile.swift +1 -1
  44. data/fastlane/swift/Matchfile.swift +1 -1
  45. data/fastlane/swift/MatchfileProtocol.swift +17 -1
  46. data/fastlane/swift/Precheckfile.swift +1 -1
  47. data/fastlane/swift/RubyCommand.swift +1 -1
  48. data/fastlane/swift/Scanfile.swift +1 -1
  49. data/fastlane/swift/ScanfileProtocol.swift +9 -1
  50. data/fastlane/swift/Screengrabfile.swift +1 -1
  51. data/fastlane/swift/Snapshotfile.swift +1 -1
  52. data/fastlane_core/lib/fastlane_core/configuration/config_item.rb +9 -0
  53. data/fastlane_core/lib/fastlane_core/device_manager.rb +3 -3
  54. data/fastlane_core/lib/fastlane_core/ipa_file_analyser.rb +1 -0
  55. data/fastlane_core/lib/fastlane_core/keychain_importer.rb +2 -0
  56. data/fastlane_core/lib/fastlane_core/project.rb +4 -0
  57. data/fastlane_core/lib/fastlane_core/provisioning_profile.rb +15 -2
  58. data/frameit/lib/frameit/commands_generator.rb +25 -0
  59. data/frameit/lib/frameit/config_parser.rb +31 -9
  60. data/frameit/lib/frameit/device.rb +90 -0
  61. data/frameit/lib/frameit/device_types.rb +121 -5
  62. data/frameit/lib/frameit/editor.rb +29 -41
  63. data/frameit/lib/frameit/offsets.rb +8 -1
  64. data/frameit/lib/frameit/options.rb +81 -54
  65. data/frameit/lib/frameit/runner.rb +17 -7
  66. data/frameit/lib/frameit/screenshot.rb +39 -47
  67. data/frameit/lib/frameit/template_finder.rb +15 -12
  68. data/gym/lib/gym/generators/package_command_generator.rb +4 -0
  69. data/gym/lib/gym/generators/package_command_generator_xcode7.rb +5 -0
  70. data/gym/lib/gym/runner.rb +16 -2
  71. data/match/lib/match/change_password.rb +1 -1
  72. data/match/lib/match/encryption.rb +4 -0
  73. data/match/lib/match/importer.rb +37 -20
  74. data/match/lib/match/module.rb +1 -1
  75. data/match/lib/match/nuke.rb +5 -1
  76. data/match/lib/match/options.rb +18 -0
  77. data/match/lib/match/runner.rb +4 -0
  78. data/match/lib/match/setup.rb +1 -1
  79. data/match/lib/match/storage.rb +4 -0
  80. data/match/lib/match/storage/google_cloud_storage.rb +2 -2
  81. data/match/lib/match/storage/s3_storage.rb +167 -0
  82. data/pilot/lib/pilot/build_manager.rb +24 -7
  83. data/pilot/lib/pilot/options.rb +8 -0
  84. data/produce/lib/produce/developer_center.rb +11 -2
  85. data/produce/lib/produce/itunes_connect.rb +11 -3
  86. data/produce/lib/produce/options.rb +12 -0
  87. data/scan/lib/scan/options.rb +10 -0
  88. data/scan/lib/scan/runner.rb +9 -7
  89. data/scan/lib/scan/test_command_generator.rb +11 -4
  90. data/screengrab/lib/screengrab/runner.rb +32 -19
  91. data/snapshot/lib/snapshot/fixes/simulator_shared_pasteboard.rb +16 -0
  92. data/snapshot/lib/snapshot/reports_generator.rb +4 -0
  93. data/snapshot/lib/snapshot/simulator_launchers/simulator_launcher_base.rb +2 -0
  94. data/spaceship/lib/spaceship/connect_api/models/app.rb +11 -0
  95. data/spaceship/lib/spaceship/connect_api/models/build.rb +1 -2
  96. data/spaceship/lib/spaceship/connect_api/models/certificate.rb +2 -0
  97. data/spaceship/lib/spaceship/connect_api/testflight/testflight.rb +23 -0
  98. data/spaceship/lib/spaceship/portal/app_service.rb +2 -2
  99. data/spaceship/lib/spaceship/portal/portal_client.rb +13 -0
  100. data/spaceship/lib/spaceship/tunes/app_version.rb +6 -1
  101. data/spaceship/lib/spaceship/tunes/application.rb +2 -1
  102. data/spaceship/lib/spaceship/tunes/tunes_client.rb +2 -2
  103. data/spaceship/lib/spaceship/two_step_or_factor_client.rb +52 -16
  104. data/supply/lib/supply/client.rb +4 -4
  105. data/supply/lib/supply/setup.rb +5 -3
  106. metadata +37 -16
@@ -118,9 +118,17 @@ module Pilot
118
118
 
119
119
  # Get latest uploaded build if no build specified
120
120
  if build.nil?
121
- UI.important("No build specified - fetching latest build")
121
+ app_version = config[:app_version]
122
+ build_number = config[:build_number]
123
+ if build_number.nil?
124
+ if app_version.nil?
125
+ UI.important("No build specified - fetching latest build")
126
+ else
127
+ UI.important("No build specified - fetching latest build for version #{app_version}")
128
+ end
129
+ end
122
130
  platform = Spaceship::ConnectAPI::Platform.map(fetch_app_platform)
123
- build ||= Spaceship::ConnectAPI::Build.all(app_id: app.id, sort: "-uploadedDate", platform: platform, limit: 1).first
131
+ build ||= Spaceship::ConnectAPI::Build.all(app_id: app.id, version: app_version, build_number: build_number, sort: "-uploadedDate", platform: platform, limit: 1).first
124
132
  end
125
133
 
126
134
  # Verify the build has all the includes that we need
@@ -207,8 +215,11 @@ module Pilot
207
215
  end
208
216
 
209
217
  def update_beta_app_meta(options, build)
210
- # Setting account required wth AppStore Connect API
211
- update_review_detail(build, { demo_account_required: options[:demo_account_required] })
218
+ # If demo_account_required is a parameter, it should added into beta_app_review_info
219
+ unless options[:demo_account_required].nil?
220
+ options[:beta_app_review_info] = {} if options[:beta_app_review_info].nil?
221
+ options[:beta_app_review_info][:demo_account_required] = options[:demo_account_required]
222
+ end
212
223
 
213
224
  if should_update_beta_app_review_info(options)
214
225
  update_review_detail(build, options[:beta_app_review_info])
@@ -481,12 +492,18 @@ module Pilot
481
492
  end
482
493
 
483
494
  def update_build_beta_details(build, info)
484
- build_beta_detail = build.build_beta_detail
485
-
486
495
  attributes = {}
487
496
  attributes[:autoNotifyEnabled] = info[:auto_notify_enabled] if info.key?(:auto_notify_enabled)
497
+ build_beta_detail = build.build_beta_detail
488
498
 
489
- Spaceship::ConnectAPI.patch_build_beta_details(build_beta_details_id: build_beta_detail.id, attributes: attributes)
499
+ # https://github.com/fastlane/fastlane/pull/16006
500
+ if build_beta_detail
501
+ Spaceship::ConnectAPI.patch_build_beta_details(build_beta_details_id: build_beta_detail.id, attributes: attributes)
502
+ else
503
+ if attributes[:autoNotifyEnabled]
504
+ UI.important("Unable to auto notify testers as the build did not include beta detail information - this is likely a temporary issue on TestFlight.")
505
+ end
506
+ end
490
507
  end
491
508
  end
492
509
  # rubocop:enable Metrics/ClassLength
@@ -162,6 +162,14 @@ module Pilot
162
162
  env_name: "PILOT_NOTIFY_EXTERNAL_TESTERS",
163
163
  description: "Should notify external testers?",
164
164
  default_value: true),
165
+ FastlaneCore::ConfigItem.new(key: :app_version,
166
+ env_name: "PILOT_APP_VERSION",
167
+ description: "The version number of the application build to distribute. If the version number is not specified, then the most recent build uploaded to TestFlight will be distributed. If specified, the most recent build for the version number will be distributed",
168
+ optional: true),
169
+ FastlaneCore::ConfigItem.new(key: :build_number,
170
+ env_name: "PILOT_BUILD_NUMBER",
171
+ description: "The build number of the application build to distribute. If the build number is not specified, the most recent build is distributed",
172
+ optional: true),
165
173
 
166
174
  # testers
167
175
  FastlaneCore::ConfigItem.new(key: :first_name,
@@ -59,7 +59,7 @@ module Produce
59
59
  app = Spaceship.app.create!(bundle_id: app_identifier,
60
60
  name: app_name,
61
61
  enable_services: enable_services,
62
- mac: Produce.config[:platform] == "osx")
62
+ mac: platform == "osx")
63
63
 
64
64
  if app.name != Produce.config[:app_name]
65
65
  UI.important("Your app name includes non-ASCII characters, which are not supported by the Apple Developer Portal.")
@@ -122,8 +122,17 @@ module Produce
122
122
 
123
123
  private
124
124
 
125
+ def platform
126
+ # This was added to support creation of multiple platforms
127
+ # Produce::ItunesConnect can take an array of platforms to create for App Store Connect
128
+ # but the Developer Center is now platform agnostic so we choose any platform here
129
+ #
130
+ # Platform won't be needed at all in the future when this is change over to use Spaceship::ConnectAPI
131
+ (Produce.config[:platforms] || []).first || Produce.config[:platform]
132
+ end
133
+
125
134
  def app_exists?
126
- Spaceship.app.find(app_identifier, mac: Produce.config[:platform] == "osx") != nil
135
+ Spaceship.app.find(app_identifier, mac: platform == "osx") != nil
127
136
  end
128
137
 
129
138
  def login
@@ -23,6 +23,8 @@ module Produce
23
23
  else
24
24
  UI.success("Creating new app '#{Produce.config[:app_name]}' on App Store Connect")
25
25
 
26
+ platforms = Produce.config[:platforms] || [Produce.config[:platform]]
27
+
26
28
  Produce.config[:bundle_identifier_suffix] = '' unless wildcard_bundle?
27
29
  generated_app = Spaceship::Tunes::Application.create!(name: Produce.config[:app_name],
28
30
  primary_language: language,
@@ -30,7 +32,7 @@ module Produce
30
32
  bundle_id: app_identifier,
31
33
  bundle_id_suffix: Produce.config[:bundle_identifier_suffix],
32
34
  company_name: Produce.config[:company_name],
33
- platform: Produce.config[:platform],
35
+ platforms: platforms,
34
36
  itunes_connect_users: Produce.config[:itc_users])
35
37
 
36
38
  UI.crash!("Something went wrong when creating the new app on iTC") if generated_app["adamId"].to_s.empty?
@@ -51,16 +53,22 @@ module Produce
51
53
  UI.crash!("Something went wrong when creating the new app - it's not listed in the App's list") unless application
52
54
 
53
55
  UI.message("Ensuring version number")
54
- application.ensure_version!(Produce.config[:app_version], platform: Produce.config[:platform]) if Produce.config[:app_version]
56
+ platforms.each do |platform|
57
+ application.ensure_version!(Produce.config[:app_version], platform: platform) if Produce.config[:app_version]
58
+ end
55
59
 
56
60
  UI.success("Successfully created new app '#{Produce.config[:app_name]}' on App Store Connect with ID #{application.apple_id}")
57
61
  end
58
62
 
59
- return Spaceship::Tunes::Application.find(@full_bundle_identifier, mac: Produce.config[:platform] == "osx").apple_id
63
+ return Spaceship::Tunes::Application.find(@full_bundle_identifier, mac: platform == "osx").apple_id
60
64
  end
61
65
 
62
66
  private
63
67
 
68
+ def platform
69
+ (Produce.config[:platforms] || []).first || Produce.config[:platform]
70
+ end
71
+
64
72
  def fetch_application
65
73
  Spaceship::Tunes::Application.find(@full_bundle_identifier)
66
74
  end
@@ -50,11 +50,23 @@ module Produce
50
50
  short_option: "-j",
51
51
  env_name: "PRODUCE_PLATFORM",
52
52
  description: "The platform to use (optional)",
53
+ conflicting_options: [:platforms],
53
54
  optional: true,
54
55
  default_value: "ios",
55
56
  verify_block: proc do |value|
56
57
  UI.user_error!("The platform can only be ios or osx") unless %('ios', 'osx').include?(value)
57
58
  end),
59
+ FastlaneCore::ConfigItem.new(key: :platforms,
60
+ short_option: "-J",
61
+ env_name: "PRODUCE_PLATFORMS",
62
+ description: "The platforms to use (optional)",
63
+ conflicting_options: [:platform],
64
+ optional: true,
65
+ type: Array,
66
+ verify_block: proc do |values|
67
+ types = %w(ios osx)
68
+ UI.user_error!("The platform can only be #{types}") unless (values - types).empty?
69
+ end),
58
70
  FastlaneCore::ConfigItem.new(key: :language,
59
71
  short_option: "-m",
60
72
  env_name: "PRODUCE_LANGUAGE",
@@ -124,6 +124,11 @@ module Scan
124
124
  end),
125
125
 
126
126
  # other test options
127
+ FastlaneCore::ConfigItem.new(key: :testplan,
128
+ env_name: "SCAN_TESTPLAN",
129
+ description: "The testplan associated with the scheme that should be used for testing",
130
+ is_string: true,
131
+ optional: true),
127
132
  FastlaneCore::ConfigItem.new(key: :xctestrun,
128
133
  short_option: "-X",
129
134
  env_name: "SCAN_XCTESTRUN",
@@ -254,6 +259,11 @@ module Scan
254
259
  default_value: false),
255
260
 
256
261
  # concurrency
262
+ FastlaneCore::ConfigItem.new(key: :concurrent_workers,
263
+ type: Integer,
264
+ env_name: "SCAN_CONCURRENT_WORKERS",
265
+ description: "Specify the exact number of test runners that will be spawned during parallel testing. Equivalent to -parallel-testing-worker-count",
266
+ optional: true),
257
267
  FastlaneCore::ConfigItem.new(key: :max_concurrent_simulators,
258
268
  type: Integer,
259
269
  env_name: "SCAN_MAX_CONCURRENT_SIMULATORS",
@@ -25,15 +25,17 @@ module Scan
25
25
  def test_app
26
26
  force_quit_simulator_processes if Scan.config[:force_quit_simulator]
27
27
 
28
- if Scan.config[:reset_simulator]
29
- Scan.devices.each do |device|
30
- FastlaneCore::Simulator.reset(udid: device.udid)
28
+ if Scan.devices
29
+ if Scan.config[:reset_simulator]
30
+ Scan.devices.each do |device|
31
+ FastlaneCore::Simulator.reset(udid: device.udid)
32
+ end
31
33
  end
32
- end
33
34
 
34
- if Scan.config[:disable_slide_to_type]
35
- Scan.devices.each do |device|
36
- FastlaneCore::Simulator.disable_slide_to_type(udid: device.udid)
35
+ if Scan.config[:disable_slide_to_type]
36
+ Scan.devices.each do |device|
37
+ FastlaneCore::Simulator.disable_slide_to_type(udid: device.udid)
38
+ end
37
39
  end
38
40
  end
39
41
 
@@ -27,7 +27,7 @@ module Scan
27
27
  UI.user_error!("No project/workspace found")
28
28
  end
29
29
 
30
- def options
30
+ def options # rubocop:disable Metrics/PerceivedComplexity
31
31
  config = Scan.config
32
32
 
33
33
  options = []
@@ -37,11 +37,17 @@ module Scan
37
37
  options << "-toolchain '#{config[:toolchain]}'" if config[:toolchain]
38
38
  options << "-derivedDataPath '#{config[:derived_data_path]}'" if config[:derived_data_path]
39
39
  options << "-resultBundlePath '#{result_bundle_path}'" if config[:result_bundle]
40
- options << "-maximum-concurrent-test-simulator-destinations #{config[:max_concurrent_simulators]}" if config[:max_concurrent_simulators]
41
- options << "-disable-concurrent-testing" if config[:disable_concurrent_testing]
40
+ options << "-parallel-testing-worker-count #{config[:concurrent_workers]}" if config[:concurrent_workers]
41
+ if FastlaneCore::Helper.xcode_at_least?(10)
42
+ options << "-maximum-concurrent-test-simulator-destinations #{config[:max_concurrent_simulators]}" if config[:max_concurrent_simulators]
43
+ options << "-disable-concurrent-testing" if config[:disable_concurrent_testing]
44
+ end
42
45
  options << "-enableCodeCoverage #{config[:code_coverage] ? 'YES' : 'NO'}" unless config[:code_coverage].nil?
43
46
  options << "-enableAddressSanitizer #{config[:address_sanitizer] ? 'YES' : 'NO'}" unless config[:address_sanitizer].nil?
44
47
  options << "-enableThreadSanitizer #{config[:thread_sanitizer] ? 'YES' : 'NO'}" unless config[:thread_sanitizer].nil?
48
+ if FastlaneCore::Helper.xcode_at_least?(11)
49
+ options << "-testPlan '#{config[:testplan]}'" if config[:testplan]
50
+ end
45
51
  options << "-xctestrun '#{config[:xctestrun]}'" if config[:xctestrun]
46
52
  options << config[:xcargs] if config[:xcargs]
47
53
 
@@ -148,7 +154,8 @@ module Scan
148
154
 
149
155
  def result_bundle_path
150
156
  unless Scan.cache[:result_bundle_path]
151
- path = File.join(Scan.config[:output_directory], Scan.config[:scheme]) + ".test_result"
157
+ ext = FastlaneCore::Helper.xcode_version.to_i >= 11 ? '.xcresult' : '.test_result'
158
+ path = File.join(Scan.config[:output_directory], Scan.config[:scheme]) + ext
152
159
  if File.directory?(path)
153
160
  FileUtils.remove_dir(path)
154
161
  end
@@ -63,7 +63,7 @@ module Screengrab
63
63
 
64
64
  # Root is needed to access device paths at /data
65
65
  if @config[:use_adb_root]
66
- run_adb_command("root", print_all: false, print_command: true)
66
+ run_adb_command("-s #{device_serial} root", print_all: false, print_command: true)
67
67
  end
68
68
 
69
69
  clear_device_previous_screenshots(device_serial, device_screenshots_paths)
@@ -73,15 +73,11 @@ module Screengrab
73
73
 
74
74
  validate_apk(app_apk_path)
75
75
 
76
- enable_clean_status_bar(device_serial, app_apk_path)
77
-
78
- run_tests(device_serial, app_apk_path, tests_apk_path, test_classes_to_use, test_packages_to_use, @config[:launch_arguments])
79
-
80
- number_of_screenshots = pull_screenshots_from_device(device_serial, device_screenshots_paths, device_type_dir_name)
76
+ number_of_screenshots = run_tests(device_type_dir_name, device_screenshots_paths, device_serial, app_apk_path, tests_apk_path, test_classes_to_use, test_packages_to_use, @config[:launch_arguments])
81
77
 
82
78
  ReportsGenerator.new.generate
83
79
 
84
- UI.success("Captured #{number_of_screenshots} screenshots! 📷✨")
80
+ UI.success("Captured #{number_of_screenshots} new screenshots! 📷✨")
85
81
  end
86
82
 
87
83
  def select_device
@@ -147,10 +143,17 @@ module Screengrab
147
143
 
148
144
  def determine_internal_screenshots_paths(app_package_name, locales)
149
145
  locale_paths = locales.map do |locale|
150
- "/data/user/0/#{app_package_name}/files/#{app_package_name}/screengrab/#{locale}/images/screenshots"
151
- end
146
+ [
147
+ "/data/user/0/#{app_package_name}/files/#{app_package_name}/screengrab/#{locale}/images/screenshots",
148
+
149
+ # https://github.com/fastlane/fastlane/issues/15653#issuecomment-578541663
150
+ "/data/data/#{app_package_name}/files/#{app_package_name}/screengrab/#{locale}/images/screenshots"
151
+ ]
152
+ end.flatten
152
153
 
153
- return ["/data/data/#{app_package_name}/app_screengrab"] + locale_paths
154
+ return ["/data/data/#{app_package_name}/app_screengrab"] +
155
+ ["/data/data/#{app_package_name}/screengrab"] +
156
+ locale_paths
154
157
  end
155
158
 
156
159
  def clear_device_previous_screenshots(device_serial, device_screenshots_paths)
@@ -232,23 +235,29 @@ module Screengrab
232
235
  end
233
236
  end
234
237
 
235
- def run_tests(device_serial, app_apk_path, tests_apk_path, test_classes_to_use, test_packages_to_use, launch_arguments)
238
+ def run_tests(device_type_dir_name, device_screenshots_paths, device_serial, app_apk_path, tests_apk_path, test_classes_to_use, test_packages_to_use, launch_arguments)
236
239
  unless @config[:reinstall_app]
237
240
  install_apks(device_serial, app_apk_path, tests_apk_path)
238
241
  grant_permissions(device_serial)
242
+ enable_clean_status_bar(device_serial, app_apk_path)
239
243
  end
240
244
 
245
+ number_of_screenshots = 0
246
+
241
247
  @config[:locales].each do |locale|
242
248
  if @config[:reinstall_app]
243
249
  uninstall_apks(device_serial, @config[:app_package_name], @config[:tests_package_name])
244
250
  install_apks(device_serial, app_apk_path, tests_apk_path)
245
251
  grant_permissions(device_serial)
252
+ enable_clean_status_bar(device_serial, app_apk_path)
246
253
  end
247
- run_tests_for_locale(locale, device_serial, test_classes_to_use, test_packages_to_use, launch_arguments)
254
+ number_of_screenshots += run_tests_for_locale(device_type_dir_name, device_screenshots_paths, locale, device_serial, test_classes_to_use, test_packages_to_use, launch_arguments)
248
255
  end
256
+
257
+ number_of_screenshots
249
258
  end
250
259
 
251
- def run_tests_for_locale(locale, device_serial, test_classes_to_use, test_packages_to_use, launch_arguments)
260
+ def run_tests_for_locale(device_type_dir_name, device_screenshots_paths, locale, device_serial, test_classes_to_use, test_packages_to_use, launch_arguments)
252
261
  UI.message("Running tests for locale: #{locale}")
253
262
 
254
263
  instrument_command = ["-s #{device_serial} shell am instrument --no-window-animation -w",
@@ -271,10 +280,12 @@ module Screengrab
271
280
  UI.error("Tests failed")
272
281
  end
273
282
  end
283
+
284
+ pull_screenshots_from_device(locale, device_serial, device_screenshots_paths, device_type_dir_name)
274
285
  end
275
286
 
276
- def pull_screenshots_from_device(device_serial, device_screenshots_paths, device_type_dir_name)
277
- UI.message("Pulling captured screenshots from the device")
287
+ def pull_screenshots_from_device(locale, device_serial, device_screenshots_paths, device_type_dir_name)
288
+ UI.message("Pulling captured screenshots for locale #{locale} from the device")
278
289
  starting_screenshot_count = screenshot_file_names_in(@config[:output_directory], device_type_dir_name).length
279
290
 
280
291
  UI.verbose("Starting screenshot count is: #{starting_screenshot_count}")
@@ -285,6 +296,7 @@ module Screengrab
285
296
  Dir.mktmpdir do |tempdir|
286
297
  device_screenshots_paths.each do |device_path|
287
298
  if_device_path_exists(device_serial, device_path) do |path|
299
+ next unless path.include?(locale)
288
300
  run_adb_command("-s #{device_serial} pull #{path} #{tempdir}",
289
301
  print_all: false,
290
302
  print_command: true)
@@ -296,7 +308,7 @@ module Screengrab
296
308
  #
297
309
  # Therefore, we'll move the pulled screenshots from their genericly named folder to one named by the
298
310
  # user provided device_type option value to match the directory structure that supply expects
299
- move_pulled_screenshots(tempdir, device_type_dir_name)
311
+ move_pulled_screenshots(locale, tempdir, device_type_dir_name)
300
312
  end
301
313
 
302
314
  ending_screenshot_count = screenshot_file_names_in(@config[:output_directory], device_type_dir_name).length
@@ -305,7 +317,8 @@ module Screengrab
305
317
 
306
318
  # Because we can't guarantee the screenshot output directory will be empty when we pull, we determine
307
319
  # success based on whether there are more screenshots there than when we started.
308
- if starting_screenshot_count == ending_screenshot_count
320
+ # This is only applicable though when `clear_previous_screenshots` is set to `true`.
321
+ if starting_screenshot_count == ending_screenshot_count && @config[:clear_previous_screenshots]
309
322
  UI.error("Make sure you've used Screengrab.screenshot() in your tests and that your expected tests are being run.")
310
323
  UI.abort_with_message!("No screenshots were detected 📷❌")
311
324
  end
@@ -313,7 +326,7 @@ module Screengrab
313
326
  ending_screenshot_count - starting_screenshot_count
314
327
  end
315
328
 
316
- def move_pulled_screenshots(pull_dir, device_type_dir_name)
329
+ def move_pulled_screenshots(locale, pull_dir, device_type_dir_name)
317
330
  # Glob pattern that finds the pulled screenshots directory for each locale
318
331
  # Possible matches:
319
332
  # [pull_dir]/en-US/images/screenshots
@@ -337,7 +350,7 @@ module Screengrab
337
350
  # specific name, as expected by supply
338
351
  #
339
352
  # (Moved to: fastlane/metadata/android/en-US/images/phoneScreenshots)
340
- dest_dir = File.join(File.dirname(dest_dir), device_type_dir_name)
353
+ dest_dir = File.join(File.dirname(dest_dir), locale, 'images', device_type_dir_name)
341
354
 
342
355
  FileUtils.mkdir_p(dest_dir)
343
356
  FileUtils.cp_r(src_screenshots, dest_dir)
@@ -0,0 +1,16 @@
1
+ require_relative '../module'
2
+
3
+ module Snapshot
4
+ module Fixes
5
+ # Becoming first responder can trigger Pasteboard sync, which can stall and crash the simulator
6
+ # See https://twitter.com/steipete/status/1227551552317140992
7
+
8
+ class SharedPasteboardFix
9
+ def self.patch
10
+ UI.verbose("Patching simulator to disable Pasteboard automatic sync")
11
+
12
+ Helper.backticks("defaults write com.apple.iphonesimulator PasteboardAutomaticSync -bool false", print: FastlaneCore::Globals.verbose?)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -97,13 +97,17 @@ module Snapshot
97
97
  'iPhone SE' => "iPhone SE",
98
98
  'iPhone 4s' => "iPhone 4s (3.5-Inch)",
99
99
  'iPad 2' => 'iPad 2',
100
+ 'iPad Air (3rd generation)' => 'iPad Air (3rd generation)',
100
101
  'iPad Air 2' => 'iPad Air 2',
101
102
  'iPad Air' => 'iPad Air',
102
103
  'iPad (5th generation)' => 'iPad (5th generation)',
104
+ 'iPad (7th generation)' => 'iPad (7th generation)',
103
105
  'iPad Pro (9.7-inch)' => 'iPad Pro (9.7-inch)',
104
106
  'iPad Pro (9.7 inch)' => 'iPad Pro (9.7-inch)', # iOS 10.3.1 simulator
105
107
  'iPad Pro (10.5-inch)' => 'iPad Pro (10.5-inch)',
108
+ 'iPad Pro (11-inch) (2nd generation)' => 'iPad Pro (11-inch) (2nd generation)',
106
109
  'iPad Pro (11-inch)' => 'iPad Pro (11-inch)',
110
+ 'iPad Pro (12.9-inch) (4th generation)' => 'iPad Pro (12.9-inch) (4th generation)',
107
111
  'iPad Pro (12.9-inch) (3rd generation)' => 'iPad Pro (12.9-inch) (3rd generation)',
108
112
  'iPad Pro (12.9-inch) (2nd generation)' => 'iPad Pro (12.9-inch) (2nd generation)',
109
113
  'iPad Pro (12.9-inch)' => 'iPad Pro (12.9-inch)',
@@ -5,6 +5,7 @@ require_relative '../test_command_generator'
5
5
  require_relative '../collector'
6
6
  require_relative '../fixes/hardware_keyboard_fix'
7
7
  require_relative '../fixes/simulator_zoom_fix'
8
+ require_relative '../fixes/simulator_shared_pasteboard'
8
9
 
9
10
  module Snapshot
10
11
  class SimulatorLauncherBase
@@ -53,6 +54,7 @@ module Snapshot
53
54
 
54
55
  Fixes::SimulatorZoomFix.patch
55
56
  Fixes::HardwareKeyboardFix.patch
57
+ Fixes::SharedPasteboardFix.patch
56
58
 
57
59
  device_types.each do |type|
58
60
  if launcher_config.erase_simulator || launcher_config.localize_simulator || !launcher_config.dark_mode.nil?
@@ -103,6 +103,17 @@ module Spaceship
103
103
  resps = Spaceship::ConnectAPI.get_beta_groups(filter: filter, includes: includes, limit: limit, sort: sort).all_pages
104
104
  return resps.flat_map(&:to_models)
105
105
  end
106
+
107
+ def create_beta_group(group_name: nil, public_link_enabled: false, public_link_limit: 10_000, public_link_limit_enabled: false)
108
+ resps = Spaceship::ConnectAPI.create_beta_group(
109
+ app_id: id,
110
+ group_name: group_name,
111
+ public_link_enabled: public_link_enabled,
112
+ public_link_limit: public_link_limit,
113
+ public_link_limit_enabled: public_link_limit_enabled
114
+ ).all_pages
115
+ return resps.flat_map(&:to_models).first
116
+ end
106
117
  end
107
118
  end
108
119
  end