fastlane 2.200.0 → 2.201.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1f80e15767a649f85c39e5b6d1cd2f0f8e4dee37c81a2c1e38c7b90673c04d68
4
- data.tar.gz: 41955caa65ee85fe319708bae375070d44562db6717307eebe28b57be5e6f280
3
+ metadata.gz: '0748d7414d5df9609fbffecf573937a1b74cbdebc81f9ee203e1197b58ecc5b1'
4
+ data.tar.gz: 6f07f231bb899663f8d4e46561b6c2fe982aad07cc531a9796ec285b0495d8bb
5
5
  SHA512:
6
- metadata.gz: ed42b7966058076011ee4a18eee35e70457f75f80b014623b9097289798304f62fb030ec16befa57c8bc39b0e9e2eb40745bff8341193cdcd32dcc4eaef8d8e0
7
- data.tar.gz: 3ae156afb0514a3a9d6e310b4610655f421b76e297aece23615c72598af7f4b2dfe7e6bc3ca5658a08aedd5060cba71718dfd049654662f9172ed0d7dc030638
6
+ metadata.gz: 79d8d561694712d172f2fcb925abfab4ce52a5be9d5af2e5645dd88813e0a65581e192c4ee21b792571685293a615d839442e156322f0cea7d6ef0303487747b
7
+ data.tar.gz: 8f5abd82eed5601477648a67bef8275c7ce4a48926550f409220f91fd54626ba375fef8827c5625ea6bf7d2ab833fbf8cdb49aa15ff9f02b51b93cde806cb144
@@ -0,0 +1,49 @@
1
+ module Fastlane
2
+ module Actions
3
+ class TrainerAction < Action
4
+ def self.run(params)
5
+ require "trainer"
6
+
7
+ params[:path] = Actions.lane_context[Actions::SharedValues::SCAN_GENERATED_PLIST_FILE] if Actions.lane_context[Actions::SharedValues::SCAN_GENERATED_PLIST_FILE]
8
+ params[:path] ||= Actions.lane_context[Actions::SharedValues::SCAN_DERIVED_DATA_PATH] if Actions.lane_context[Actions::SharedValues::SCAN_DERIVED_DATA_PATH]
9
+
10
+ fail_build = params[:fail_build]
11
+ resulting_paths = Trainer::TestParser.auto_convert(params)
12
+ resulting_paths.each do |path, test_successful|
13
+ UI.test_failure!("Unit tests failed") if fail_build && !test_successful
14
+ end
15
+
16
+ return resulting_paths
17
+ end
18
+
19
+ def self.description
20
+ "Convert the Xcode plist log to a JUnit report"
21
+ end
22
+
23
+ def self.detail
24
+ "Convert the Xcode plist log to a JUnit report. This will raise an exception if the tests failed"
25
+ end
26
+
27
+ def self.authors
28
+ ["KrauseFx"]
29
+ end
30
+
31
+ def self.return_value
32
+ "A hash with the key being the path of the generated file, the value being if the tests were successful"
33
+ end
34
+
35
+ def self.available_options
36
+ require 'trainer'
37
+ FastlaneCore::CommanderGenerator.new.generate(Trainer::Options.available_options)
38
+ end
39
+
40
+ def self.is_supported?(platform)
41
+ %i[ios mac].include?(platform)
42
+ end
43
+
44
+ def self.category
45
+ :testing
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,9 @@
1
+ module Fastlane
2
+ module Helper
3
+ class XcodebuildFormatterHelper
4
+ def self.xcbeautify_installed?
5
+ return `which xcbeautify`.include?("xcbeautify")
6
+ end
7
+ end
8
+ end
9
+ end
@@ -15,7 +15,8 @@ module Fastlane
15
15
  :match,
16
16
  :scan,
17
17
  :gym,
18
- :precheck
18
+ :precheck,
19
+ :trainer
19
20
  ]
20
21
 
21
22
  # a list of all the config files we currently expect
@@ -1,5 +1,5 @@
1
1
  module Fastlane
2
- VERSION = '2.200.0'.freeze
2
+ VERSION = '2.201.0.rc1'.freeze
3
3
  DESCRIPTION = "The easiest way to automate beta deployments and releases for your iOS and Android apps".freeze
