fastlane 2.200.0 → 2.201.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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>