fastlane 2.130.0 → 2.135.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +64 -64
  3. data/cert/lib/cert/module.rb +2 -0
  4. data/cert/lib/cert/options.rb +6 -0
  5. data/cert/lib/cert/runner.rb +17 -11
  6. data/fastlane/lib/fastlane/action.rb +1 -1
  7. data/fastlane/lib/fastlane/actions/actions_helper.rb +1 -1
  8. data/fastlane/lib/fastlane/actions/app_store_build_number.rb +11 -3
  9. data/fastlane/lib/fastlane/actions/carthage.rb +7 -0
  10. data/fastlane/lib/fastlane/actions/cocoapods.rb +24 -2
  11. data/fastlane/lib/fastlane/actions/copy_artifacts.rb +1 -1
  12. data/fastlane/lib/fastlane/actions/deploygate.rb +1 -1
  13. data/fastlane/lib/fastlane/actions/docs/capture_ios_screenshots.md +1 -1
  14. data/fastlane/lib/fastlane/actions/docs/sync_code_signing.md +26 -5
  15. data/fastlane/lib/fastlane/actions/docs/upload_to_play_store.md +26 -2
  16. data/fastlane/lib/fastlane/actions/download_dsyms.rb +34 -6
  17. data/fastlane/lib/fastlane/actions/download_from_play_store.rb +1 -1
  18. data/fastlane/lib/fastlane/actions/ensure_env_vars.rb +58 -0
  19. data/fastlane/lib/fastlane/actions/get_version_number.rb +12 -3
  20. data/fastlane/lib/fastlane/actions/gradle.rb +11 -1
  21. data/fastlane/lib/fastlane/actions/onesignal.rb +59 -29
  22. data/fastlane/lib/fastlane/actions/pod_push.rb +10 -1
  23. data/fastlane/lib/fastlane/actions/register_devices.rb +1 -1
  24. data/fastlane/lib/fastlane/actions/resign.rb +2 -2
  25. data/fastlane/lib/fastlane/actions/sonar.rb +16 -0
  26. data/fastlane/lib/fastlane/actions/testfairy.rb +1 -1
  27. data/fastlane/lib/fastlane/actions/update_fastlane.rb +9 -49
  28. data/fastlane/lib/fastlane/actions/update_keychain_access_groups.rb +94 -0
  29. data/fastlane/lib/fastlane/environment_printer.rb +9 -3
  30. data/fastlane/lib/fastlane/fast_file.rb +10 -4
  31. data/fastlane/lib/fastlane/helper/crashlytics_helper.rb +1 -1
  32. data/fastlane/lib/fastlane/lane_manager.rb +1 -1
  33. data/fastlane/lib/fastlane/plugins/plugin_manager.rb +12 -2
  34. data/fastlane/lib/fastlane/plugins/template/.rubocop.yml +1 -0
  35. data/fastlane/lib/fastlane/runner.rb +2 -2
  36. data/fastlane/lib/fastlane/setup/setup_android.rb +1 -1
  37. data/fastlane/lib/fastlane/swift_fastlane_api_generator.rb +10 -3
  38. data/fastlane/lib/fastlane/swift_fastlane_function.rb +72 -3
  39. data/fastlane/lib/fastlane/swift_runner_upgrader.rb +4 -0
  40. data/fastlane/lib/fastlane/version.rb +1 -1
  41. data/fastlane/swift/Actions.swift +4 -0
  42. data/fastlane/swift/Deliverfile.swift +1 -1
  43. data/fastlane/swift/DeliverfileProtocol.swift +121 -1
  44. data/fastlane/swift/Fastlane.swift +3932 -18
  45. data/fastlane/swift/Gymfile.swift +1 -1
  46. data/fastlane/swift/GymfileProtocol.swift +81 -1
  47. data/fastlane/swift/Matchfile.swift +1 -1
  48. data/fastlane/swift/MatchfileProtocol.swift +65 -1
  49. data/fastlane/swift/Plugins.swift +4 -0
  50. data/fastlane/swift/Precheckfile.swift +1 -1
  51. data/fastlane/swift/PrecheckfileProtocol.swift +15 -2
  52. data/fastlane/swift/Scanfile.swift +1 -1
  53. data/fastlane/swift/ScanfileProtocol.swift +109 -1
  54. data/fastlane/swift/Screengrabfile.swift +1 -1
  55. data/fastlane/swift/ScreengrabfileProtocol.swift +39 -2
  56. data/fastlane/swift/Snapshotfile.swift +1 -1
  57. data/fastlane/swift/SnapshotfileProtocol.swift +71 -1
  58. data/fastlane_core/lib/fastlane_core/configuration/commander_generator.rb +3 -3
  59. data/fastlane_core/lib/fastlane_core/configuration/configuration.rb +1 -1
  60. data/fastlane_core/lib/fastlane_core/device_manager.rb +1 -1
  61. data/fastlane_core/lib/fastlane_core/helper.rb +1 -1
  62. data/fastlane_core/lib/fastlane_core/itunes_transporter.rb +1 -3
  63. data/fastlane_core/lib/fastlane_core/swag.rb +1 -1
  64. data/fastlane_core/lib/fastlane_core/ui/fastlane_runner.rb +1 -1
  65. data/fastlane_core/lib/fastlane_core/ui/implementations/shell.rb +3 -2
  66. data/frameit/lib/frameit/screenshot.rb +4 -0
  67. data/{pilot/lib/pilot/.manager.rb.swp → gym/lib/gym/.module.rb.swp} +0 -0
  68. data/gym/lib/gym/runner.rb +33 -5
  69. data/match/lib/match/generator.rb +1 -0
  70. data/match/lib/match/importer.rb +2 -2
  71. data/match/lib/match/module.rb +2 -0
  72. data/match/lib/match/nuke.rb +5 -5
  73. data/match/lib/match/options.rb +17 -0
  74. data/match/lib/match/runner.rb +10 -6
  75. data/match/lib/match/storage/git_storage.rb +8 -2
  76. data/match/lib/match/storage/google_cloud_storage.rb +85 -33
  77. data/produce/lib/produce/service.rb +7 -1
  78. data/scan/lib/scan/error_handler.rb +9 -4
  79. data/scan/lib/scan/runner.rb +1 -1
  80. data/sigh/lib/assets/resign.sh +2 -2
  81. data/sigh/lib/sigh/runner.rb +13 -5
  82. data/snapshot/lib/snapshot/options.rb +5 -0
  83. data/snapshot/lib/snapshot/reports_generator.rb +3 -0
  84. data/snapshot/lib/snapshot/simulator_launchers/launcher_configuration.rb +2 -0
  85. data/snapshot/lib/snapshot/simulator_launchers/simulator_launcher.rb +2 -2
  86. data/snapshot/lib/snapshot/simulator_launchers/simulator_launcher_base.rb +16 -1
  87. data/spaceship/lib/spaceship/client.rb +2 -2
  88. data/spaceship/lib/spaceship/connect_api/models/app.rb +6 -6
  89. data/spaceship/lib/spaceship/connect_api/models/build.rb +3 -3
  90. data/spaceship/lib/spaceship/connect_api/models/build_delivery.rb +1 -1
  91. data/spaceship/lib/spaceship/connect_api/models/bundle_id.rb +1 -1
  92. data/spaceship/lib/spaceship/connect_api/models/certificate.rb +1 -1
  93. data/spaceship/lib/spaceship/connect_api/models/device.rb +1 -1
  94. data/spaceship/lib/spaceship/connect_api/models/profile.rb +1 -1
  95. data/spaceship/lib/spaceship/portal/provisioning_profile.rb +1 -1
  96. data/spaceship/lib/spaceship/tunes/app_version.rb +4 -0
  97. data/spaceship/lib/spaceship/tunes/application.rb +4 -0
  98. data/spaceship/lib/spaceship/tunes/iap_family_details.rb +10 -2
  99. data/spaceship/lib/spaceship/tunes/tunes_client.rb +25 -0
  100. data/supply/lib/supply.rb +23 -0
  101. data/{fastlane/lib/fastlane/actions/.update_project_provisioning.rb.swp → supply/lib/supply/.client.rb.swp} +0 -0
  102. data/supply/lib/supply/.options.rb.swp +0 -0
  103. data/supply/lib/supply/.uploader.rb.swp +0 -0
  104. data/supply/lib/supply/client.rb +101 -55
  105. data/supply/lib/supply/options.rb +49 -14
  106. data/supply/lib/supply/release_listing.rb +18 -0
  107. data/supply/lib/supply/setup.rb +42 -34
  108. data/supply/lib/supply/uploader.rb +168 -93
  109. metadata +54 -53
  110. data/fastlane/lib/fastlane/actions/.hockey.rb.swp +0 -0
  111. data/fastlane/lib/fastlane/actions/.slack.rb.swp +0 -0
  112. data/fastlane/swift/FastlaneSwiftRunner/FastlaneSwiftRunner.xcodeproj/project.xcworkspace/xcuserdata/josh.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  113. data/spaceship/lib/spaceship/connect_api/.DS_Store +0 -0