4
4
  MINIMUM_XCODE_RELEASE = "7.0".freeze
5
5
  RUBOCOP_REQUIREMENT = '1.12.1'.freeze
@@ -72,32 +72,78 @@ module Gym
72
72
  def pipe
73
73
  pipe = []
74
74
  pipe << "| tee #{xcodebuild_log_path.shellescape}"
75
- unless Gym.config[:disable_xcpretty]
76
- formatter = Gym.config[:xcpretty_formatter]
77
- pipe << "| xcpretty"
78
- pipe << " --test" if Gym.config[:xcpretty_test_format]
79
- pipe << " --no-color" if Helper.colors_disabled?
80
- pipe << " --formatter " if formatter
81
- pipe << formatter if formatter
82
- pipe << "--utf" if Gym.config[:xcpretty_utf]
83
- report_output_junit = Gym.config[:xcpretty_report_junit]
84
- report_output_html = Gym.config[:xcpretty_report_html]
85
- report_output_json = Gym.config[:xcpretty_report_json]
86
- if report_output_junit
87
- pipe << " --report junit --output "
88
- pipe << report_output_junit.shellescape
89
- elsif report_output_html
90
- pipe << " --report html --output "
91
- pipe << report_output_html.shellescape
92
- elsif report_output_json
93
- pipe << " --report json-compilation-database --output "
94
- pipe << report_output_json.shellescape
95
- end
75
+
76
+ formatter = Gym.config[:xcodebuild_formatter].chomp
77
+ options = legacy_xcpretty_options
78
+
79
+ if Gym.config[:disable_xcpretty] || formatter == ''
80
+ UI.verbose("Not using an xcodebuild formatter")
81
+ elsif !options.empty?
82
+ UI.important("Detected legacy xcpretty being used so formatting wth xcpretty")
83
+ UI.important("Option(s) used: #{options.join(', ')}")
84
+ pipe += pipe_xcpretty
85
+ elsif formatter == 'xcpretty'
86
+ pipe += pipe_xcpretty
87
+ elsif formatter == 'xcbeautify'
88
+ pipe += pipe_xcbeautify
89
+ else
90
+ pipe << "| #{formatter}"
96
91
  end
92
+
97
93
  pipe << "> /dev/null" if Gym.config[:suppress_xcode_output]
98
94
  pipe
99
95
  end
100
96
 
97
+ def pipe_xcbeautify
98
+ pipe = ['| xcbeautify']
99
+
100
+ if FastlaneCore::Helper.colors_disabled?
101
+ pipe << '--disable-colored-output'
102
+ end
103
+
104
+ return pipe
105
+ end
106
+
107
+ def legacy_xcpretty_options
108
+ options = []
109
+
110
+ options << "xcpretty_test_format" if Gym.config[:xcpretty_test_format]
111
+ options << "xcpretty_formatter" if Gym.config[:xcpretty_formatter]
112
+ options << "xcpretty_report_junit" if Gym.config[:xcpretty_report_junit]
113
+ options << "xcpretty_report_html" if Gym.config[:xcpretty_report_html]
114
+ options << "xcpretty_report_json" if Gym.config[:xcpretty_report_json]
115
+ options << "xcpretty_utf" if Gym.config[:xcpretty_utf]
116
+
117
+ return options
118
+ end
119
+
120
+ def pipe_xcpretty
121
+ pipe = []
122
+
123
+ formatter = Gym.config[:xcpretty_formatter]
124
+ pipe << "| xcpretty"
125
+ pipe << " --test" if Gym.config[:xcpretty_test_format]
126
+ pipe << " --no-color" if Helper.colors_disabled?
127
+ pipe << " --formatter " if formatter
128
+ pipe << formatter if formatter
129
+ pipe << "--utf" if Gym.config[:xcpretty_utf]
130
+ report_output_junit = Gym.config[:xcpretty_report_junit]
131
+ report_output_html = Gym.config[:xcpretty_report_html]
132
+ report_output_json = Gym.config[:xcpretty_report_json]
133
+ if report_output_junit
134
+ pipe << " --report junit --output "
135
+ pipe << report_output_junit.shellescape
136
+ elsif report_output_html
137
+ pipe << " --report html --output "
138
+ pipe << report_output_html.shellescape
139
+ elsif report_output_json
140
+ pipe << " --report json-compilation-database --output "
141
+ pipe << report_output_json.shellescape
142
+ end
143
+
144
+ pipe
145
+ end
146
+
101
147
  def post_build
