fastlane 2.146.0 → 2.149.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +86 -86
  3. data/cert/lib/cert/commands_generator.rb +1 -0
  4. data/credentials_manager/lib/credentials_manager/cli.rb +2 -0
  5. data/deliver/lib/deliver/app_screenshot.rb +3 -3
  6. data/deliver/lib/deliver/commands_generator.rb +1 -0
  7. data/deliver/lib/deliver/html_generator.rb +2 -2
  8. data/deliver/lib/deliver/submit_for_review.rb +5 -1
  9. data/fastlane/lib/{fastlane/actions/.update_code_signing_settings.rb.swp → assets/.s3_html_template.erb.swp} +0 -0
  10. data/fastlane/lib/assets/custom_action_template.rb +6 -6
  11. data/fastlane/lib/assets/s3_html_template.erb +1 -1
  12. data/fastlane/lib/fastlane/actions/.hipchat.rb.swp +0 -0
  13. data/fastlane/lib/fastlane/actions/.slack.rb.swp +0 -0
  14. data/fastlane/lib/fastlane/actions/cocoapods.rb +1 -1
  15. data/fastlane/lib/fastlane/actions/crashlytics.rb +0 -4
  16. data/fastlane/lib/fastlane/actions/docs/build_app.md +1 -1
  17. data/fastlane/lib/fastlane/actions/docs/capture_android_screenshots.md +42 -2
  18. data/fastlane/lib/fastlane/actions/docs/capture_ios_screenshots.md +3 -1
  19. data/fastlane/lib/fastlane/actions/docs/frame_screenshots.md +1 -1
  20. data/fastlane/lib/fastlane/actions/docs/sync_code_signing.md +2 -2
  21. data/fastlane/lib/fastlane/actions/docs/upload_to_play_store.md +12 -0
  22. data/fastlane/lib/fastlane/actions/get_managed_play_store_publishing_rights.rb +1 -1
  23. data/fastlane/lib/fastlane/actions/git_branch.rb +1 -1
  24. data/fastlane/lib/fastlane/actions/hipchat.rb +1 -1
  25. data/fastlane/lib/fastlane/actions/push_to_git_remote.rb +1 -1
  26. data/fastlane/lib/fastlane/actions/set_pod_key.rb +3 -3
  27. data/fastlane/lib/fastlane/actions/slack.rb +1 -1
  28. data/fastlane/lib/fastlane/actions/slather.rb +8 -1
  29. data/fastlane/lib/fastlane/actions/swiftlint.rb +14 -0
  30. data/fastlane/lib/fastlane/actions/sync_code_signing.rb +1 -1
  31. data/fastlane/lib/fastlane/actions/testfairy.rb +18 -3
  32. data/fastlane/lib/fastlane/actions/update_code_signing_settings.rb +7 -2
  33. data/fastlane/lib/fastlane/actions/upload_symbols_to_crashlytics.rb +2 -2
  34. data/fastlane/lib/fastlane/actions/verify_xcode.rb +7 -0
  35. data/fastlane/lib/fastlane/actions/xcodebuild.rb +4 -4
  36. data/fastlane/lib/fastlane/cli_tools_distributor.rb +28 -6
  37. data/fastlane/lib/fastlane/commands_generator.rb +5 -2
  38. data/fastlane/lib/fastlane/documentation/actions_list.rb +1 -1
  39. data/fastlane/lib/fastlane/helper/lane_helper.rb +13 -0
  40. data/fastlane/lib/fastlane/lane_manager.rb +0 -10
  41. data/fastlane/lib/fastlane/plugins/plugin_manager.rb +3 -3
  42. data/fastlane/lib/fastlane/plugins/template/.github/workflows/test.yml +29 -0
  43. data/fastlane/lib/fastlane/swift_fastlane_function.rb +15 -2
  44. data/fastlane/lib/fastlane/swift_lane_manager.rb +0 -8
  45. data/fastlane/lib/fastlane/version.rb +1 -1
  46. data/fastlane/swift/Deliverfile.swift +1 -1
  47. data/fastlane/swift/Fastlane.swift +130 -26
  48. data/fastlane/swift/Gymfile.swift +1 -1
  49. data/fastlane/swift/GymfileProtocol.swift +1 -1
  50. data/fastlane/swift/LaneFileProtocol.swift +5 -2
  51. data/fastlane/swift/Matchfile.swift +1 -1
  52. data/fastlane/swift/MatchfileProtocol.swift +9 -1
  53. data/fastlane/swift/Precheckfile.swift +1 -1
  54. data/fastlane/swift/Scanfile.swift +1 -1
  55. data/fastlane/swift/ScanfileProtocol.swift +15 -3
  56. data/fastlane/swift/Screengrabfile.swift +1 -1
  57. data/fastlane/swift/Snapshotfile.swift +1 -1
  58. data/fastlane/swift/SnapshotfileProtocol.swift +25 -1
  59. data/fastlane_core/lib/fastlane_core/helper.rb +17 -0
  60. data/fastlane_core/lib/fastlane_core/keychain_importer.rb +46 -2
  61. data/fastlane_core/lib/fastlane_core/project.rb +1 -0
  62. data/frameit/lib/frameit/commands_generator.rb +1 -0
  63. data/frameit/lib/frameit/device_types.rb +10 -0
  64. data/frameit/lib/frameit/options.rb +5 -2
  65. data/frameit/lib/frameit/runner.rb +5 -0
  66. data/frameit/lib/frameit/screenshot.rb +1 -0
  67. data/gym/lib/gym/generators/package_command_generator.rb +4 -0
  68. data/gym/lib/gym/generators/package_command_generator_xcode7.rb +4 -0
  69. data/gym/lib/gym/options.rb +1 -1
  70. data/gym/lib/gym/runner.rb +14 -0
  71. data/match/lib/match/change_password.rb +1 -18
  72. data/match/lib/match/commands_generator.rb +1 -0
  73. data/match/lib/match/encryption/openssl.rb +1 -1
  74. data/match/lib/match/generator.rb +7 -2
  75. data/match/lib/match/nuke.rb +21 -16
  76. data/match/lib/match/options.rb +23 -1
  77. data/match/lib/match/storage/git_storage.rb +4 -0
  78. data/match/lib/match/storage/google_cloud_storage.rb +4 -0
  79. data/match/lib/match/storage/interface.rb +4 -0
  80. data/match/lib/match/storage/s3_storage.rb +4 -0
  81. data/match/lib/match/utils.rb +1 -1
  82. data/pem/lib/pem/commands_generator.rb +1 -0
  83. data/pilot/lib/pilot/build_manager.rb +23 -7
  84. data/pilot/lib/pilot/options.rb +5 -0
  85. data/produce/lib/produce/commands_generator.rb +1 -0
  86. data/scan/lib/scan/.options.rb.swp +0 -0
  87. data/scan/lib/scan/detect_values.rb +3 -0
  88. data/scan/lib/scan/options.rb +26 -3
  89. data/scan/lib/scan/runner.rb +2 -0
  90. data/scan/lib/scan/test_command_generator.rb +7 -2
  91. data/scan/lib/scan/test_result_parser.rb +9 -2
  92. data/screengrab/lib/screengrab/runner.rb +10 -9
  93. data/sigh/lib/sigh/commands_generator.rb +1 -0
  94. data/sigh/lib/sigh/options.rb +7 -1
  95. data/sigh/lib/sigh/runner.rb +2 -1
  96. data/snapshot/lib/assets/SnapfileTemplate +3 -0
  97. data/snapshot/lib/assets/SnapshotHelper.swift +12 -33
  98. data/snapshot/lib/snapshot/detect_values.rb +15 -0
  99. data/snapshot/lib/snapshot/options.rb +42 -0
  100. data/snapshot/lib/snapshot/reports_generator.rb +1 -1
  101. data/snapshot/lib/snapshot/simulator_launchers/launcher_configuration.rb +2 -0
  102. data/snapshot/lib/snapshot/simulator_launchers/simulator_launcher.rb +4 -0
  103. data/snapshot/lib/snapshot/simulator_launchers/simulator_launcher_base.rb +24 -1
  104. data/snapshot/lib/snapshot/test_command_generator.rb +8 -3
  105. data/snapshot/lib/snapshot/test_command_generator_base.rb +10 -1
  106. data/spaceship/lib/spaceship/base.rb +1 -1
  107. data/spaceship/lib/spaceship/client.rb +9 -1
  108. data/spaceship/lib/spaceship/commands_generator.rb +1 -0
  109. data/spaceship/lib/spaceship/connect_api/model.rb +6 -0
  110. data/spaceship/lib/spaceship/connect_api/models/build.rb +4 -0
  111. data/spaceship/lib/spaceship/errors.rb +3 -0
  112. data/spaceship/lib/spaceship/tunes/iap.rb +15 -0
  113. data/spaceship/lib/spaceship/tunes/tunes_client.rb +14 -0
  114. data/supply/lib/supply/commands_generator.rb +1 -0
  115. data/supply/lib/supply/options.rb +9 -0
  116. data/supply/lib/supply/uploader.rb +4 -0
  117. metadata +47 -30