@@ -37,7 +37,9 @@ module Match
37
37
  git_full_name: params[:git_full_name],
38
38
  git_user_email: params[:git_user_email],
39
39
  clone_branch_directly: params[:clone_branch_directly],
40
+ git_basic_authorization: params[:git_basic_authorization],
40
41
  type: params[:type].to_s,
42
+ generate_apple_certs: params[:generate_apple_certs],
41
43
  platform: params[:platform].to_s,
42
44
  google_cloud_bucket_name: params[:google_cloud_bucket_name].to_s,
43
45
  google_cloud_keys_file: params[:google_cloud_keys_file].to_s,
@@ -85,12 +87,14 @@ module Match
85
87
  spaceship.certificate_exists(username: params[:username], certificate_id: cert_id) if spaceship
86
88
 
87
89
  # Provisioning Profiles
88
- app_identifiers.each do |app_identifier|
89
- loop do
90
- break if fetch_provisioning_profile(params: params,
91
- certificate_id: cert_id,
92
- app_identifier: app_identifier,
93
- working_directory: storage.working_directory)
90
+ unless params[:skip_provisioning_profiles]
91
+ app_identifiers.each do |app_identifier|
92
+ loop do
93
+ break if fetch_provisioning_profile(params: params,
94
+ certificate_id: cert_id,
95
+ app_identifier: app_identifier,
96
+ working_directory: storage.working_directory)
97
+ end
94
98
  end