102
148
  commands = []
103
149
  commands << %{grep -E '^[0-9.]+ms' #{xcodebuild_log_path.shellescape} | grep -vE '^0\.[0-9]' | sort -nr > culprits.txt} if Gym.config[:analyze_build_time]
@@ -1,4 +1,5 @@
1
1
  require 'fastlane_core/configuration/config_item'
2
+ require 'fastlane/helper/xcodebuild_formatter_helper'
2
3
  require 'credentials_manager/appfile_config'
3
4
  require_relative 'module'
4
5
 
@@ -230,8 +231,18 @@ module Gym
230
231
  description: "Suppress the output of xcodebuild to stdout. Output is still saved in buildlog_path",
231
232
  optional: true,
232
233
  type: Boolean),
234
+
235
+ FastlaneCore::ConfigItem.new(key: :xcodebuild_formatter,
236
+ env_names: ["GYM_XCODEBUILD_FORMATTER", "FASTLANE_XCODEBUILD_FORMATTER"],
237
+ description: "xcodebuild formatter to use (ex: 'xcbeautify', 'xcbeautify --quieter', 'xcpretty', 'xcpretty -test')",
238
+ type: String,
239
+ default_value: Fastlane::Helper::XcodebuildFormatterHelper.xcbeautify_installed? ? 'xcbeautify' : 'xcpretty',
240
+ default_value_dynamic: true),
241
+
242
+ # xcpretty
233
243
  FastlaneCore::ConfigItem.new(key: :disable_xcpretty,
234
244
  env_name: "DISABLE_XCPRETTY",
245
+ deprecated: "Use `xcodebuild_formatter: ''` instead",
235
246
  description: "Disable xcpretty formatting of build output",
236
247
  optional: true,
237
248
  type: Boolean),
@@ -259,16 +270,17 @@ module Gym
259
270
  env_name: "XCPRETTY_REPORT_JSON",
260
271
  description: "Have xcpretty create a JSON compilation database at the provided path",
261
272
  optional: true),
262
- FastlaneCore::ConfigItem.new(key: :analyze_build_time,
263
- env_name: "GYM_ANALYZE_BUILD_TIME",
264
- description: "Analyze the project build time and store the output in 'culprits.txt' file",
265
- optional: true,
266
- type: Boolean),
267
273
  FastlaneCore::ConfigItem.new(key: :xcpretty_utf,
268
274
  env_name: "XCPRETTY_UTF",
269
275
  description: "Have xcpretty use unicode encoding when reporting builds",
270
276
  optional: true,
271
277
  type: Boolean),
278
+
279
+ FastlaneCore::ConfigItem.new(key: :analyze_build_time,
280
+ env_name: "GYM_ANALYZE_BUILD_TIME",
281
+ description: "Analyze the project build time and store the output in 'culprits.txt' file",
282
+ optional: true,
283
+ type: Boolean),
272
284
  FastlaneCore::ConfigItem.new(key: :skip_profile_detection,
273
285
  env_name: "GYM_SKIP_PROFILE_DETECTION",
274
286
  description: "Do not try to build a profile mapping from the xcodeproj. Match or a manually provided mapping should be used",
@@ -1,4 +1,5 @@
1
1
  require 'fastlane_core/configuration/config_item'
2
+ require 'fastlane/helper/xcodebuild_formatter_helper'
2
3
  require 'credentials_manager/appfile_config'
3
4
  require_relative 'module'
4
5
 
@@ -214,11 +215,7 @@ module Scan
214
215
  description: "Should the HTML report be opened when tests are completed?",
215
216
  is_string: false,
216
217
  default_value: false),