@@ -148,6 +148,8 @@ module Scan
148
148
  end
149
149
 
150
150
  def test_results
151
+ return if Scan.config[:disable_xcpretty]
152
+
151
153
  temp_junit_report = Scan.cache[:temp_junit_report]
152
154
  return File.read(temp_junit_report) if temp_junit_report && File.file?(temp_junit_report)
153
155
 
@@ -37,8 +37,8 @@ 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 << "-parallel-testing-worker-count #{config[:concurrent_workers]}" if config[:concurrent_workers]
41
40
  if FastlaneCore::Helper.xcode_at_least?(10)
41
+ options << "-parallel-testing-worker-count #{config[:concurrent_workers]}" if config[:concurrent_workers]
42
42
  options << "-maximum-concurrent-test-simulator-destinations #{config[:max_concurrent_simulators]}" if config[:max_concurrent_simulators]
43
43
  options << "-disable-concurrent-testing" if config[:disable_concurrent_testing]
44
44
  end
@@ -47,6 +47,11 @@ module Scan
47
47
  options << "-enableThreadSanitizer #{config[:thread_sanitizer] ? 'YES' : 'NO'}" unless config[:thread_sanitizer].nil?
48
48
  if FastlaneCore::Helper.xcode_at_least?(11)
49
49
  options << "-testPlan '#{config[:testplan]}'" if config[:testplan]