95
99
  end
96
100
 
@@ -17,6 +17,7 @@ module Match
17
17
  attr_accessor :clone_branch_directly
18
18
  attr_accessor :type
19
19
  attr_accessor :platform
20
+ attr_accessor :git_basic_authorization
20
21
 
21
22
  def self.configure(params)
22
23
  return self.new(
@@ -28,7 +29,8 @@ module Match
28
29
  branch: params[:git_branch],
29
30
  git_full_name: params[:git_full_name],
30
31
  git_user_email: params[:git_user_email],
31
- clone_branch_directly: params[:clone_branch_directly]
32
+ clone_branch_directly: params[:clone_branch_directly],
33
+ git_basic_authorization: params[:git_basic_authorization]
32
34
  )
33
35
  end
34
36
 
@@ -40,7 +42,8 @@ module Match
40
42
  branch: "master",
41
43
  git_full_name: nil,
42
44
  git_user_email: nil,
43
- clone_branch_directly: false)
45
+ clone_branch_directly: false,
46
+ git_basic_authorization: nil)
44
47
  self.git_url = git_url
45
48
  self.shallow_clone = shallow_clone
46
49
  self.skip_docs = skip_docs
@@ -48,6 +51,7 @@ module Match
48
51
  self.git_full_name = git_full_name
49
52
  self.git_user_email = git_user_email
50
53
  self.clone_branch_directly = clone_branch_directly
54
+ self.git_basic_authorization = git_basic_authorization
51
55
 
52
56
  self.type = type if type
53
57
  self.platform = platform if platform
@@ -65,6 +69,8 @@ module Match
65
69
  self.working_directory = Dir.mktmpdir
66
70
 
67
71
  command = "git clone #{self.git_url.shellescape} #{self.working_directory.shellescape}"
72
+ command << " -c http.extraheader='AUTHORIZATION: basic #{self.git_basic_authorization}'" unless self.git_basic_authorization.nil?
73
+
68
74
  if self.shallow_clone
69
75
  command << " --depth 1 --no-single-branch"
