fastlane 2.201.0.rc2 → 2.201.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -17,4 +17,4 @@ public class Gymfile: GymfileProtocol {
17
17
  // during the `init` process, and you won't see this message
18
18
  }
19
19
 
20
- // Generated with fastlane 2.200.0
20
+ // Generated with fastlane 2.201.2
@@ -104,7 +104,10 @@ public protocol GymfileProtocol: class {
104
104
  /// Suppress the output of xcodebuild to stdout. Output is still saved in buildlog_path
105
105
  var suppressXcodeOutput: Bool? { get }
106
106
 
107
- /// Disable xcpretty formatting of build output
107
+ /// xcodebuild formatter to use (ex: 'xcbeautify', 'xcbeautify --quieter', 'xcpretty', 'xcpretty -test'). Use empty string (ex: '') to disable any formatter (More information: https://docs.fastlane.tools/best-practices/xcodebuild-formatters/)
108
+ var xcodebuildFormatter: String { get }
109
+
110
+ /// **DEPRECATED!** Use `xcodebuild_formatter: ''` instead - Disable xcpretty formatting of build output
108
111
  var disableXcpretty: Bool? { get }
109
112
 
110
113
  /// Use the test (RSpec style) format for build output
@@ -122,12 +125,12 @@ public protocol GymfileProtocol: class {
122
125
  /// Have xcpretty create a JSON compilation database at the provided path
123
126
  var xcprettyReportJson: String? { get }
124
127
 
125
- /// Analyze the project build time and store the output in 'culprits.txt' file
126
- var analyzeBuildTime: Bool? { get }
127
-
128
128
  /// Have xcpretty use unicode encoding when reporting builds
129
129
  var xcprettyUtf: Bool? { get }
130
130
 
131
+ /// Analyze the project build time and store the output in 'culprits.txt' file
132
+ var analyzeBuildTime: Bool? { get }
133
+
131
134
  /// Do not try to build a profile mapping from the xcodeproj. Match or a manually provided mapping should be used
132
135
  var skipProfileDetection: Bool { get }
133
136
 
@@ -182,14 +185,15 @@ public extension GymfileProtocol {
182
185
  var xcargs: String? { return nil }
183
186
  var xcconfig: String? { return nil }
184
187
  var suppressXcodeOutput: Bool? { return nil }
188
+ var xcodebuildFormatter: String { return "xcbeautify" }
185
189
  var disableXcpretty: Bool? { return nil }
186
190
  var xcprettyTestFormat: Bool? { return nil }
187
191
  var xcprettyFormatter: String? { return nil }
188
192
  var xcprettyReportJunit: String? { return nil }
189
193
  var xcprettyReportHtml: String? { return nil }
190
194
  var xcprettyReportJson: String? { return nil }
191
- var analyzeBuildTime: Bool? { return nil }
192
195
  var xcprettyUtf: Bool? { return nil }
196
+ var analyzeBuildTime: Bool? { return nil }
193
197
  var skipProfileDetection: Bool { return false }
194
198
  var xcodebuildCommand: String { return "xcodebuild" }
195
199
  var clonedSourcePackagesPath: String? { return nil }
@@ -200,4 +204,4 @@ public extension GymfileProtocol {
200
204
 
201
205
  // Please don't remove the lines below
202
206
  // They are used to detect outdated files
203
- // FastlaneRunnerAPIVersion [0.9.93]
207
+ // FastlaneRunnerAPIVersion [0.9.96]
@@ -17,4 +17,4 @@ public class Matchfile: MatchfileProtocol {
17
17
  // during the `init` process, and you won't see this message
18
18
  }
19
19
 
20
- // Generated with fastlane 2.200.0
20
+ // Generated with fastlane 2.201.2
@@ -192,4 +192,4 @@ public extension MatchfileProtocol {
192
192
 
193
193
  // Please don't remove the lines below
194
194
  // They are used to detect outdated files
195
- // FastlaneRunnerAPIVersion [0.9.87]
195
+ // FastlaneRunnerAPIVersion [0.9.90]
@@ -17,4 +17,4 @@ public class Precheckfile: PrecheckfileProtocol {
17
17
  // during the `init` process, and you won't see this message
18
18
  }
19
19
 
20
- // Generated with fastlane 2.200.0
20
+ // Generated with fastlane 2.201.2
@@ -52,4 +52,4 @@ public extension PrecheckfileProtocol {
52
52
 
53
53
  // Please don't remove the lines below
54
54
  // They are used to detect outdated files
55
- // FastlaneRunnerAPIVersion [0.9.86]
55
+ // FastlaneRunnerAPIVersion [0.9.89]
@@ -17,4 +17,4 @@ public class Scanfile: ScanfileProtocol {
17
17
  // during the `init` process, and you won't see this message
18
18
  }
19
19
 
20
- // Generated with fastlane 2.200.0
20
+ // Generated with fastlane 2.201.2
@@ -80,9 +80,6 @@ public protocol ScanfileProtocol: class {
80
80
  /// Should the HTML report be opened when tests are completed?
81
81
  var openReport: Bool { get }
82
82
 
83
- /// Disable xcpretty formatting of build, similar to `output_style='raw'` but this will also skip the test results table
84
- var disableXcpretty: Bool? { get }
85
-
86
83
  /// The directory in which all reports will be stored
87
84
  var outputDirectory: String { get }
88
85
 
@@ -104,9 +101,21 @@ public protocol ScanfileProtocol: class {
104
101
  /// Suppress the output of xcodebuild to stdout. Output is still saved in buildlog_path
105
102
  var suppressXcodeOutput: Bool? { get }
106
103
 
107
- /// A custom xcpretty formatter to use
104
+ /// xcodebuild formatter to use (ex: 'xcbeautify', 'xcbeautify --quieter', 'xcpretty', 'xcpretty -test'). Use empty string (ex: '') to disable any formatter (More information: https://docs.fastlane.tools/best-practices/xcodebuild-formatters/)
105
+ var xcodebuildFormatter: String { get }
106
+
107
+ /// Remove retry attempts from test results table and the JUnit report (if not using xcpretty)
108
+ var outputRemoveRetryAttempts: Bool { get }
109
+
110
+ /// **DEPRECATED!** Use `output_style: 'raw'` instead - Disable xcpretty formatting of build, similar to `output_style='raw'` but this will also skip the test results table
111
+ var disableXcpretty: Bool? { get }
112
+
113
+ /// **DEPRECATED!** Use 'xcpretty_formatter' instead - A custom xcpretty formatter to use
108
114
  var formatter: String? { get }
109
115
 
116
+ /// A custom xcpretty formatter to use
117
+ var xcprettyFormatter: String? { get }
118
+
110
119
  /// Pass in xcpretty additional command line arguments (e.g. '--test --no-color' or '--tap --no-utf')
111
120
  var xcprettyArgs: String? { get }
112
121
 
@@ -212,7 +221,7 @@ public protocol ScanfileProtocol: class {
212
221
  /// Lets xcodebuild use system's scm configuration
213
222
  var useSystemScm: Bool { get }
214
223
 
215
- /// The number of times a test can fail before scan should stop retrying
224
+ /// The number of times a test can fail
216
225
  var numberOfRetries: Int { get }
217
226
 
218
227
  /// Should this step stop the build if the tests fail? Set this to false if you're using trainer
@@ -246,7 +255,6 @@ public extension ScanfileProtocol {
246
255
  var addressSanitizer: Bool? { return nil }
247
256
  var threadSanitizer: Bool? { return nil }
248
257
  var openReport: Bool { return false }
249
- var disableXcpretty: Bool? { return nil }
250
258
  var outputDirectory: String { return "./test_output" }
251
259
  var outputStyle: String? { return nil }
252
260
  var outputTypes: String { return "html,junit" }
@@ -254,7 +262,11 @@ public extension ScanfileProtocol {
254
262
  var buildlogPath: String { return "~/Library/Logs/scan" }
255
263
  var includeSimulatorLogs: Bool { return false }
256
264
  var suppressXcodeOutput: Bool? { return nil }
265
+ var xcodebuildFormatter: String { return "xcbeautify" }
266
+ var outputRemoveRetryAttempts: Bool { return false }
267
+ var disableXcpretty: Bool? { return nil }
257
268
  var formatter: String? { return nil }
269
+ var xcprettyFormatter: String? { return nil }
258
270
  var xcprettyArgs: String? { return nil }
259
271
  var derivedDataPath: String? { return nil }
260
272
  var shouldZipBuildProducts: Bool { return false }
@@ -296,4 +308,4 @@ public extension ScanfileProtocol {
296
308
 
297
309
  // Please don't remove the lines below
298
310
  // They are used to detect outdated files
299
- // FastlaneRunnerAPIVersion [0.9.98]
311
+ // FastlaneRunnerAPIVersion [0.9.101]
@@ -17,4 +17,4 @@ public class Screengrabfile: ScreengrabfileProtocol {
17
17
  // during the `init` process, and you won't see this message
18
18
  }
19
19
 
20
- // Generated with fastlane 2.200.0
20
+ // Generated with fastlane 2.201.2
@@ -96,4 +96,4 @@ public extension ScreengrabfileProtocol {
96
96
 
97
97
  // Please don't remove the lines below
98
98
  // They are used to detect outdated files
99
- // FastlaneRunnerAPIVersion [0.9.88]
99
+ // FastlaneRunnerAPIVersion [0.9.91]
@@ -17,4 +17,4 @@ public class Snapshotfile: SnapshotfileProtocol {
17
17
  // during the `init` process, and you won't see this message
18
18
  }
19
19
 
20
- // Generated with fastlane 2.200.0
20
+ // Generated with fastlane 2.201.2
@@ -86,9 +86,6 @@ public protocol SnapshotfileProtocol: class {
86
86
  /// The configuration to use when building the app. Defaults to 'Release'
87
87
  var configuration: String? { get }
88
88
 
89
- /// Additional xcpretty arguments
90
- var xcprettyArgs: String? { get }
91
-
92
89
  /// The SDK that should be used for building the application
93
90
  var sdk: String? { get }
94
91
 
@@ -137,6 +134,12 @@ public protocol SnapshotfileProtocol: class {
137
134
  /// Array of strings matching Test Bundle/Test Suite/Test Cases to skip
138
135
  var skipTesting: String? { get }
139
136
 
137
+ /// xcodebuild formatter to use (ex: 'xcbeautify', 'xcbeautify --quieter', 'xcpretty', 'xcpretty -test'). Use empty string (ex: '') to disable any formatter (More information: https://docs.fastlane.tools/best-practices/xcodebuild-formatters/)
138
+ var xcodebuildFormatter: String { get }
139
+
140
+ /// **DEPRECATED!** Use `xcodebuild_formatter: ''` instead - Additional xcpretty arguments
141
+ var xcprettyArgs: String? { get }
142
+
140
143
  /// Disable xcpretty formatting of build
141
144
  var disableXcpretty: Bool? { get }
142
145
 
@@ -176,7 +179,6 @@ public extension SnapshotfileProtocol {
176
179
  var clean: Bool { return false }
177
180
  var testWithoutBuilding: Bool? { return nil }
178
181
  var configuration: String? { return nil }
179
- var xcprettyArgs: String? { return nil }
180
182
  var sdk: String? { return nil }
181
183
  var scheme: String? { return nil }
182
184
  var numberOfRetries: Int { return 1 }
@@ -193,6 +195,8 @@ public extension SnapshotfileProtocol {
193
195
  var testplan: String? { return nil }
194
196
  var onlyTesting: String? { return nil }
195
197
  var skipTesting: String? { return nil }
198
+ var xcodebuildFormatter: String { return "xcbeautify" }
199
+ var xcprettyArgs: String? { return nil }
196
200
  var disableXcpretty: Bool? { return nil }
197
201
  var suppressXcodeOutput: Bool? { return nil }
198
202
  var useSystemScm: Bool { return false }
@@ -200,4 +204,4 @@ public extension SnapshotfileProtocol {
200
204
 
201
205
  // Please don't remove the lines below
202
206
  // They are used to detect outdated files
203
- // FastlaneRunnerAPIVersion [0.9.82]
207
+ // FastlaneRunnerAPIVersion [0.9.85]
@@ -2,35 +2,35 @@
2
2
  "entries": {
3
3
  "brew": {
4
4
  "swiftformat": {
5
- "version": "0.49.1",
5
+ "version": "0.49.2",
6
6
  "bottle": {
7
7
  "rebuild": 0,
8
8
  "root_url": "https://ghcr.io/v2/homebrew/core",
9
9
  "files": {
10
10
  "arm64_monterey": {
11
11
  "cellar": ":any_skip_relocation",
12
- "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:c43caffb4d2cf9546b0a8fa732ffe5d95b1b1fd7ab03f1c5da39c8e7a0e8ecb4",
13
- "sha256": "c43caffb4d2cf9546b0a8fa732ffe5d95b1b1fd7ab03f1c5da39c8e7a0e8ecb4"
12
+ "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:2279db95259ddbc7ad83e47f5bbf8c308db55b74d5464ac79a027bd33138b023",
13
+ "sha256": "2279db95259ddbc7ad83e47f5bbf8c308db55b74d5464ac79a027bd33138b023"
14
14
  },
15
15
  "arm64_big_sur": {
16
16
  "cellar": ":any_skip_relocation",
17
- "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:ad0ce5fc15fe1d339d366ece18694fdc1d14021684462a126ed20b537a1a9bf5",
18
- "sha256": "ad0ce5fc15fe1d339d366ece18694fdc1d14021684462a126ed20b537a1a9bf5"
17
+ "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:2f6bddbef7d750d6ed546ed5decd4d54d439f16009491bdb4e4999c99d877bcf",
18
+ "sha256": "2f6bddbef7d750d6ed546ed5decd4d54d439f16009491bdb4e4999c99d877bcf"
19
19
  },
20
20
  "monterey": {
21
21
  "cellar": ":any_skip_relocation",
22
- "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:33652b8015d31dbe45e00bdc598f1b228cb63c7083b90137fdec66318a88010f",
23
- "sha256": "33652b8015d31dbe45e00bdc598f1b228cb63c7083b90137fdec66318a88010f"
22
+ "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:190bf822a188ec8e8be754de2fcd34166ffb07bbd40d67385653d898a251b167",
23
+ "sha256": "190bf822a188ec8e8be754de2fcd34166ffb07bbd40d67385653d898a251b167"
24
24
  },
25
25
  "big_sur": {
26
26
  "cellar": ":any_skip_relocation",
27
- "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:f0ad88e5594a6a3e5a35834a9a22473a05511375942dbb046d1085cc537d60b8",
28
- "sha256": "f0ad88e5594a6a3e5a35834a9a22473a05511375942dbb046d1085cc537d60b8"
27
+ "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:fe294ff0fa69548876a70ef7aaf30b7221a43adc9f75f7c157c6f881089da6eb",
28
+ "sha256": "fe294ff0fa69548876a70ef7aaf30b7221a43adc9f75f7c157c6f881089da6eb"
29
29
  },
30
30
  "catalina": {
31
31
  "cellar": ":any_skip_relocation",
32
- "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:564f5daf9cd82407843aed590bd4190f3e5aaa73a30b3bc8ae07135f1319ac97",
33
- "sha256": "564f5daf9cd82407843aed590bd4190f3e5aaa73a30b3bc8ae07135f1319ac97"
32
+ "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:2a174bf9c47a070b1fcaa32c066cd7c82604fc428db952f11c9bf1e4448c567a",
33
+ "sha256": "2a174bf9c47a070b1fcaa32c066cd7c82604fc428db952f11c9bf1e4448c567a"
34
34
  }
35
35
  }
36
36
  }
@@ -56,10 +56,10 @@
56
56
  "macOS": "11.6"
57
57
  },
58
58
  "monterey": {
59
- "HOMEBREW_VERSION": "3.3.10-21-g3ba6afb",
59
+ "HOMEBREW_VERSION": "3.3.12-10-g129e5bb",
60
60
  "HOMEBREW_PREFIX": "/opt/homebrew",
61
- "Homebrew/homebrew-core": "54f307bcd04cec374c7fd3f22fe7e6b13f1ad783",
62
- "CLT": "13.1.0.0.1.1633545042",
61
+ "Homebrew/homebrew-core": "ee89c86d2e1e18edd19974ae766264a4dcd1246d",
62
+ "CLT": "13.2.0.0.1.1638488800",
63
63
  "Xcode": "13.2.1",
64
64
  "macOS": "12.0.1"
65
65
  }
@@ -114,6 +114,13 @@ module Commander
114
114
  action_launch_context = FastlaneCore::ActionLaunchContext.context_for_action_name(@program[:name], fastlane_client_language: fastlane_client_language, args: ARGV)
115
115
  FastlaneCore.session.action_launched(launch_context: action_launch_context)
116
116
 
117
+ # Trainer has been added to fastlane as of 2.201.0
118
+ # We need to make sure that the trainer fastlane plugin is no longer installed
119
+ # to avoid any clashes
120
+ if Gem::Specification.any? { |s| (s.name == 'fastlane-plugin-trainer') && Gem::Requirement.default =~ (s.version) }
121
+ FastlaneCore::UI.user_error!("Migration Needed: As of 2.201.0, trainer is included in fastlane. Please remove the trainer plugin from your Gemfile or Pluginfile (or with 'gem uninstall fastlane-plugin-trainer') - More information: https://docs.fastlane.tools/best-practices/xcodebuild-formatters/")
122
+ end
123
+
117
124
  return_value = run_active_command
118
125
 
119
126
  action_completed(@program[:name], status: FastlaneCore::ActionCompletionStatus::SUCCESS)
@@ -234,7 +234,7 @@ module Gym
234
234
 
235
235
  FastlaneCore::ConfigItem.new(key: :xcodebuild_formatter,
236
236
  env_names: ["GYM_XCODEBUILD_FORMATTER", "FASTLANE_XCODEBUILD_FORMATTER"],
237
- description: "xcodebuild formatter to use (ex: 'xcbeautify', 'xcbeautify --quieter', 'xcpretty', 'xcpretty -test'). Use empty string (ex: '') to disable any formatter",
237
+ description: "xcodebuild formatter to use (ex: 'xcbeautify', 'xcbeautify --quieter', 'xcpretty', 'xcpretty -test'). Use empty string (ex: '') to disable any formatter (More information: https://docs.fastlane.tools/best-practices/xcodebuild-formatters/)",
238
238
  type: String,
239
239
  default_value: Fastlane::Helper::XcodebuildFormatterHelper.xcbeautify_installed? ? 'xcbeautify' : 'xcpretty',
240
240
  default_value_dynamic: true),
@@ -27,6 +27,15 @@ module Scan
27
27
  print("If you are using zshell or another shell, make sure to edit the correct bash file.")
28
28
  print("For more information visit this stackoverflow answer:")
29
29
  print("https://stackoverflow.com/a/17031697/445598")
30
+ when /Testing failed on/
31
+ # This is important because xcbeautify and raw output will print:
32
+ # Testing failed on 'iPhone 13 Pro Max'
33
+ # when multiple devices are use.
34
+ # xcpretty hides this output so its not an issue with xcpretty.
35
+ # We need to catch "Testing failed on" before "Test failed"
36
+ # so that an error isn't raised.
37
+ # Raising an error prevents trainer from processing the xcresult
38
+ return
30
39
  when /Testing failed/
31
40
  UI.build_failure!("Error building the application. #{details}")
32
41
  when /Executed/, /Failing tests:/
@@ -264,10 +264,15 @@ module Scan
264
264
 
265
265
  FastlaneCore::ConfigItem.new(key: :xcodebuild_formatter,
266
266
  env_names: ["SCAN_XCODEBUILD_FORMATTER", "FASTLANE_XCODEBUILD_FORMATTER"],
267
- description: "xcodebuild formatter to use (ex: 'xcbeautify', 'xcbeautify --quieter', 'xcpretty', 'xcpretty -test'). Use empty string (ex: '') to disable any formatter",
267
+ description: "xcodebuild formatter to use (ex: 'xcbeautify', 'xcbeautify --quieter', 'xcpretty', 'xcpretty -test'). Use empty string (ex: '') to disable any formatter (More information: https://docs.fastlane.tools/best-practices/xcodebuild-formatters/)",
268
268
  type: String,
269
269
  default_value: Fastlane::Helper::XcodebuildFormatterHelper.xcbeautify_installed? ? 'xcbeautify' : 'xcpretty',
270
270
  default_value_dynamic: true),
271
+ FastlaneCore::ConfigItem.new(key: :output_remove_retry_attempts,
272
+ env_name: "SCAN_OUTPUT_REMOVE_RETRY_ATTEMPS",
273
+ description: "Remove retry attempts from test results table and the JUnit report (if not using xcpretty)",
274
+ type: Boolean,
275
+ default_value: false),
271
276
 
272
277
  # xcpretty
273
278
  FastlaneCore::ConfigItem.new(key: :disable_xcpretty,
@@ -510,7 +515,7 @@ module Scan
510
515
  default_value: false),
511
516
  FastlaneCore::ConfigItem.new(key: :number_of_retries,
512
517
  env_name: 'SCAN_NUMBER_OF_RETRIES',
513
- description: "The number of times a test can fail before scan should stop retrying",
518
+ description: "The number of times a test can fail",
514
519
  type: Integer,
515
520
  default_value: 0)
516
521
 
@@ -20,6 +20,7 @@ module Scan
20
20
  end
21
21
 
22
22
  def run
23
+ @xcresults_before_run = find_xcresults_in_derived_data
23
24
  handle_results(test_app)
24
25
  end
25
26
 
@@ -51,13 +52,18 @@ module Scan
51
52
  end
52
53
  end
53
54
 
54
- # Set retries to 0 if Xcode 13 because TestCommandGenerator will set '-retry-tests-on-failure -test-iterations'
55
- retries = Helper.xcode_at_least?(13) ? 0 : Scan.config[:number_of_retries]
55
+ retries = Scan.config[:number_of_retries]
56
56
  execute(retries: retries)
57
57
  end
58
58
 
59
59
  def execute(retries: 0)
60
- Scan.cache[:retry_attempt] = Scan.config[:number_of_retries] - retries
60
+ # Set retries to 0 if Xcode 13 because TestCommandGenerator will set '-retry-tests-on-failure -test-iterations'
61
+ if Helper.xcode_at_least?(13)
62
+ retries = 0
63
+ Scan.cache[:retry_attempt] = 0
64
+ else
65
+ Scan.cache[:retry_attempt] = Scan.config[:number_of_retries] - retries
66
+ end
61
67
 
62
68
  command = @test_command_generator.generate
63
69
 
@@ -101,7 +107,7 @@ module Scan
101
107
  tests = retryable_tests(error_output)
102
108
 
103
109
  if tests.empty?
104
- UI.crash!("Failed to find failed tests to retry (could not parse error output)")
110
+ UI.build_failure!("Failed to find failed tests to retry (could not parse error output)")
105
111
  end
106
112
 
107
113
  Scan.config[:only_testing] = tests
@@ -167,6 +173,12 @@ module Scan
167
173
  return find_filename('json-compilation-database')
168
174
  end
169
175
 
176
+ def find_xcresults_in_derived_data
177
+ derived_data_path = Scan.config[:derived_data_path]
178
+ xcresults_path = File.join(derived_data_path, "Logs", "Test", "*.xcresult")
179
+ return Dir[xcresults_path]
180
+ end
181
+
170
182
  def trainer_test_results
171
183
  require "trainer"
172
184
 
@@ -178,24 +190,44 @@ module Scan
178
190
 
179
191
  result_bundle_path = Scan.cache[:result_bundle_path]
180
192
 
193
+ # Looks for xcresult file in derived data if not specifically set
194
+ if result_bundle_path.nil?
195
+ xcresults = find_xcresults_in_derived_data
196
+ new_xcresults = xcresults - @xcresults_before_run
197
+
198
+ if new_xcresults.size != 1
199
+ UI.build_failure!("Cannot find .xcresult in derived data which is needed to determine test results. This is an issue within scan. File an issue on GitHub or try setting option `result_bundle: true`")
200
+ end
201
+
202
+ result_bundle_path = new_xcresults.first
203
+ Scan.cache[:result_bundle_path] = result_bundle_path
204
+ end
205
+
181
206
  output_path = Scan.config[:output_directory] || Dir.mktmpdir
182
207
  output_path = File.absolute_path(output_path)
183
208
 
184
- UI.crash!("A -resultBundlePath is needed to parse the test results. This should not have happened. Please file an issue.") unless result_bundle_path
209
+ UI.build_failure!("A -resultBundlePath is needed to parse the test results. This should not have happened. Please file an issue.") unless result_bundle_path
185
210
 
186
211
  params = {
187
212
  path: result_bundle_path,
188
- silent: true
213
+ output_remove_retry_attempts: Scan.config[:output_remove_retry_attempts],
214
+ silent: !FastlaneCore::Globals.verbose?
189
215
  }
190
216
 
191
217
  formatter = Scan.config[:xcodebuild_formatter].chomp
192
-
218
+ show_output_types_tip = false
193
219
  if output_html? && formatter != 'xcpretty'
194
- UI.error("HTML output is only available with `xcodebuild_formatter: 'xcpretty'` right now...")
220
+ UI.important("Skipping HTML... only available with `xcodebuild_formatter: 'xcpretty'` right now")
221
+ show_output_types_tip = true
195
222
  end
196
223
 
197
224
  if output_json_compilation_database? && formatter != 'xcpretty'
198
- UI.error("JSON Compilation Database output is only available with `xcodebuild_formatter: 'xcpretty'` right now...")
225
+ UI.important("Skipping JSON Compilation Database... only available with `xcodebuild_formatter: 'xcpretty'` right now")
226
+ show_output_types_tip = true
227
+ end
228
+
229
+ if show_output_types_tip
230
+ UI.important("Your 'xcodebuild_formatter' doesn't support these 'output_types'. Change your 'output_types' to prevent these warnings from showing...")
199
231
  end
200
232
 
201
233
  if output_junit?
@@ -219,6 +251,8 @@ module Scan
219
251
  end
220
252
 
221
253
  def handle_results(tests_exit_status)
254
+ return if Scan.config[:build_for_testing]
255
+
222
256
  results = trainer_test_results
223
257
 
224
258
  number_of_retries = results[:number_of_retries]
@@ -53,7 +53,7 @@ module Scan
53
53
  if config[:use_system_scm] && !options.include?("-scmProvider system")
54
54
  options << "-scmProvider system"
55
55
  end
56
- options << "-resultBundlePath '#{result_bundle_path(config[:result_bundle])}'"
56
+ options << "-resultBundlePath '#{result_bundle_path(true)}'" if config[:result_bundle]
57
57
  if FastlaneCore::Helper.xcode_at_least?(10)
58
58
  options << "-parallel-testing-worker-count #{config[:concurrent_workers]}" if config[:concurrent_workers]
59
59
  options << "-maximum-concurrent-test-simulator-destinations #{config[:max_concurrent_simulators]}" if config[:max_concurrent_simulators]
@@ -72,9 +72,13 @@ module Scan
72
72
  end
73
73
  options << "-xctestrun '#{config[:xctestrun]}'" if config[:xctestrun]
74
74
  options << config[:xcargs] if config[:xcargs]
75
- if config[:number_of_retries] >= 1 && FastlaneCore::Helper.xcode_at_least?(13)
75
+
76
+ # Number of retries does not equal xcodebuild's -test-iterations number
77
+ # It needs include 1 iteration by default
78
+ number_of_retries = config[:number_of_retries] + 1
79
+ if number_of_retries > 1 && FastlaneCore::Helper.xcode_at_least?(13)
76
80
  options << "-retry-tests-on-failure"
77
- options << "-test-iterations #{config[:number_of_retries]}"
81
+ options << "-test-iterations #{number_of_retries}"
78
82
  end
79
83
 
80
84
  # detect_values will ensure that these values are present as Arrays if
@@ -291,7 +291,7 @@ module Snapshot
291
291
 
292
292
  FastlaneCore::ConfigItem.new(key: :xcodebuild_formatter,
293
293
  env_names: ["SNAPSHOT_XCODEBUILD_FORMATTER", "FASTLANE_XCODEBUILD_FORMATTER"],
294
- description: "xcodebuild formatter to use (ex: 'xcbeautify', 'xcbeautify --quieter', 'xcpretty', 'xcpretty -test'). Use empty string (ex: '') to disable any formatter",
294
+ description: "xcodebuild formatter to use (ex: 'xcbeautify', 'xcbeautify --quieter', 'xcpretty', 'xcpretty -test'). Use empty string (ex: '') to disable any formatter (More information: https://docs.fastlane.tools/best-practices/xcodebuild-formatters/)",
295
295
  type: String,
296
296
  default_value: Fastlane::Helper::XcodebuildFormatterHelper.xcbeautify_installed? ? 'xcbeautify' : 'xcpretty',
297
297
  default_value_dynamic: true),
@@ -1,12 +1,12 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
2
  <% number_of_tests = 0 %>
3
3
  <% number_of_failures = 0 %>
4
- <% @results.each { |a| number_of_tests += a[:number_of_tests] } %>
5
- <% @results.each { |a| number_of_failures += a[:number_of_failures] } %>
4
+ <% @results.each { |a| number_of_tests += a[:number_of_tests_excluding_retries] } %>
5
+ <% @results.each { |a| number_of_failures += a[:number_of_failures_excluding_retries] } %>
6
6
 
7
7
  <testsuites tests="<%= number_of_tests %>" failures="<%= number_of_failures %>">
8
8
  <% @results.each do |testsuite| %>
9
- <testsuite name=<%= (testsuite[:target_name].nil? ? testsuite[:test_name] : testsuite[:target_name]).encode(:xml => :attr) %> tests="<%= testsuite[:number_of_tests] %>" failures="<%= testsuite[:number_of_failures] %>" time="<%= testsuite[:duration] %>">
9
+ <testsuite name=<%= (testsuite[:target_name].nil? ? testsuite[:test_name] : testsuite[:target_name]).encode(:xml => :attr) %> tests="<%= testsuite[:number_of_tests_excluding_retries] %>" failures="<%= testsuite[:number_of_failures_excluding_retries] %>" time="<%= testsuite[:duration] %>">
10
10
  <% testsuite[:tests].each do |test| %>
11
11
  <testcase classname=<%= test[:test_group].encode(:xml => :attr) %> name=<%= test[:name].encode(:xml => :attr) %> time="<%= test[:duration] %>">
12
12
  <% (test[:failures] || []).each do |failure| %>
@@ -33,6 +33,12 @@ module Trainer
33
33
  default_value: nil,
34
34
  optional: true,
35
35
  description: "Directoy in which the xml files should be written to. Same directory as source by default"),
36
+ FastlaneCore::ConfigItem.new(key: :output_filename,
37
+ short_option: "-f",
38
+ env_name: "TRAINER_OUTPUT_FILENAME",
39
+ default_value: nil,
40
+ optional: true,
41
+ description: "Filename the xml file should be written to. Defaults to name of input file. (Only works if one input file is used)"),
36
42
  FastlaneCore::ConfigItem.new(key: :fail_build,
37
43
  env_name: "TRAINER_FAIL_BUILD",
38
44
  description: "Should this step stop the build if the tests fail? Set this to false if you're handling this with a test reporter",
@@ -48,6 +54,11 @@ module Trainer
48
54
  env_name: "TRAINER_SILENT",
49
55
  description: "Silences all output",
50
56
  is_string: false,
57
+ default_value: false),
58
+ FastlaneCore::ConfigItem.new(key: :output_remove_retry_attempts,
59
+ env_name: "TRAINER_OUTPUT_REMOVE_RETRY_ATTEMPTS",
60
+ description: "Doesn't include retry attempts in the output",
61
+ is_string: false,
51
62
  default_value: false)
52
63
  ]
53
64
  end
@@ -100,7 +100,7 @@ module Trainer
100
100
  UI.user_error!("File not found at path '#{path}'") unless File.exist?(path)
101
101
 
102
102
  if File.directory?(path) && path.end_with?(".xcresult")
103
- parse_xcresult(path)
103
+ parse_xcresult(path, output_remove_retry_attempts: config[:output_remove_retry_attempts])
104
104
  else
105
105
  self.file_content = File.read(path)
106
106
  self.raw_json = Plist.parse_xml(self.file_content)
@@ -193,7 +193,7 @@ module Trainer
193
193
  return output
194
194
  end
195
195
 
196
- def parse_xcresult(path)
196
+ def parse_xcresult(path, output_remove_retry_attempts: false)
197
197
  require 'shellwords'
198
198
  path = Shellwords.escape(path)
199
199
 
@@ -218,10 +218,10 @@ module Trainer
218
218
 
219
219
  # Converts the ActionTestPlanRunSummaries to data for junit generator
220
220
  failures = actions_invocation_record.issues.test_failure_summaries || []
221
- summaries_to_data(summaries, failures)
221
+ summaries_to_data(summaries, failures, output_remove_retry_attempts: output_remove_retry_attempts)
222
222
  end
223
223
 
224
- def summaries_to_data(summaries, failures)
224
+ def summaries_to_data(summaries, failures, output_remove_retry_attempts: false)
225
225
  # Gets flat list of all ActionTestableSummary
226
226
  all_summaries = summaries.map(&:summaries).flatten
227
227
  testable_summaries = all_summaries.map(&:testable_summaries).flatten
@@ -281,6 +281,30 @@ module Trainer
281
281
  test_row
282
282
  end
283
283
 
284
+ # Remove retry attempts from the count and test rows
285
+ if output_remove_retry_attempts
286
+ test_rows = test_rows.reject do |test_row|
287
+ remove = false
288
+
289
+ identifier = test_row[:identifier]
290
+ info = tests_by_identifier[identifier]
291
+
292
+ # Remove if this row is a retry and is a failure
293
+ if info[:retry_count] > 0
294
+ remove = !(test_row[:failures] || []).empty?
295
+ end
296
+
297
+ # Remove all failure and retry count if test did eventually pass
298
+ if remove
299
+ info[:failure_count] -= 1
300
+ info[:retry_count] -= 1
301
+ tests_by_identifier[identifier] = info
302
+ end
303
+
304
+ remove
305
+ end
306
+ end
307
+
284
308
  row = {
285
309
  project_path: testable_summary.project_relative_path,
286
310
  target_name: testable_summary.target_name,
@@ -339,6 +363,12 @@ module Trainer
339
363
  }
340
364
  summary_row[:number_of_tests] = summary_row[:tests].count
341
365
  summary_row[:number_of_failures] = summary_row[:tests].find_all { |a| (a[:failures] || []).count > 0 }.count
366
+
367
+ # Makes sure that plist support matches data output of xcresult
368
+ summary_row[:number_of_tests_excluding_retries] = summary_row[:number_of_tests]
369
+ summary_row[:number_of_failures_excluding_retries] = summary_row[:number_of_failures]
370
+ summary_row[:number_of_retries] = 0
371
+
342
372
  summary_row
343
373
  end
344
374
  end