50
+
51
+ # detect_values will ensure that these values are present as Arrays if
52
+ # they are present at all
53
+ options += config[:only_test_configurations].map { |name| "-only-test-configuration '#{name}'" } if config[:only_test_configurations]
54
+ options += config[:skip_test_configurations].map { |name| "-skip-test-configuration '#{name}'" } if config[:skip_test_configurations]
50
55
  end
51
56
  options << "-xctestrun '#{config[:xctestrun]}'" if config[:xctestrun]
52
57
  options << config[:xcargs] if config[:xcargs]
@@ -85,7 +90,7 @@ module Scan
85
90
  def pipe
86
91
  pipe = ["| tee '#{xcodebuild_log_path}'"]
87
92
 
88
- if Scan.config[:output_style] == 'raw'
93
+ if Scan.config[:disable_xcpretty] || Scan.config[:output_style] == 'raw'
89
94
  return pipe
90
95
  end
91
96
 
@@ -3,6 +3,13 @@ require_relative 'module'
3
3
  module Scan
4
4
  class TestResultParser
5
5
  def parse_result(output)
6
+ unless output
7
+ return {
8
+ tests: 0,
9
+ failures: 0
10
+ }
11
+ end
12
+
6
13
  # e.g. ...<testsuites tests='2' failures='1'>...
7
14
  matched = output.scan(/<testsuites\b(?=[^<>]*\s+tests='(\d+)')(?=[^<>]*\s+failures='(\d+)')[^<>]+>/)
8
15
 
@@ -10,13 +17,13 @@ module Scan
10
17
  tests = matched[0][0].to_i
11
18
  failures = matched[0][1].to_i
12
19
 