217
- FastlaneCore::ConfigItem.new(key: :disable_xcpretty,
218
- env_name: "SCAN_DISABLE_XCPRETTY",
219
- description: "Disable xcpretty formatting of build, similar to `output_style='raw'` but this will also skip the test results table",
220
- type: Boolean,
221
- optional: true),
218
+
222
219
  FastlaneCore::ConfigItem.new(key: :output_directory,
223
220
  short_option: "-o",
224
221
  env_name: "SCAN_OUTPUT_DIRECTORY",
@@ -227,6 +224,7 @@ module Scan
227
224
  code_gen_default_value: "./test_output",
228
225
  default_value: File.join(containing, "test_output"),
229
226
  default_value_dynamic: true),
227
+
230
228
  FastlaneCore::ConfigItem.new(key: :output_style,
231
229
  short_option: "-b",
232
230
  env_name: "SCAN_OUTPUT_STYLE",
@@ -263,9 +261,30 @@ module Scan
263
261
  description: "Suppress the output of xcodebuild to stdout. Output is still saved in buildlog_path",
264
262
  optional: true,
265
263
  type: Boolean),
264
+
265
+ FastlaneCore::ConfigItem.new(key: :xcodebuild_formatter,
266
+ env_names: ["SCAN_XCODEBUILD_FORMATTER", "FASTLANE_XCODEBUILD_FORMATTER"],
267
+ description: "xcodebuild formatter to use (ex: 'xcbeautify', 'xcbeautify --quieter', 'xcpretty', 'xcpretty -test')",
268
+ type: String,
269
+ default_value: Fastlane::Helper::XcodebuildFormatterHelper.xcbeautify_installed? ? 'xcbeautify' : 'xcpretty',
270
+ default_value_dynamic: true),
271
+
272
+ # xcpretty
273
+ FastlaneCore::ConfigItem.new(key: :disable_xcpretty,
274
+ env_name: "SCAN_DISABLE_XCPRETTY",
275
+ deprecated: "Use `output_style: 'raw'` instead",
276
+ description: "Disable xcpretty formatting of build, similar to `output_style='raw'` but this will also skip the test results table",
277
+ type: Boolean,
278
+ optional: true),
266
279
  FastlaneCore::ConfigItem.new(key: :formatter,
267
280
  short_option: "-n",
268
281
  env_name: "SCAN_FORMATTER",
282
+ deprecated: "Use 'xcpretty_formatter' instead",
283
+ description: "A custom xcpretty formatter to use",
284
+ optional: true),
285
+ FastlaneCore::ConfigItem.new(key: :xcpretty_formatter,
286
+ short_option: "-N",
287
+ env_name: "SCAN_XCPRETTY_FORMATTER",
269
288
  description: "A custom xcpretty formatter to use",
270
289
  optional: true),
271
290
  FastlaneCore::ConfigItem.new(key: :xcpretty_args,
@@ -273,6 +292,7 @@ module Scan
273
292
  description: "Pass in xcpretty additional command line arguments (e.g. '--test --no-color' or '--tap --no-utf')",
274
293
  type: String,
275
294
  optional: true),
295
+
276
296
  FastlaneCore::ConfigItem.new(key: :derived_data_path,
277
297
  short_option: "-j",
278
298
  env_name: "SCAN_DERIVED_DATA_PATH",
@@ -51,7 +51,9 @@ module Scan
51
51
  end
52
52
  end
53
53
 
54
- execute(retries: Scan.config[:number_of_retries])
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]
56
+ execute(retries: retries)
55
57
  end
56
58
 
57
59
  def execute(retries: 0)
@@ -135,27 +137,68 @@ module Scan
135
137
  return retryable_tests.uniq
136
138
  end
137
139
 
138
- def handle_results(tests_exit_status)
139
- if Scan.config[:disable_xcpretty]
140
- unless tests_exit_status == 0
141
- UI.test_failure!("Test execution failed. Exit status: #{tests_exit_status}")
142
- end
143
- return
140
+ def trainer_test_results
141
+ require "trainer"
142
+
143
+ results = {
144
+ number_of_tests: 0,
145
+ number_of_failures: 0,
146
+ number_of_retries: 0
147
+ }
148
+
149
+ result_bundle_path = Scan.cache[:result_bundle_path]
150
+ output_path = Scan.config[:output_directory] || Dir.mktmpdir
151
+
152
+ UI.crash!("A -resultBundlePath is needed to parse the test results. This should not have happened. Please file an issue.") unless result_bundle_path
153
+
154
+ params = {
155
+ path: result_bundle_path,
156
+ output_path: output_path,
157
+ silent: true,
158
+ extension: "xml"
159
+ }
160
+
161
+ resulting_paths = Trainer::TestParser.auto_convert(params)
162
+ resulting_paths.each do |path, data|
163
+ results[:number_of_tests] += data[:number_of_tests_excluding_retries]
164
+ results[:number_of_failures] += data[:number_of_failures_excluding_retries]
165
+ results[:number_of_retries] += data[:number_of_retries]
144
166
  end