70
76
  elsif self.clone_branch_directly
@@ -97,6 +97,7 @@ module Match
97
97
  end
98
98
 
99
99
  ensure_bucket_is_selected
100
+ check_bucket_permissions
100
101
  end
101
102
 
102
103
  def currently_used_team_id
@@ -234,74 +235,125 @@ module Match
234
235
  end
235
236
  end
236
237
 
237
- # User doesn't seem to have provided a keys file.
238
- UI.message("Looks like you don't have a Google Cloud #{DEFAULT_KEYS_FILE_NAME.cyan} file")
239
- UI.message("If you have one, make sure to put it into the '#{Dir.pwd}' directory and call it '#{DEFAULT_KEYS_FILE_NAME.cyan}'")
238
+ # User doesn't seem to have provided a keys file
239
+ UI.message("Looks like you don't have a Google Cloud #{DEFAULT_KEYS_FILE_NAME.cyan} file yet.")
240
+ UI.message("If you have one, make sure to put it into the '#{Dir.pwd}' directory and call it '#{DEFAULT_KEYS_FILE_NAME.cyan}'.")
240
241
  unless UI.confirm("Do you want fastlane to help you to create a #{DEFAULT_KEYS_FILE_NAME} file?")
241
242
  UI.user_error!("Process stopped, run fastlane again to start things up again")
242
243
  end
243
244
 
244
- UI.message("fastlane will help you create a keys file. First, open the following website")
245
+ UI.message("fastlane will help you create a keys file. Start by opening the following website:")
245
246
  UI.message("")
246
247
  UI.message("\t\thttps://console.cloud.google.com".cyan)
247
248
  UI.message("")
248
- UI.input("Press enter once you're logged in")
249
+ UI.input("Press [Enter] once you're logged in")
249
250
 
250
- UI.message("Now it's time to generate a new JSON auth file for fastlane to access Google Cloud")
251
251
  UI.message("First, switch to the Google Cloud project you want to use.")
252
- UI.message("If you don't have one yet, create a new one and switch to it")
252
+ UI.message("If you don't have one yet, create a new one and switch to it.")
253
253
  UI.message("")
254
- UI.message("\t\thttps://console.cloud.google.com/apis/credentials".cyan)
254
+ UI.message("\t\thttps://console.cloud.google.com/projectcreate".cyan)
255
255
  UI.message("")
256
- UI.input("Ensure the right project is selected on top of the page and confirm with enter")
256
+ UI.input("Press [Enter] once you selected the right project")
257
257
 
258
- UI.message("Now create a new JSON auth file by clicking on")
258
+ UI.message("Next fastlane will show you the steps to create a keys file.")
259
+ UI.message("For this it might be useful to switch the Google Cloud interface to English.")
260
+ UI.message("Append " + "&hl=en".cyan + " to the URL and the interface should be in English.")
261
+ UI.input("Press [Enter] to continue")
262
+
263
+ UI.message("Now it's time to generate a new JSON auth file for fastlane to access Google Cloud Storage:")
259
264
  UI.message("")
260
- UI.message("\t\t 1. Create credentials".cyan)
261
- UI.message("\t\t 2. Service account key".cyan)
262
- UI.message("\t\t 3. App Engine default service account".cyan)
263
- UI.message("\t\t 4. JSON".cyan)
264
- UI.message("\t\t 5. Create".cyan)
265
+ UI.message("\t\t 1. From the side menu choose 'APIs & Services' and then 'Credentials'".cyan)
266
+ UI.message("\t\t 2. Click 'Create credentials'".cyan)
267
+ UI.message("\t\t 3. Choose 'Service account key'".cyan)
268
+ UI.message("\t\t 4. Select 'New service account'".cyan)
269
+ UI.message("\t\t 5. Enter a name and ID for the service account".cyan)
270
+ UI.message("\t\t 6. Don't give the service account a role just yet!".cyan)
271
+ UI.message("\t\t 7. Make sure the key type is set to 'JSON'".cyan)
272
+ UI.message("\t\t 8. Click 'Create'".cyan)
265
273
  UI.message("")
266
- UI.input("Confirm with enter once you created and download the JSON file")
274
+ UI.input("Confirm with [Enter] once you created and downloaded the JSON file")
267
275
 