13
- return {
20
+ {
14
21
  tests: tests,
15
22
  failures: failures
16
23
  }
17
24
  else
18
25
  UI.error("Couldn't parse the number of tests from the output")
19
- return {
26
+ {
20
27
  tests: 0,
21
28
  failures: 0
22
29
  }
@@ -57,7 +57,7 @@ module Screengrab
57
57
  device_serial = select_device
58
58
 
59
59
  device_screenshots_paths = [
60
- determine_external_screenshots_path(device_serial),
60
+ determine_external_screenshots_path(device_serial, @config[:locales]),
61
61
  determine_internal_screenshots_paths(@config[:app_package_name], @config[:locales])
62
62
  ].flatten
63
63
 
@@ -130,7 +130,7 @@ module Screengrab
130
130
  Dir.glob(File.join(output_directory, '**', device_type, '*.png'), File::FNM_CASEFOLD)
131
131
  end
132
132
 
133
- def determine_external_screenshots_path(device_serial)
133
+ def determine_external_screenshots_path(device_serial, locales)
134
134
  # macOS evaluates $foo in `echo $foo` before executing the command,
135
135
  # Windows doesn't - hence the double backslash vs. single backslash
136
136
  command = Helper.windows? ? "shell echo \$EXTERNAL_STORAGE " : "shell echo \\$EXTERNAL_STORAGE"
@@ -138,22 +138,23 @@ module Screengrab
138
138
  print_all: true,
139
139
  print_command: true)
140
140
  device_ext_storage = device_ext_storage.strip
141
- File.join(device_ext_storage, @config[:app_package_name], 'screengrab')
141
+ return locales.map do |locale|
142
+ File.join(device_ext_storage, @config[:app_package_name], 'screengrab', locale, "images", "screenshots")
143
+ end.flatten
142
144
  end
143
145
 
144
146
  def determine_internal_screenshots_paths(app_package_name, locales)
145
- locale_paths = locales.map do |locale|
147
+ return locales.map do |locale|
146
148
  [
147
149
  "/data/user/0/#{app_package_name}/files/#{app_package_name}/screengrab/#{locale}/images/screenshots",
148
150
 
149
151
  # https://github.com/fastlane/fastlane/issues/15653#issuecomment-578541663
150
- "/data/data/#{app_package_name}/files/#{app_package_name}/screengrab/#{locale}/images/screenshots"
152
+ "/data/data/#{app_package_name}/files/#{app_package_name}/screengrab/#{locale}/images/screenshots",
153
+
154
+ "/data/data/#{app_package_name}/app_screengrab/#{locale}/images/screenshots",
155
+ "/data/data/#{app_package_name}/screengrab/#{locale}/images/screenshots"
151
156
  ]
152
157
  end.flatten
153
-
154
- return ["/data/data/#{app_package_name}/app_screengrab"] +
155
- ["/data/data/#{app_package_name}/screengrab"] +
156
- locale_paths
157
158
  end
158
159
 
159
160
  def clear_device_previous_screenshots(device_serial, device_screenshots_paths)
@@ -26,6 +26,7 @@ module Sigh
26
26
  program :help_formatter, :compact
27
27
 
28
28
  global_option('--verbose') { FastlaneCore::Globals.verbose = true }
29
+ global_option('--env STRING[,STRING2]', String, 'Add environment(s) to use with `dotenv`')
29
30
 
30
31
  command :renew do |c|
31
32
  c.syntax = 'fastlane sigh renew'
@@ -153,7 +153,13 @@ module Sigh
153
153
  env_name: "SIGH_PROVISIONING_PROFILE_TEMPLATE_NAME",
154
154
  description: "The name of provisioning profile template. If the developer account has provisioning profile templates (aka: custom entitlements), the template name can be found by inspecting the Entitlements drop-down while creating/editing a provisioning profile (e.g. \"Apple Pay Pass Suppression Development\")",
155
155
  optional: true,
156
- default_value: nil)
156
+ default_value: nil),
157
+ FastlaneCore::ConfigItem.new(key: :fail_on_name_taken,
158
+ env_name: "SIGH_FAIL_ON_NAME_TAKEN",
159
+ description: "Should the command fail if it was about to create a duplicate of an existing provisioning profile. It can happen due to issues on Apple Developer Portal, when profile to be recreated was not properly deleted first",
160
+ optional: true,
161
+ is_string: false,
162
+ default_value: false)
157
163
  ]
