fastlane 2.200.0 → 2.201.0
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 +4 -4
- data/README.md +100 -93
- data/fastlane/lib/fastlane/actions/trainer.rb +49 -0
- data/fastlane/lib/fastlane/helper/xcodebuild_formatter_helper.rb +9 -0
- data/fastlane/lib/fastlane/tools.rb +2 -1
- data/fastlane/lib/fastlane/version.rb +1 -1
- data/fastlane/swift/Deliverfile.swift +1 -1
- data/fastlane/swift/DeliverfileProtocol.swift +1 -1
- data/fastlane/swift/Fastlane.swift +134 -43
- data/fastlane/swift/Gymfile.swift +1 -1
- data/fastlane/swift/GymfileProtocol.swift +10 -6
- data/fastlane/swift/Matchfile.swift +1 -1
- data/fastlane/swift/MatchfileProtocol.swift +1 -1
- data/fastlane/swift/Precheckfile.swift +1 -1
- data/fastlane/swift/PrecheckfileProtocol.swift +1 -1
- data/fastlane/swift/Scanfile.swift +1 -1
- data/fastlane/swift/ScanfileProtocol.swift +18 -6
- data/fastlane/swift/Screengrabfile.swift +1 -1
- data/fastlane/swift/ScreengrabfileProtocol.swift +1 -1
- data/fastlane/swift/Snapshotfile.swift +1 -1
- data/fastlane/swift/SnapshotfileProtocol.swift +9 -5
- data/fastlane/swift/formatting/Brewfile.lock.json +13 -13
- data/fastlane_core/lib/fastlane_core/ui/fastlane_runner.rb +7 -0
- data/gym/lib/gym/generators/build_command_generator.rb +67 -21
- data/gym/lib/gym/options.rb +17 -5
- data/scan/lib/scan/options.rb +30 -5
- data/scan/lib/scan/runner.rb +121 -14
- data/scan/lib/scan/test_command_generator.rb +55 -5
- data/snapshot/lib/snapshot/options.rb +23 -7
- data/snapshot/lib/snapshot/test_command_generator.rb +37 -2
- data/trainer/lib/assets/junit.xml.erb +20 -0
- data/trainer/lib/trainer/commands_generator.rb +51 -0
- data/trainer/lib/trainer/junit_generator.rb +31 -0
- data/trainer/lib/trainer/module.rb +10 -0
- data/trainer/lib/trainer/options.rb +55 -0
- data/trainer/lib/trainer/test_parser.rb +376 -0
- data/trainer/lib/trainer/xcresult.rb +403 -0
- data/trainer/lib/trainer.rb +7 -0
- metadata +29 -18
data/scan/lib/scan/runner.rb
CHANGED
@@ -51,11 +51,18 @@ module Scan
|
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
54
|
-
|
54
|
+
retries = Scan.config[:number_of_retries]
|
55
|
+
execute(retries: retries)
|
55
56
|
end
|
56
57
|
|
57
58
|
def execute(retries: 0)
|
58
|
-
|
59
|
+
# Set retries to 0 if Xcode 13 because TestCommandGenerator will set '-retry-tests-on-failure -test-iterations'
|
60
|
+
if Helper.xcode_at_least?(13)
|
61
|
+
retries = 0
|
62
|
+
Scan.cache[:retry_attempt] = 0
|
63
|
+
else
|
64
|
+
Scan.cache[:retry_attempt] = Scan.config[:number_of_retries] - retries
|
65
|
+
end
|
59
66
|
|
60
67
|
command = @test_command_generator.generate
|
61
68
|
|
@@ -135,27 +142,127 @@ module Scan
|
|
135
142
|
return retryable_tests.uniq
|
136
143
|
end
|
137
144
|
|
138
|
-
def
|
139
|
-
|
140
|
-
|
141
|
-
|
145
|
+
def find_filename(type)
|
146
|
+
index = Scan.config[:output_types].split(',').index(type)
|
147
|
+
return nil if index.nil?
|
148
|
+
return (Scan.config[:output_files] || "").split(',')[index]
|
149
|
+
end
|
150
|
+
|
151
|
+
def output_html?
|
152
|
+
return Scan.config[:output_types].split(',').include?('html')
|
153
|
+
end
|
154
|
+
|
155
|
+
def output_junit?
|
156
|
+
return Scan.config[:output_types].split(',').include?('junit')
|
157
|
+
end
|
158
|
+
|
159
|
+
def output_json_compilation_database?
|
160
|
+
return Scan.config[:output_types].split(',').include?('json-compilation-database')
|
161
|
+
end
|
162
|
+
|
163
|
+
def output_html_filename
|
164
|
+
return find_filename('html')
|
165
|
+
end
|
166
|
+
|
167
|
+
def output_junit_filename
|
168
|
+
return find_filename('junit')
|
169
|
+
end
|
170
|
+
|
171
|
+
def output_json_compilation_database_filename
|
172
|
+
return find_filename('json-compilation-database')
|
173
|
+
end
|
174
|
+
|
175
|
+
def trainer_test_results
|
176
|
+
require "trainer"
|
177
|
+
|
178
|
+
results = {
|
179
|
+
number_of_tests: 0,
|
180
|
+
number_of_failures: 0,
|
181
|
+
number_of_retries: 0
|
182
|
+
}
|
183
|
+
|
184
|
+
result_bundle_path = Scan.cache[:result_bundle_path]
|
185
|
+
|
186
|
+
output_path = Scan.config[:output_directory] || Dir.mktmpdir
|
187
|
+
output_path = File.absolute_path(output_path)
|
188
|
+
|
189
|
+
UI.crash!("A -resultBundlePath is needed to parse the test results. This should not have happened. Please file an issue.") unless result_bundle_path
|
190
|
+
|
191
|
+
params = {
|
192
|
+
path: result_bundle_path,
|
193
|
+
output_remove_retry_attempts: Scan.config[:output_remove_retry_attempts],
|
194
|
+
silent: !FastlaneCore::Globals.verbose?
|
195
|
+
}
|
196
|
+
|
197
|
+
formatter = Scan.config[:xcodebuild_formatter].chomp
|
198
|
+
show_output_types_tip = false
|
199
|
+
if output_html? && formatter != 'xcpretty'
|
200
|
+
UI.important("Skipping HTML... only available with `xcodebuild_formatter: 'xcpretty'` right now")
|
201
|
+
show_output_types_tip = true
|
202
|
+
end
|
203
|
+
|
204
|
+
if output_json_compilation_database? && formatter != 'xcpretty'
|
205
|
+
UI.important("Skipping JSON Compilation Database... only available with `xcodebuild_formatter: 'xcpretty'` right now")
|
206
|
+
show_output_types_tip = true
|
207
|
+
end
|
208
|
+
|
209
|
+
if show_output_types_tip
|
210
|
+
UI.important("Your 'xcodebuild_formatter' doesn't support these 'output_types'. Change your 'output_types' to prevent these warnings from showing...")
|
211
|
+
end
|
212
|
+
|
213
|
+
if output_junit?
|
214
|
+
if formatter == 'xcpretty'
|
215
|
+
UI.verbose("Generating junit report with xcpretty")
|
216
|
+
else
|
217
|
+
UI.verbose("Generating junit report with trainer")
|
218
|
+
params[:output_filename] = output_junit_filename || "report.junit"
|
219
|
+
params[:output_directory] = output_path
|
142
220
|
end
|
143
|
-
return
|
144
221
|
end
|
145
222
|
|
146
|
-
|
147
|
-
|
223
|
+
resulting_paths = Trainer::TestParser.auto_convert(params)
|
224
|
+
resulting_paths.each do |path, data|
|
225
|
+
results[:number_of_tests] += data[:number_of_tests_excluding_retries]
|
226
|
+
results[:number_of_failures] += data[:number_of_failures_excluding_retries]
|
227
|
+
results[:number_of_retries] += data[:number_of_retries]
|
228
|
+
end
|
229
|
+
|
230
|
+
return results
|
231
|
+
end
|
232
|
+
|
233
|
+
def handle_results(tests_exit_status)
|
234
|
+
return if Scan.config[:build_for_testing]
|
148
235
|
|
149
|
-
|
150
|
-
|
236
|
+
results = trainer_test_results
|
237
|
+
|
238
|
+
number_of_retries = results[:number_of_retries]
|
239
|
+
number_of_tests = results[:number_of_tests]
|
240
|
+
number_of_failures = results[:number_of_failures]
|
241
|
+
|
242
|
+
SlackPoster.new.run({
|
243
|
+
tests: number_of_tests,
|
244
|
+
failures: number_of_failures
|
245
|
+
})
|
246
|
+
|
247
|
+
if number_of_failures > 0
|
248
|
+
failures_str = number_of_failures.to_s.red
|
151
249
|
else
|
152
|
-
failures_str =
|
250
|
+
failures_str = number_of_failures.to_s.green
|
153
251
|
end
|
154
252
|
|
253
|
+
retries_str = case number_of_retries
|
254
|
+
when 0
|
255
|
+
""
|
256
|
+
when 1
|
257
|
+
" (and 1 retry)"
|
258
|
+
else
|
259
|
+
" (and #{number_of_retries} retries)"
|
260
|
+
end
|
261
|
+
|
155
262
|
puts(Terminal::Table.new({
|
156
263
|
title: "Test Results",
|
157
264
|
rows: [
|
158
|
-
["Number of tests",
|
265
|
+
["Number of tests", "#{number_of_tests}#{retries_str}"],
|
159
266
|
["Number of failures", failures_str]
|
160
267
|
]
|
161
268
|
}))
|
@@ -165,7 +272,7 @@ module Scan
|
|
165
272
|
zip_build_products
|
166
273
|
copy_xctestrun
|
167
274
|
|
168
|
-
if
|
275
|
+
if number_of_failures > 0
|
169
276
|
open_report
|
170
277
|
|
171
278
|
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
|
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,56 @@ 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 formatter == ''
|
123
|
+
UI.verbose("Not using an xcodebuild formatter")
|
124
|
+
elsif !options.empty?
|
125
|
+
UI.important("Detected legacy xcpretty being used so formatting wth xcpretty")
|
126
|
+
UI.important("Option(s) used: #{options.join(', ')}")
|
127
|
+
pipe << pipe_xcpretty
|
128
|
+
elsif formatter == 'xcpretty'
|
129
|
+
pipe << pipe_xcpretty
|
130
|
+
elsif formatter == 'xcbeautify'
|
131
|
+
pipe << pipe_xcbeautify
|
132
|
+
else
|
133
|
+
pipe << "| #{formatter}"
|
134
|
+
end
|
135
|
+
|
136
|
+
return pipe
|
137
|
+
end
|
138
|
+
|
139
|
+
def pipe_xcbeautify
|
140
|
+
formatter = ['| xcbeautify']
|
141
|
+
|
142
|
+
if FastlaneCore::Helper.colors_disabled?
|
143
|
+
formatter << '--disable-colored-output'
|
144
|
+
end
|
145
|
+
|
146
|
+
return formatter.join(' ')
|
147
|
+
end
|
148
|
+
|
149
|
+
def legacy_xcpretty_options
|
150
|
+
options = []
|
151
|
+
|
152
|
+
options << "formatter" if Scan.config[:formatter]
|
153
|
+
options << "xcpretty_formatter" if Scan.config[:xcpretty_formatter]
|
154
|
+
options << "output_style" if Scan.config[:output_style]
|
155
|
+
options << "output_types" if (Scan.config[:output_types] || "").include?("json-compilation-database")
|
156
|
+
options << "custom_report_file_name" if Scan.config[:custom_report_file_name]
|
157
|
+
|
158
|
+
return options
|
159
|
+
end
|
160
|
+
|
161
|
+
def pipe_xcpretty
|
114
162
|
formatter = []
|
115
|
-
if (custom_formatter = Scan.config[:formatter])
|
163
|
+
if (custom_formatter = Scan.config[:xcpretty_formatter] || Scan.config[:formatter])
|
116
164
|
if custom_formatter.end_with?(".rb")
|
117
165
|
formatter << "-f '#{custom_formatter}'"
|
118
166
|
else
|
@@ -143,7 +191,7 @@ module Scan
|
|
143
191
|
Scan.config[:xcpretty_args])
|
144
192
|
reporter_options = @reporter_options_generator.generate_reporter_options
|
145
193
|
reporter_xcpretty_args = @reporter_options_generator.generate_xcpretty_args_options
|
146
|
-
return
|
194
|
+
return "| xcpretty #{formatter.join(' ')} #{reporter_options.join(' ')} #{reporter_xcpretty_args}"
|
147
195
|
end
|
148
196
|
|
149
197
|
# Store the raw file
|
@@ -183,11 +231,13 @@ module Scan
|
|
183
231
|
end
|
184
232
|
|
185
233
|
# The path to the result bundle
|
186
|
-
def result_bundle_path
|
234
|
+
def result_bundle_path(use_output_directory)
|
235
|
+
root_dir = use_output_directory ? Scan.config[:output_directory] : Dir.mktmpdir
|
236
|
+
|
187
237
|
retry_count = Scan.cache[:retry_attempt] || 0
|
188
238
|
attempt = retry_count > 0 ? "-#{retry_count}" : ""
|
189
239
|
ext = FastlaneCore::Helper.xcode_version.to_i >= 11 ? '.xcresult' : '.test_result'
|
190
|
-
path = File.join(
|
240
|
+
path = File.join([root_dir, Scan.config[:scheme]].compact) + attempt + ext
|
191
241
|
|
192
242
|
Scan.cache[:result_bundle_path] = path
|
193
243
|
|
@@ -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
|
-
|
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'). Use empty string (ex: '') to disable any formatter (More information: https://docs.fastlane.tools/best-practices/xcodebuild-formatters/)",
|
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
|
-
|
31
|
-
|
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_excluding_retries] } %>
|
5
|
+
<% @results.each { |a| number_of_failures += a[:number_of_failures_excluding_retries] } %>
|
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_excluding_retries] %>" failures="<%= testsuite[:number_of_failures_excluding_retries] %>" 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>
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'commander'
|
2
|
+
|
3
|
+
require 'fastlane_core/configuration/configuration'
|
4
|
+
require 'fastlane_core/ui/help_formatter'
|
5
|
+
|
6
|
+
require_relative 'options'
|
7
|
+
require_relative 'test_parser'
|
8
|
+
|
9
|
+
require_relative 'module'
|
10
|
+
|
11
|
+
HighLine.track_eof = false
|
12
|
+
|
13
|
+
module Trainer
|
14
|
+
class CommandsGenerator
|
15
|
+
include Commander::Methods
|
16
|
+
|
17
|
+
def self.start
|
18
|
+
self.new.run
|
19
|
+
end
|
20
|
+
|
21
|
+
def run
|
22
|
+
program :version, Fastlane::VERSION
|
23
|
+
program :description, Trainer::DESCRIPTION
|
24
|
+
program :help, 'Author', 'Felix Krause <trainer@krausefx.com>'
|
25
|
+
program :help, 'Website', 'https://fastlane.tools'
|
26
|
+
program :help, 'GitHub', 'https://github.com/KrauseFx/trainer'
|
27
|
+
program :help_formatter, :compact
|
28
|
+
|
29
|
+
global_option('--verbose', 'Shows a more verbose output') { $verbose = true }
|
30
|
+
|
31
|
+
always_trace!
|
32
|
+
|
33
|
+
FastlaneCore::CommanderGenerator.new.generate(Trainer::Options.available_options)
|
34
|
+
|
35
|
+
command :run do |c|
|
36
|
+
c.syntax = 'trainer'
|
37
|
+
c.description = Trainer::DESCRIPTION
|
38
|
+
|
39
|
+
c.action do |args, options|
|
40
|
+
options = FastlaneCore::Configuration.create(Trainer::Options.available_options, options.__hash__)
|
41
|
+
FastlaneCore::PrintTable.print_values(config: options, title: "Summary for trainer #{Fastlane::VERSION}") if $verbose
|
42
|
+
Trainer::TestParser.auto_convert(options)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
default_command(:run)
|
47
|
+
|
48
|
+
run!
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require_relative 'module'
|
2
|
+
|
3
|
+
module Trainer
|
4
|
+
class JunitGenerator
|
5
|
+
attr_accessor :results
|
6
|
+
|
7
|
+
def initialize(results)
|
8
|
+
self.results = results
|
9
|
+
end
|
10
|
+
|
11
|
+
def generate
|
12
|
+
# JUnit file documentation: http://llg.cubic.org/docs/junit/
|
13
|
+
# And http://nelsonwells.net/2012/09/how-jenkins-ci-parses-and-displays-junit-output/
|
14
|
+
# And http://windyroad.com.au/dl/Open%20Source/JUnit.xsd
|
15
|
+
|
16
|
+
lib_path = Trainer::ROOT
|
17
|
+
xml_path = File.join(lib_path, "lib/assets/junit.xml.erb")
|
18
|
+
xml = ERB.new(File.read(xml_path), nil, '<>').result(binding) # http://www.rrn.dk/rubys-erb-templating-system
|
19
|
+
|
20
|
+
xml = xml.gsub('system_', 'system-').delete("\e") # Jenkins can not parse 'ESC' symbol
|
21
|
+
|
22
|
+
# We have to manuall clear empty lines
|
23
|
+
# They may contain white spaces
|
24
|
+
clean_xml = []
|
25
|
+
xml.each_line do |row|
|
26
|
+
clean_xml << row.delete("\n") if row.strip.to_s.length > 0
|
27
|
+
end
|
28
|
+
return clean_xml.join("\n")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'fastlane_core/helper'
|
2
|
+
require 'fastlane/boolean'
|
3
|
+
|
4
|
+
module Trainer
|
5
|
+
Helper = FastlaneCore::Helper # you gotta love Ruby: Helper.* should use the Helper class contained in FastlaneCore
|
6
|
+
UI = FastlaneCore::UI
|
7
|
+
Boolean = Fastlane::Boolean
|
8
|
+
ROOT = Pathname.new(File.expand_path('../../..', __FILE__))
|
9
|
+
DESCRIPTION = "Convert xcodebuild plist and xcresult files to JUnit reports"
|
10
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'fastlane_core/configuration/config_item'
|
2
|
+
|
3
|
+
require_relative 'module'
|
4
|
+
|
5
|
+
module Trainer
|
6
|
+
class Options
|
7
|
+
def self.available_options
|
8
|
+
@options ||= [
|
9
|
+
FastlaneCore::ConfigItem.new(key: :path,
|
10
|
+
short_option: "-p",
|
11
|
+
env_name: "TRAINER_PATH",
|
12
|
+
default_value: ".",
|
13
|
+
description: "Path to the directory that should be converted",
|
14
|
+
verify_block: proc do |value|
|
15
|
+
v = File.expand_path(value.to_s)
|
16
|
+
if v.end_with?(".plist")
|
17
|
+
UI.user_error!("Can't find file at path #{v}") unless File.exist?(v)
|
18
|
+
else
|
19
|
+
UI.user_error!("Path '#{v}' is not a directory or can't be found") unless File.directory?(v)
|
20
|
+
end
|
21
|
+
end),
|
22
|
+
FastlaneCore::ConfigItem.new(key: :extension,
|
23
|
+
short_option: "-e",
|
24
|
+
env_name: "TRAINER_EXTENSION",
|
25
|
+
default_value: ".xml",
|
26
|
+
description: "The extension for the newly created file. Usually .xml or .junit",
|
27
|
+
verify_block: proc do |value|
|
28
|
+
UI.user_error!("extension must contain a `.`") unless value.include?(".")
|
29
|
+
end),
|
30
|
+
FastlaneCore::ConfigItem.new(key: :output_directory,
|
31
|
+
short_option: "-o",
|
32
|
+
env_name: "TRAINER_OUTPUT_DIRECTORY",
|
33
|
+
default_value: nil,
|
34
|
+
optional: true,
|
35
|
+
description: "Directoy in which the xml files should be written to. Same directory as source by default"),
|
36
|
+
FastlaneCore::ConfigItem.new(key: :fail_build,
|
37
|
+
env_name: "TRAINER_FAIL_BUILD",
|
38
|
+
description: "Should this step stop the build if the tests fail? Set this to false if you're handling this with a test reporter",
|
39
|
+
is_string: false,
|
40
|
+
default_value: true),
|
41
|
+
FastlaneCore::ConfigItem.new(key: :xcpretty_naming,
|
42
|
+
short_option: "-x",
|
43
|
+
env_name: "TRAINER_XCPRETTY_NAMING",
|
44
|
+
description: "Produces class name and test name identical to xcpretty naming in junit file",
|
45
|
+
is_string: false,
|
46
|
+
default_value: false),
|
47
|
+
FastlaneCore::ConfigItem.new(key: :silent,
|
48
|
+
env_name: "TRAINER_SILENT",
|
49
|
+
description: "Silences all output",
|
50
|
+
is_string: false,
|
51
|
+
default_value: false)
|
52
|
+
]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|