268
276
  UI.message("Copy the file to the current directory (#{Dir.pwd})")
269
277
  UI.message("and rename it to `#{DEFAULT_KEYS_FILE_NAME.cyan}`")
270
278
  UI.message("")
271
- UI.input("Confirm with enter")
279
+ UI.input("Confirm with [Enter]")
272
280
 
273
281
  until File.exist?(DEFAULT_KEYS_FILE_NAME)
274
282
  UI.message("Make sure to place the file in '#{Dir.pwd.cyan}' and name it '#{DEFAULT_KEYS_FILE_NAME.cyan}'")
275
- UI.input("Confirm with enter")
283
+ UI.message("")
284
+ UI.input("Confirm with [Enter]")
276
285
  end
277
286
 
278
287
  UI.important("Please never add the #{DEFAULT_KEYS_FILE_NAME.cyan} file in version control.")
279
- UI.important("Instead please add the file to your .gitignore")
280
- UI.input("Confirm with enter")
288
+ UI.important("Instead please add the file to your `.gitignore` file")
289
+ UI.message("")
290
+ UI.input("Confirm with [Enter]")
281
291
 
282
292
  return DEFAULT_KEYS_FILE_NAME
283
293
  end
284
294
 
285
295
  def ensure_bucket_is_selected
286
- # In case the user didn't provide a bucket name yet, they will
287
- # be asked to provide one here
296
+ # Skip the instructions if the user provided a bucket name
297
+ return unless self.bucket_name.to_s.length == 0
298
+
299
+ created_bucket = UI.confirm("Did you already create a Google Cloud Storage bucket?")
288
300
  while self.bucket_name.to_s.length == 0
289
- # Have a nice selection of the available buckets here
290
- # This can only happen after we went through auth of Google Cloud
291
- available_bucket_identifiers = self.gc_storage.buckets.collect(&:id)
292
- if available_bucket_identifiers.count > 0
293
- @bucket_name = UI.select("What Google Cloud Storage bucket do you want to use? (you can define it using the `google_cloud_bucket_name` key)", available_bucket_identifiers)
294
- else
295
- UI.error("Looks like your Google Cloud account for the project ID '#{self.google_cloud_project_id}' doesn't")
296
- UI.error("have any available storage buckets yet. Please visit the following URL")
301
+ unless created_bucket
302
+ UI.message("Create a bucket at the following URL:")
297
303
  UI.message("")
298
304
  UI.message("\t\thttps://console.cloud.google.com/storage/browser".cyan)
299
305
  UI.message("")
300
- UI.message("and make sure to have the right project selected on top of the page")
301
- UI.message("click on " + "Create Bucket".cyan + ", choose a name and confirm")
306
+ UI.message("Make sure to select the right project at the top of the page!")
302
307
  UI.message("")
303
- UI.input("Once you're finished, please confirm with enter")
308
+ UI.message("\t\t 1. Click 'Create bucket'".cyan)
309
+ UI.message("\t\t 2. Enter a unique name".cyan)
310
+ UI.message("\t\t 3. Select a geographic location for your bucket".cyan)
311
+ UI.message("\t\t 4. Make sure the storage class is set to 'Standard'".cyan)
312
+ UI.message("\t\t 5. Click 'Create' to create the bucket".cyan)
313
+ UI.message("")
314
+ UI.input("Press [Enter] once you created a bucket")
315
+ end
316
+ bucket_name = UI.input("Enter the name of your bucket: ")
317
+
318
+ # Verify if the bucket exists
319
+ begin
320
+ bucket_exists = !self.gc_storage.bucket(bucket_name).nil?
321
+ rescue Google::Cloud::PermissionDeniedError
322
+ bucket_exists = true
323
+ end
324
+ created_bucket = bucket_exists
325
+ if bucket_exists
326
+ @bucket_name = bucket_name
327
+ else
328
+ UI.error("It looks like the bucket '#{bucket_name}' doesn't exist. Make sure to create it first.")
329
+ end
330
+ end
331
+ end
332
+
333
+ def check_bucket_permissions
334
+ bucket = nil
335
+ while bucket.nil?
336
+ begin
337
+ bucket = self.gc_storage.bucket(self.bucket_name)
338
+ rescue Google::Cloud::PermissionDeniedError
339
+ bucket = nil
304
340
  end