158
164
  end
159
165
  end
@@ -125,7 +125,8 @@ module Sigh
125
125
  name = Sigh.config[:provisioning_name] || [bundle_id, profile_type.pretty_type].join(' ')
126
126
 
127
127
  unless Sigh.config[:skip_fetch_profiles]
128
- if Spaceship.provisioning_profile.all.find { |p| p.name == name }
128
+ if Spaceship.provisioning_profile.all(mac: Sigh.config[:platform].to_s == 'macos').find { |p| p.name == name }
129
+ UI.user_error!("The name '#{name}' is already taken, and fail_on_name_taken is true") if Sigh.config[:fail_on_name_taken]
129
130
  UI.error("The name '#{name}' is already taken, using another one.")
130
131
  name += " #{Time.now.to_i}"
131
132
  end
@@ -27,6 +27,9 @@
27
27
  # remove the '#' to clear all previously generated screenshots before creating new ones
28
28
  # clear_previous_screenshots(true)
29
29
 
30
+ # Remove the '#' to set the status bar to 9:41 AM, and show full battery and reception.
31
+ # override_status_bar(true)
32
+
30
33
  # Arguments to pass to the app on launch. See https://docs.fastlane.tools/actions/snapshot/#launch-arguments
31
34
  # launch_arguments(["-favColor red"])
32
35
 
@@ -38,22 +38,13 @@ func snapshot(_ name: String, timeWaitingForIdle timeout: TimeInterval = 20) {
38
38
  }
39
39
 