145
167
 
146
- result = TestResultParser.new.parse_result(test_results)
147
- SlackPoster.new.run(result)
168
+ return results
169
+ end
170
+
171
+ def handle_results(tests_exit_status)
172
+ results = trainer_test_results
148
173
 
149
- if result[:failures] > 0
150
- failures_str = result[:failures].to_s.red
174
+ number_of_retries = results[:number_of_retries]
175
+ number_of_tests = results[:number_of_tests]
176
+ number_of_failures = results[:number_of_failures]
177
+
178
+ SlackPoster.new.run({
179
+ tests: number_of_tests,
180
+ failures: number_of_failures
181
+ })
182
+
183
+ if number_of_failures > 0
184
+ failures_str = number_of_failures.to_s.red
151
185
  else
152
- failures_str = result[:failures].to_s.green
186
+ failures_str = number_of_failures.to_s.green
153
187
  end
154
188
 
189
+ retries_str = case number_of_retries
190
+ when 0
191
+ ""
192
+ when 1
193
+ " (and 1 retry)"
194
+ else
195
+ " (and #{number_of_retries} retries)"
196
+ end
197
+
155
198
  puts(Terminal::Table.new({
156
199
  title: "Test Results",
157
200
  rows: [
158
- ["Number of tests", result[:tests]],
201
+ ["Number of tests", "#{number_of_tests}#{retries_str}"],
159
202
  ["Number of failures", failures_str]
160
203
  ]
161
204
  }))
@@ -165,7 +208,7 @@ module Scan
165
208
  zip_build_products
166
209
  copy_xctestrun
167
210
 
168
- if result[:failures] > 0
211
+ if number_of_failures > 0
169
212
  open_report
170
213
 
171
214
  UI.test_failure!("Tests have failed")
@@ -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}'" if config[:result_bundle]
56
+ options << "-resultBundlePath '#{result_bundle_path(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,6 +72,10 @@ 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)
76
+ options << "-retry-tests-on-failure"
77
+ options << "-test-iterations #{config[:number_of_retries]}"
78
+ end
75
79
 
76
80
  # detect_values will ensure that these values are present as Arrays if
77
81
  # they are present at all
@@ -107,12 +111,55 @@ module Scan
107
111
  def pipe
108
112
  pipe = ["| tee '#{xcodebuild_log_path}'"]
109
113
 
114
+ # disable_xcpretty is now deprecated and directs to use output_style of raw
110
115
  if Scan.config[:disable_xcpretty] || Scan.config[:output_style] == 'raw'
111
116
  return pipe
112
117
  end
113
118
 
119
+ formatter = Scan.config[:xcodebuild_formatter].chomp
120
+ options = legacy_xcpretty_options
121
+
122
+ if !options.empty?
123
+ UI.important("Detected legacy xcpretty being used so formatting wth xcpretty")
124
+ UI.important("Option(s) used: #{options.join(', ')}")
125
+ pipe << pipe_xcpretty
126
+ elsif formatter == 'xcpretty'
127
+ pipe << pipe_xcpretty
128
+ elsif formatter == 'xcbeautify'
129
+ pipe << pipe_xcbeautify
130
+ else
131
+ pipe << "| #{formatter}"
132
+ end
133
+
134
+ return pipe
135
+ end
136
+
137
+ def pipe_xcbeautify
138
+ formatter = ['| xcbeautify']
139
+
140
+ if FastlaneCore::Helper.colors_disabled?
141
+ formatter << '--disable-colored-output'
142
+ end
143
+
144
+ return formatter.join(' ')
145
+ end
146
+
147
+ def legacy_xcpretty_options
148
+ options = []
149
+
150
+ options << "formatter" if Scan.config[:formatter]
151
+ options << "xcpretty_formatter" if Scan.config[:xcpretty_formatter]
152
+ options << "output_style" if Scan.config[:output_style]
153
+ options << "output_files" if Scan.config[:output_files]
154
+ options << "output_types" if (Scan.config[:output_types] || "").include?("json-compilation-database")
155
+ options << "custom_report_file_name" if Scan.config[:custom_report_file_name]
156
+
157
+ return options
158
+ end
159
+
160
+ def pipe_xcpretty
114
161
  formatter = []