341
+ return if bucket.nil? == false
342
+ UI.error("Looks like your Google Cloud account for the project ID '#{self.google_cloud_project_id}' doesn't")
343
+ UI.error("have access to the storage bucket '#{self.bucket_name}'. Please visit the following URL:")
344
+ UI.message("")
345
+ UI.message("\t\thttps://console.cloud.google.com/storage/browser".cyan)
346
+ UI.message("")
347
+ UI.message("You need to give your account the correct permissions:")
348
+ UI.message("")
349
+ UI.message("\t\t 1. Click on your bucket to open it".cyan)
350
+ UI.message("\t\t 2. Click 'Permissions'".cyan)
351
+ UI.message("\t\t 3. Click 'Add members'".cyan)
352
+ UI.message("\t\t 4. Enter the email of your service account".cyan)
353
+ UI.message("\t\t 5. Set the role to 'Storage Admin'".cyan)
354
+ UI.message("\t\t 6. Click 'Save'".cyan)
355
+ UI.message("")
356
+ UI.input("Confirm with [Enter] once you're finished")
305
357
  end
306
358
  end
307
359
  end
@@ -229,7 +229,13 @@ module Produce
229
229
  UI.message("\tPush Notifications")
230
230
 
231
231
  if on
232
- app.update_service(Spaceship.app_service.push_notification.on)
232
+ # Don't enable push notifications if already enabled
233
+ # Enabling push notifications when already on revokes certs
234
+ # https://github.com/fastlane/fastlane/issues/15315
235
+ # https://github.com/fastlane/fastlane/issues/8883
236
+ unless app.details.enable_services.include?("push")
237
+ app.update_service(Spaceship.app_service.push_notification.on)
238
+ end
233
239
  else
234
240
  app.update_service(Spaceship.app_service.push_notification.off)
235
241
  end
@@ -6,8 +6,13 @@ module Scan
6
6
  class << self
7
7
  # @param [String] The output of the errored build
8
8
  # This method should raise an exception in any case, as the return code indicated a failed build
9
- def handle_build_error(output)
10
- # The order of the handling below is import
9
+ def handle_build_error(output, log_path)
10
+ # The order of the handling below is important
11
+
12
+ instruction = 'See the log'
13
+ location = Scan.config[:suppress_xcode_output] ? "here: '#{log_path}'" : "above"
14
+ details = "#{instruction} #{location}."
15
+
11
16
  case output
12
17
  when /US\-ASCII/
13
18
  print("Your shell environment is not correctly configured")
@@ -23,7 +28,7 @@ module Scan
23
28
  print("For more information visit this stackoverflow answer:")
24
29
  print("https://stackoverflow.com/a/17031697/445598")
25
30
  when /Testing failed/
26
- UI.build_failure!("Error building the application - see the log above")
31
+ UI.build_failure!("Error building the application. #{details}")
27
32
  when /Executed/, /Failing tests:/
28
33
  # this is *really* important:
29
34
  # we don't want to raise an exception here
@@ -38,7 +43,7 @@ module Scan
38
43
  # followed by a list of tests that failed.
39
44
  return
40
45
  end
41
- UI.build_failure!("Error building/testing the application - see the log above")
46
+ UI.build_failure!("Error building/testing the application. #{details}")
42
47
  end
43
48
 
44
49
  private
@@ -67,7 +67,7 @@ module Scan
67
67
  error: proc do |error_output|
68
68
  begin
69
69
  exit_status = $?.exitstatus
70
- ErrorHandler.handle_build_error(error_output)
70
+ ErrorHandler.handle_build_error(error_output, @test_command_generator.xcodebuild_log_path)
71
71
  rescue => ex