40
40
  enum SnapshotError: Error, CustomDebugStringConvertible {
41
- case cannotDetectUser
42
- case cannotFindHomeDirectory
43
41
  case cannotFindSimulatorHomeDirectory
44
- case cannotAccessSimulatorHomeDirectory(String)
45
42
  case cannotRunOnPhysicalDevice
46
43
 
47
44
  var debugDescription: String {
48
45
  switch self {
49
- case .cannotDetectUser:
50
- return "Couldn't find Snapshot configuration files - can't detect current user "
51
- case .cannotFindHomeDirectory:
52
- return "Couldn't find Snapshot configuration files - can't detect `Users` dir"
53
46
  case .cannotFindSimulatorHomeDirectory:
54
47
  return "Couldn't find simulator home location. Please, check SIMULATOR_HOST_HOME env variable."
55
- case .cannotAccessSimulatorHomeDirectory(let simulatorHostHome):
56
- return "Can't prepare environment. Simulator home location is inaccessible. Does \(simulatorHostHome) exist?"
57
48
  case .cannotRunOnPhysicalDevice:
58
49
  return "Can't use Snapshot on a physical device."
59
50
  }
@@ -75,7 +66,7 @@ open class Snapshot: NSObject {
75
66
  Snapshot.waitForAnimations = waitForAnimations
76
67
 
77
68
  do {
78
- let cacheDir = try pathPrefix()
69
+ let cacheDir = try getCacheDirectory()
79
70
  Snapshot.cacheDirectory = cacheDir
80
71
  setLanguage(app)
81
72
  setLocale(app)
@@ -206,34 +197,22 @@ open class Snapshot: NSObject {
206
197
  _ = XCTWaiter.wait(for: [networkLoadingIndicatorDisappeared], timeout: timeout)
207
198
  }
208
199
 
209
- class func pathPrefix() throws -> URL? {
210
- let homeDir: URL
200
+ class func getCacheDirectory() throws -> URL {
201
+ let cachePath = "Library/Caches/tools.fastlane"
211
202
  // on OSX config is stored in /Users/<username>/Library
212
203
  // and on iOS/tvOS/WatchOS it's in simulator's home dir
213
204
  #if os(OSX)
214
- guard let user = ProcessInfo().environment["USER"] else {
215
- throw SnapshotError.cannotDetectUser
205
+ let homeDir = URL(fileURLWithPath: NSHomeDirectory())
206
+ return homeDir.appendingPathComponent(cachePath)
207
+ #elseif arch(i386) || arch(x86_64)
208
+ guard let simulatorHostHome = ProcessInfo().environment["SIMULATOR_HOST_HOME"] else {
209
+ throw SnapshotError.cannotFindSimulatorHomeDirectory
216
210
  }
217
-
218
- guard let usersDir = FileManager.default.urls(for: .userDirectory, in: .localDomainMask).first else {
219
- throw SnapshotError.cannotFindHomeDirectory
220
- }
221
-
222
- homeDir = usersDir.appendingPathComponent(user)
211
+ let homeDir = URL(fileURLWithPath: simulatorHostHome)
212
+ return homeDir.appendingPathComponent(cachePath)
223
213
  #else
224
- #if arch(i386) || arch(x86_64)
225
- guard let simulatorHostHome = ProcessInfo().environment["SIMULATOR_HOST_HOME"] else {
226
- throw SnapshotError.cannotFindSimulatorHomeDirectory
227
- }
228
- guard let homeDirUrl = URL(string: simulatorHostHome) else {
229
- throw SnapshotError.cannotAccessSimulatorHomeDirectory(simulatorHostHome)
230
- }
231
- homeDir = URL(fileURLWithPath: homeDirUrl.path)
232
- #else
233
- throw SnapshotError.cannotRunOnPhysicalDevice
234
- #endif
214
+ throw SnapshotError.cannotRunOnPhysicalDevice
235
215
  #endif
236
- return homeDir.appendingPathComponent("Library/Caches/tools.fastlane")
237
216
  }
238
217
  }
239
218
 
@@ -300,4 +279,4 @@ private extension CGFloat {
300
279
 
301
280
  // Please don't remove the lines below
302
281
  // They are used to detect outdated configuration files
303
- // SnapshotHelperVersion [1.21]
282
+ // SnapshotHelperVersion [1.22]
@@ -30,6 +30,9 @@ module Snapshot
30
30
 
31
31
  Snapshot.project.select_scheme(preferred_to_include: "UITests")
32
32
 
33
+ coerce_to_array_of_strings(:only_testing)
34
+ coerce_to_array_of_strings(:skip_testing)
35
+
33
36
  # Devices
34
37
  if config[:devices].nil? && !Snapshot.project.mac?
35
38
  config[:devices] = []
@@ -67,5 +70,17 @@ module Snapshot
67
70
  config[:devices] = ["Mac"]
68
71
  end
69
72
  end
73
+
74
+ def self.coerce_to_array_of_strings(config_key)
75
+ config_value = Snapshot.config[config_key]
76
+
77
+ return if config_value.nil?
78
+
79
+ # splitting on comma allows us to support comma-separated lists of values
80
+ # from the command line, even though the ConfigItem is not defined as an
81
+ # Array type
82
+ config_value = config_value.split(',') unless config_value.kind_of?(Array)
83
+ Snapshot.config[config_key] = config_value.map(&:to_s)
84
+ end
70
85
  end
71
86
  end
@@ -5,6 +5,11 @@ require_relative 'module'
5
5
 
6
6
  module Snapshot
7
7
  class Options
8
+ def self.verify_type(item_name, acceptable_types, value)
9
+ type_ok = [Array, String].any? { |type| value.kind_of?(type) }
10
+ UI.user_error!("'#{item_name}' should be of type #{acceptable_types.join(' or ')} but found: #{value.class.name}") unless type_ok
11
+ end
12
+
8
13
  def self.available_options
9
14
  output_directory = (File.directory?("fastlane") ? "fastlane/screenshots" : "screenshots")
10
15
 
@@ -111,6 +116,11 @@ module Snapshot
111
116
  description: "Enabling this option will automatically erase the simulator before running the application",
112
117
  default_value: false,
113
118
  is_string: false),
119
+ FastlaneCore::ConfigItem.new(key: :override_status_bar,
120
+ env_name: 'SNAPSHOT_OVERRIDE_STATUS_BAR',
121
+ description: "Enabling this option wil automatically override the status bar to show 9:41 AM, full battery, and full reception",
122
+ default_value: false,
123
+ is_string: false),
114
124
  FastlaneCore::ConfigItem.new(key: :localize_simulator,
115
125
  env_name: 'SNAPSHOT_LOCALIZE_SIMULATOR',
116
126
  description: "Enabling this option will configure the Simulator's system language",
@@ -142,6 +152,12 @@ module Snapshot
142
152
  description: "A list of videos that should be added to the simulator before running the application",
143
153
  type: Array,
144
154
  optional: true),
155
+ FastlaneCore::ConfigItem.new(key: :html_template,
156
+ env_name: 'SNAPSHOT_HTML_TEMPLATE',
157
+ short_option: "-e",
158
+ description: "A path to screenshots.html template",
159
+ default_value: File.join(Snapshot::ROOT, "lib", "snapshot/page.html.erb"),
160
+ optional: true),
145
161
 
146
162
  # Everything around building
147
163
  FastlaneCore::ConfigItem.new(key: :buildlog_path,
@@ -232,6 +248,32 @@ module Snapshot
232
248
  env_name: "SNAPSHOT_CLONED_SOURCE_PACKAGES_PATH",
233
249
  description: "Sets a custom path for Swift Package Manager dependencies",
234
250
  type: String,
251
+ optional: true),
252
+ FastlaneCore::ConfigItem.new(key: :testplan,
253
+ env_name: "SNAPSHOT_TESTPLAN",
254
+ description: "The testplan associated with the scheme that should be used for testing",
255
+ is_string: true,
256
+ optional: true),
257
+ FastlaneCore::ConfigItem.new(key: :only_testing,
258
+ env_name: "SNAPSHOT_ONLY_TESTING",
259
+ description: "Array of strings matching Test Bundle/Test Suite/Test Cases to run",
260
+ optional: true,
261
+ is_string: false,
262
+ verify_block: proc do |value|
263
+ verify_type('only_testing', [Array, String], value)
264
+ end),
265
+ FastlaneCore::ConfigItem.new(key: :skip_testing,
266
+ env_name: "SNAPSHOT_SKIP_TESTING",
267
+ description: "Array of strings matching Test Bundle/Test Suite/Test Cases to skip",
268
+ optional: true,
269
+ is_string: false,
270
+ verify_block: proc do |value|
271
+ verify_type('skip_testing', [Array, String], value)
272
+ end),
273
+ FastlaneCore::ConfigItem.new(key: :disable_xcpretty,
274
+ env_name: "SNAPSHOT_DISABLE_XCPRETTY",
275
+ description: "Disable xcpretty formatting of build",
276
+ type: Boolean,
235
277
  optional: true)
236
278
  ]
237
279
  end
@@ -36,7 +36,7 @@ module Snapshot
36
36
  end
37
37
  end
38
38
 
39
- html_path = File.join(Snapshot::ROOT, "lib", "snapshot/page.html.erb")
39
+ html_path = Snapshot.config[:html_template]
40
40
  html = ERB.new(File.read(html_path)).result(binding) # https://web.archive.org/web/20160430190141/www.rrn.dk/rubys-erb-templating-system
41
41
 
42
42
  export_path = "#{screens_path}/screenshots.html"
@@ -12,6 +12,7 @@ module Snapshot
12
12
  attr_accessor :reinstall_app
13
13
  attr_accessor :app_identifier
14
14
  attr_accessor :disable_slide_to_type
15
+ attr_accessor :override_status_bar
15
16
 
16
17
  # xcode 8
17
18
  attr_accessor :number_of_retries
@@ -43,6 +44,7 @@ module Snapshot
43
44
  @output_directory = snapshot_config[:output_directory]
44
45
  @concurrent_simulators = snapshot_config[:concurrent_simulators]
45
46
  @disable_slide_to_type = snapshot_config[:disable_slide_to_type]
47
+ @override_status_bar = snapshot_config[:override_status_bar]
46
48
 
47
49
  launch_arguments = Array(snapshot_config[:launch_arguments])
48
50
  # if more than 1 set of arguments, use a tuple with an index
@@ -89,10 +89,14 @@ module Snapshot
89
89
  log_path: xcodebuild_log_path(language: language, locale: locale)
90
90
  )
91
91
 
92
+ devices.each { |device_type| override_status_bar(device_type) } if launcher_config.override_status_bar
93
+
92
94
  UI.important("Running snapshot on: #{devices.join(', ')}")
93
95
 
94
96
  execute(command: command, language: language, locale: locale, launch_args: launch_arguments, devices: devices)
95
97
 
98
+ devices.each { |device_type| clear_status_bar(device_type) } if launcher_config.override_status_bar
99
+
96
100
  return copy_screenshots(language: language, locale: locale, launch_args: launch_arguments)
97
101
  end
98
102
 
@@ -1,4 +1,5 @@
1
1
  require 'plist'
2
+ require 'time'
2
3
 
3
4
  require_relative '../module'
4
5
  require_relative '../test_command_generator'
@@ -58,7 +59,9 @@ module Snapshot
58
59
 
59
60
  device_types.each do |type|
60
61
  if launcher_config.erase_simulator || launcher_config.localize_simulator || !launcher_config.dark_mode.nil?
61
- erase_simulator(type)
62
+ if launcher_config.erase_simulator
63
+ erase_simulator(type)
64
+ end
62
65
  if launcher_config.localize_simulator
63
66
  localize_simulator(type, language, locale)
64
67
  end
@@ -102,6 +105,26 @@ module Snapshot
102
105
  end
103
106
  end
104
107
 
108
+ def override_status_bar(device_type)
109
+ device_udid = TestCommandGenerator.device_udid(device_type)
110
+
111
+ UI.message("Launch Simulator #{device_type}")
112
+ Helper.backticks("xcrun instruments -w #{device_udid} &> /dev/null")
113
+
114
+ UI.message("Overriding Status Bar")
115
+
116
+ # The time needs to be passed as ISO8601 so the simulator formats it correctly
117
+ time = Time.new(2007, 1, 9, 9, 41, 0)
118
+ Helper.backticks("xcrun simctl status_bar #{device_udid} override --time #{time.iso8601} --dataNetwork wifi --wifiMode active --wifiBars 3 --cellularMode active --cellularBars 4 --batteryState charged --batteryLevel 100 &> /dev/null")
119
+ end
120
+
121
+ def clear_status_bar(device_type)
122
+ device_udid = TestCommandGenerator.device_udid(device_type)
123
+
124
+ UI.message("Clearing Status Bar Override")
125
+ Helper.backticks("xcrun simctl status_bar #{device_udid} clear &> /dev/null")
126
+ end
127
+
105
128
  def uninstall_app(device_type)
106
129
  launcher_config.app_identifier ||= UI.input("App Identifier: ")
107
130
  device_udid = TestCommandGenerator.device_udid(device_type)
@@ -16,20 +16,25 @@ module Snapshot
16
16
  parts += build_settings
17
17
  parts += actions
18
18
  parts += suffix
19
- parts += pipe(language: language, locale: locale, log_path: log_path)
19
+ parts += pipe(log_path: log_path)
20
20
 
21
21
  return parts
22
22
  end
23
23
 
24
- def pipe(language: nil, locale: nil, log_path: nil)
24
+ def pipe(log_path: nil)
25
25
  tee_command = ['tee']
26
26
  tee_command << '-a' if log_path && File.exist?(log_path)
27
27
  tee_command << log_path.shellescape if log_path
28
28
 
29
+ pipe = ["| #{tee_command.join(' ')}"]
30
+ if Snapshot.config[:disable_xcpretty]
31
+ return pipe
32
+ end
33
+
29
34
  xcpretty = "xcpretty #{Snapshot.config[:xcpretty_args]}"
30
35
  xcpretty << "--no-color" if Helper.colors_disabled?
31
36
 
32
- return ["| #{tee_command.join(' ')} | #{xcpretty}"]
37
+ return pipe << "| #{xcpretty}"
33
38
  end
34
39
 
35
40
  def destination(devices)