115
- if (custom_formatter = Scan.config[:formatter])
162
+ if (custom_formatter = Scan.config[:xcpretty_formatter] || Scan.config[:formatter])
116
163
  if custom_formatter.end_with?(".rb")
117
164
  formatter << "-f '#{custom_formatter}'"
118
165
  else
@@ -143,7 +190,7 @@ module Scan
143
190
  Scan.config[:xcpretty_args])
144
191
  reporter_options = @reporter_options_generator.generate_reporter_options
145
192
  reporter_xcpretty_args = @reporter_options_generator.generate_xcpretty_args_options
146
- return pipe << "| xcpretty #{formatter.join(' ')} #{reporter_options.join(' ')} #{reporter_xcpretty_args}"
193
+ return "| xcpretty #{formatter.join(' ')} #{reporter_options.join(' ')} #{reporter_xcpretty_args}"
147
194
  end
148
195
 
149
196
  # Store the raw file
@@ -183,11 +230,13 @@ module Scan
183
230
  end
184
231
 
185
232
  # The path to the result bundle
186
- def result_bundle_path
233
+ def result_bundle_path(use_output_directory)
234
+ root_dir = use_output_directory ? Scan.config[:output_directory] : Dir.mktmpdir
235
+
187
236
  retry_count = Scan.cache[:retry_attempt] || 0
188
237
  attempt = retry_count > 0 ? "-#{retry_count}" : ""
189
238
  ext = FastlaneCore::Helper.xcode_version.to_i >= 11 ? '.xcresult' : '.test_result'
190
- path = File.join(Scan.config[:output_directory], Scan.config[:scheme]) + attempt + ext
239
+ path = File.join([root_dir, Scan.config[:scheme]].compact) + attempt + ext
191
240
 
192
241
  Scan.cache[:result_bundle_path] = path
193
242
 
@@ -1,5 +1,6 @@
1
1
  require 'fastlane_core/configuration/config_item'
2
2
  require 'fastlane_core/device_manager'
3
+ require 'fastlane/helper/xcodebuild_formatter_helper'
3
4
  require 'credentials_manager/appfile_config'
4
5
  require_relative 'module'
5
6
 
@@ -11,9 +12,13 @@ module Snapshot
11
12
  end
12
13
 
13
14
  def self.available_options
15
+ @options ||= plain_options
16
+ end
17
+
18
+ def self.plain_options
14
19
  output_directory = (File.directory?("fastlane") ? "fastlane/screenshots" : "screenshots")
15
20
 