72
72
  SlackPoster.new.run({
73
73
  build_errors: 1
@@ -474,7 +474,7 @@ function resign {
474
474
  log "Profile app identifier prefix is '$APP_IDENTIFIER_PREFIX'"
475
475
  fi
476
476
 
477
- # Set new app identifer prefix if such entry exists in plist file
477
+ # Set new app identifier prefix if such entry exists in plist file
478
478
  PlistBuddy -c "Set :AppIdentifierPrefix $APP_IDENTIFIER_PREFIX." "$APP_PATH/Info.plist" 2>/dev/null
479
479
 
480
480
  TEAM_IDENTIFIER=$(PlistBuddy -c "Print :Entitlements:com.apple.developer.team-identifier" "$TEMP_DIR/profile.plist" | tr -d '\n')
@@ -690,7 +690,7 @@ function resign {
690
690
  # Get the old and new app identifier (prefix)
691
691
  APP_ID_KEY="application-identifier"
692
692
  # Extract just the identifier from the value
693
- # Use the fact that we are after some identifer, which is always at the start of the string
693
+ # Use the fact that we are after some identifier, which is always at the start of the string
694
694
  OLD_APP_ID=$(PlistBuddy -c "Print $APP_ID_KEY" "$APP_ENTITLEMENTS" | grep -E '^[A-Z0-9]*' -o | tr -d '\n')
695
695
  NEW_APP_ID=$(PlistBuddy -c "Print $APP_ID_KEY" "$PROFILE_ENTITLEMENTS" | grep -E '^[A-Z0-9]*' -o | tr -d '\n')
696
696
 
@@ -155,27 +155,35 @@ module Sigh
155
155
  case Sigh.config[:platform].to_s
156
156
  when 'ios', 'tvos'
157
157
  if profile_type == Spaceship.provisioning_profile.Development
158
- certificates = Spaceship.certificate.development.all
158
+ certificates = Spaceship.certificate.development.all +
159
+ Spaceship.certificate.apple_development.all
159
160
  elsif profile_type == Spaceship.provisioning_profile.InHouse
161
+ # Enterprise accounts don't have access to Apple Distribution certificates
160
162
  certificates = Spaceship.certificate.in_house.all
161
163
  # handles case where the desired certificate type is adhoc but the account is an enterprise account
162
164
  # the apple dev portal api has a weird quirk in it where if you query for distribution certificates
163
165
  # for enterprise accounts, you get nothing back even if they exist.
164
166
  elsif profile_type == Spaceship.provisioning_profile.AdHoc && Spaceship.client && Spaceship.client.in_house?
167
+ # Enterprise accounts don't have access to Apple Distribution certificates
165
168
  certificates = Spaceship.certificate.in_house.all
166
169
  else
167
- certificates = Spaceship.certificate.production.all # Ad hoc or App Store
170
+ # Ad hoc or App Store
171
+ certificates = Spaceship.certificate.production.all +
172
+ Spaceship.certificate.apple_distribution.all
168
173
  end
169
174
 
170
175
  when 'macos'
171
176
  if profile_type == Spaceship.provisioning_profile.Development
172
- certificates = Spaceship.certificate.mac_development.all
177
+ certificates = Spaceship.certificate.mac_development.all +
178
+ Spaceship.certificate.apple_development.all
173
179
  elsif profile_type == Spaceship.provisioning_profile.AppStore
174
- certificates = Spaceship.certificate.mac_app_distribution.all
180
+ certificates = Spaceship.certificate.mac_app_distribution.all +
181
+ Spaceship.certificate.apple_distribution.all
175
182
  elsif profile_type == Spaceship.provisioning_profile.Direct
176
183
  certificates = Spaceship.certificate.developer_id_application.all
177
184
  else
178
- certificates = Spaceship.certificate.mac_app_distribution.all
185
+ certificates = Spaceship.certificate.mac_app_distribution.all +
186
+ Spaceship.certificate.apple_distribution.all
179
187
  end
180
188
  end
181
189
 
@@ -116,6 +116,11 @@ module Snapshot
116
116
  description: "Enabling this option will configure the Simulator's system language",
117
117
  default_value: false,
118
118
  is_string: false),
119
+ FastlaneCore::ConfigItem.new(key: :dark_mode,
120
+ env_name: 'SNAPSHOT_DARK_MODE',
121
+ description: "Enabling this option will configure the Simulator to be in dark mode (false for light, true for dark)",
122
+ optional: true,
123
+ type: Boolean),
119
124
  FastlaneCore::ConfigItem.new(key: :app_identifier,
120
125
  env_name: 'SNAPSHOT_APP_IDENTIFIER',
121
126
  short_option: "-a",
@@ -77,6 +77,9 @@ module Snapshot
77
77
  {
78
78
  # snapshot in Xcode 9 saves screenshots with the SIMULATOR_DEVICE_NAME
79
79
  # which includes spaces
80
+ 'iPhone 11 Pro Max' => "iPhone 11 Pro Max",
81
+ 'iPhone 11 Pro' => "iPhone 11 Pro",
82
+ 'iPhone 11' => "iPhone 11",
80
83
  'iPhone XS Max' => "iPhone XS Max",
81
84
  'iPhone XS' => "iPhone XS",
82
85
  'iPhone XR' => "iPhone XR",
@@ -8,6 +8,7 @@ module Snapshot
8
8
  attr_accessor :clean
9
9
  attr_accessor :erase_simulator
10
10
  attr_accessor :localize_simulator
11
+ attr_accessor :dark_mode
11
12
  attr_accessor :reinstall_app
12
13
  attr_accessor :app_identifier
13
14
 
@@ -32,6 +33,7 @@ module Snapshot
32
33
  @clean = snapshot_config[:clean]
33
34
  @erase_simulator = snapshot_config[:erase_simulator]
34
35
  @localize_simulator = snapshot_config[:localize_simulator]
36
+ @dark_mode = snapshot_config[:dark_mode]
35
37
  @reinstall_app = snapshot_config[:reinstall_app]
36
38
  @app_identifier = snapshot_config[:app_identifier]
37
39
  @number_of_retries = snapshot_config[:number_of_retries]
@@ -50,7 +50,7 @@ module Snapshot
50
50
  language = language[0]
51
51
  end
52
52
 
53
- # Clear logs so subsequent xcodebuild executions dont append to old ones
53
+ # Clear logs so subsequent xcodebuild executions don't append to old ones
54
54
  log_path = xcodebuild_log_path(language: language, locale: locale)
55
55
  File.delete(log_path) if File.exist?(log_path)
56
56
 
@@ -190,7 +190,7 @@ module Snapshot
190
190
  hash[name] = ["No tests were executed"]
191
191
  else
192
192
  tests = Array(summary.data.first[:tests])
193
- hash[name] = tests.map { |test| Array(test[:failures]).map { |failure| failure[:failure_message] } }.flatten
193
+ hash[name] = tests.flat_map { |test| Array(test[:failures]).map { |failure| failure[:failure_message] } }
194
194
  end
195
195
  end
196
196
  end
@@ -55,11 +55,14 @@ module Snapshot
55
55
  Fixes::HardwareKeyboardFix.patch
56
56
 
57
57
  device_types.each do |type|
58
- if launcher_config.erase_simulator || launcher_config.localize_simulator
58
+ if launcher_config.erase_simulator || launcher_config.localize_simulator || !launcher_config.dark_mode.nil?
59
59
  erase_simulator(type)
60
60
  if launcher_config.localize_simulator
61
61
  localize_simulator(type, language, locale)
62
62
  end
63
+ unless launcher_config.dark_mode.nil?
64
+ interface_style(type, launcher_config.dark_mode)
65
+ end
63
66
  elsif launcher_config.reinstall_app
64
67
  # no need to reinstall if device has been erased
65
68
  uninstall_app(type)
@@ -124,6 +127,18 @@ module Snapshot
124
127
  end
125
128
  end
126
129
 
130
+ def interface_style(device_type, dark_mode)
131
+ device_udid = TestCommandGenerator.device_udid(device_type)
132
+ if device_udid
133
+ plist = {
134
+ UserInterfaceStyleMode: (dark_mode ? 2 : 1)
135
+ }
136
+ UI.message("Setting interface style #{device_type} (UserInterfaceStyleMode=#{dark_mode})")
137
+ plist_path = "#{ENV['HOME']}/Library/Developer/CoreSimulator/Devices/#{device_udid}/data/Library/Preferences/com.apple.uikitservices.userInterfaceStyleMode.plist"
138
+ File.write(plist_path, Plist::Emit.dump(plist))
139
+ end
140
+ end
141
+
127
142
  def copy_simulator_logs(device_names, language, locale, launch_arguments)
128
143
  return unless launcher_config.output_simulator_logs
129
144