16
- @options ||= [
21
+ [
17
22
  FastlaneCore::ConfigItem.new(key: :workspace,
18
23
  short_option: "-w",
19
24
  env_name: "SNAPSHOT_WORKSPACE",
@@ -194,12 +199,6 @@ module Snapshot
194
199
  description: "The configuration to use when building the app. Defaults to 'Release'",
195
200
  default_value_dynamic: true,
196
201
  optional: true),
197
- FastlaneCore::ConfigItem.new(key: :xcpretty_args,
198
- short_option: "-x",
199
- env_name: "SNAPSHOT_XCPRETTY_ARGS",
200
- description: "Additional xcpretty arguments",
201
- is_string: true,
202
- optional: true),
203
202
  FastlaneCore::ConfigItem.new(key: :sdk,
204
203
  short_option: "-k",
205
204
  env_name: "SNAPSHOT_SDK",
@@ -289,11 +288,28 @@ module Snapshot
289
288
  verify_block: proc do |value|
290
289
  verify_type('skip_testing', [Array, String], value)
291
290
  end),
291
+
292
+ FastlaneCore::ConfigItem.new(key: :xcodebuild_formatter,
293
+ env_names: ["SNAPSHOT_XCODEBUILD_FORMATTER", "FASTLANE_XCODEBUILD_FORMATTER"],
294
+ description: "xcodebuild formatter to use (ex: 'xcbeautify', 'xcbeautify --quieter', 'xcpretty', 'xcpretty -test')",
295
+ type: String,
296
+ default_value: Fastlane::Helper::XcodebuildFormatterHelper.xcbeautify_installed? ? 'xcbeautify' : 'xcpretty',
297
+ default_value_dynamic: true),
298
+
299
+ # xcpretty
300
+ FastlaneCore::ConfigItem.new(key: :xcpretty_args,
301
+ short_option: "-x",
302
+ env_name: "SNAPSHOT_XCPRETTY_ARGS",
303
+ deprecated: "Use `xcodebuild_formatter: ''` instead",
304
+ description: "Additional xcpretty arguments",
305
+ is_string: true,
306
+ optional: true),
292
307
  FastlaneCore::ConfigItem.new(key: :disable_xcpretty,
293
308
  env_name: "SNAPSHOT_DISABLE_XCPRETTY",
294
309
  description: "Disable xcpretty formatting of build",
295
310
  type: Boolean,
296
311
  optional: true),
312
+
297
313
  FastlaneCore::ConfigItem.new(key: :suppress_xcode_output,
298
314
  env_name: "SNAPSHOT_SUPPRESS_XCODE_OUTPUT",
299
315
  description: "Suppress the output of xcodebuild to stdout. Output is still saved in buildlog_path",
@@ -27,10 +27,45 @@ module Snapshot
27
27
  tee_command << log_path.shellescape if log_path
28
28
 
29
29
  pipe = ["| #{tee_command.join(' ')}"]
30
- if Snapshot.config[:disable_xcpretty]
31
- return pipe
30
+
31
+ formatter = Snapshot.config[:xcodebuild_formatter].chomp
32
+ options = legacy_xcpretty_options
33
+
34
+ if Snapshot.config[:disable_xcpretty] || formatter == ''
35
+ UI.verbose("Not using an xcodebuild formatter")
36
+ elsif !options.empty?
37
+ UI.important("Detected legacy xcpretty being used so formatting wth xcpretty")
38
+ UI.important("Option(s) used: #{options.join(', ')}")
39
+ pipe += pipe_xcpretty
40
+ elsif formatter == 'xcpretty'
41
+ pipe += pipe_xcpretty
42
+ elsif formatter == 'xcbeautify'
43
+ pipe += pipe_xcbeautify
44
+ else
45
+ pipe << "| #{formatter}"
46
+ end
47
+
48
+ pipe
49
+ end
50
+
51
+ def pipe_xcbeautify
52
+ pipe = ['| xcbeautify']
53
+
54
+ if FastlaneCore::Helper.colors_disabled?
55
+ pipe << '--disable-colored-output'
32
56
  end
33
57
 
58
+ return pipe
59
+ end
60
+
61
+ def legacy_xcpretty_options
62
+ options = []
63
+ options << "xcpretty_args" if Snapshot.config[:xcpretty_args]
64
+ return options
65
+ end
66
+
67
+ def pipe_xcpretty
68
+ pipe = []
34
69
  xcpretty = "xcpretty #{Snapshot.config[:xcpretty_args]}"
35
70
  xcpretty << "--no-color" if Helper.colors_disabled?
36
71
  pipe << "| #{xcpretty}"
@@ -0,0 +1,20 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <% number_of_tests = 0 %>
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] } %>
6
+
7
+ <testsuites tests="<%= number_of_tests %>" failures="<%= number_of_failures %>">
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] %>">
10
+ <% testsuite[:tests].each do |test| %>
11
+ <testcase classname=<%= test[:test_group].encode(:xml => :attr) %> name=<%= test[:name].encode(:xml => :attr) %> time="<%= test[:duration] %>">
12
+ <% (test[:failures] || []).each do |failure| %>
13
+ <failure message=<%= failure[:failure_message].encode(:xml => :attr) %>>
14
+ </failure>
15
+ <% end %>
16
+ </testcase>
17
+ <% end %>
18
+ </testsuite>
19
+ <% end %>
20
+ </testsuites>