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 +4 -4
- 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/gym/lib/gym/generators/build_command_generator.rb +67 -21
- data/gym/lib/gym/options.rb +17 -5
- data/scan/lib/scan/options.rb +25 -5
- data/scan/lib/scan/runner.rb +57 -14
- data/scan/lib/scan/test_command_generator.rb +54 -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 +335 -0
- data/trainer/lib/trainer/xcresult.rb +403 -0
- data/trainer/lib/trainer.rb +7 -0
- metadata +13 -3
@@ -0,0 +1,403 @@
|
|
1
|
+
module Trainer
|
2
|
+
module XCResult
|
3
|
+
# Model attributes and relationships taken from running the following command:
|
4
|
+
# xcrun xcresulttool formatDescription
|
5
|
+
|
6
|
+
class AbstractObject
|
7
|
+
attr_accessor :type
|
8
|
+
def initialize(data)
|
9
|
+
self.type = data["_type"]["_name"]
|
10
|
+
end
|
11
|
+
|
12
|
+
def fetch_value(data, key)
|
13
|
+
return (data[key] || {})["_value"]
|
14
|
+
end
|
15
|
+
|
16
|
+
def fetch_values(data, key)
|
17
|
+
return (data[key] || {})["_values"] || []
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# - ActionTestPlanRunSummaries
|
22
|
+
# * Kind: object
|
23
|
+
# * Properties:
|
24
|
+
# + summaries: [ActionTestPlanRunSummary]
|
25
|
+
class ActionTestPlanRunSummaries < AbstractObject
|
26
|
+
attr_accessor :summaries
|
27
|
+
def initialize(data)
|
28
|
+
self.summaries = fetch_values(data, "summaries").map do |summary_data|
|
29
|
+
ActionTestPlanRunSummary.new(summary_data)
|
30
|
+
end
|
31
|
+
super
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# - ActionAbstractTestSummary
|
36
|
+
# * Kind: object
|
37
|
+
# * Properties:
|
38
|
+
# + name: String?
|
39
|
+
class ActionAbstractTestSummary < AbstractObject
|
40
|
+
attr_accessor :name
|
41
|
+
def initialize(data)
|
42
|
+
self.name = fetch_value(data, "name")
|
43
|
+
super
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# - ActionTestPlanRunSummary
|
48
|
+
# * Supertype: ActionAbstractTestSummary
|
49
|
+
# * Kind: object
|
50
|
+
# * Properties:
|
51
|
+
# + testableSummaries: [ActionTestableSummary]
|
52
|
+
class ActionTestPlanRunSummary < ActionAbstractTestSummary
|
53
|
+
attr_accessor :testable_summaries
|
54
|
+
def initialize(data)
|
55
|
+
self.testable_summaries = fetch_values(data, "testableSummaries").map do |summary_data|
|
56
|
+
ActionTestableSummary.new(summary_data)
|
57
|
+
end
|
58
|
+
super
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# - ActionTestableSummary
|
63
|
+
# * Supertype: ActionAbstractTestSummary
|
64
|
+
# * Kind: object
|
65
|
+
# * Properties:
|
66
|
+
# + projectRelativePath: String?
|
67
|
+
# + targetName: String?
|
68
|
+
# + testKind: String?
|
69
|
+
# + tests: [ActionTestSummaryIdentifiableObject]
|
70
|
+
# + diagnosticsDirectoryName: String?
|
71
|
+
# + failureSummaries: [ActionTestFailureSummary]
|
72
|
+
# + testLanguage: String?
|
73
|
+
# + testRegion: String?
|
74
|
+
class ActionTestableSummary < ActionAbstractTestSummary
|
75
|
+
attr_accessor :project_relative_path
|
76
|
+
attr_accessor :target_name
|
77
|
+
attr_accessor :test_kind
|
78
|
+
attr_accessor :tests
|
79
|
+
def initialize(data)
|
80
|
+
self.project_relative_path = fetch_value(data, "projectRelativePath")
|
81
|
+
self.target_name = fetch_value(data, "targetName")
|
82
|
+
self.test_kind = fetch_value(data, "testKind")
|
83
|
+
self.tests = fetch_values(data, "tests").map do |tests_data|
|
84
|
+
ActionTestSummaryIdentifiableObject.create(tests_data, self)
|
85
|
+
end
|
86
|
+
super
|
87
|
+
end
|
88
|
+
|
89
|
+
def all_tests
|
90
|
+
return tests.map(&:all_subtests).flatten
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# - ActionTestSummaryIdentifiableObject
|
95
|
+
# * Supertype: ActionAbstractTestSummary
|
96
|
+
# * Kind: object
|
97
|
+
# * Properties:
|
98
|
+
# + identifier: String?
|
99
|
+
class ActionTestSummaryIdentifiableObject < ActionAbstractTestSummary
|
100
|
+
attr_accessor :identifier
|
101
|
+
attr_accessor :parent
|
102
|
+
def initialize(data, parent)
|
103
|
+
self.identifier = fetch_value(data, "identifier")
|
104
|
+
self.parent = parent
|
105
|
+
super(data)
|
106
|
+
end
|
107
|
+
|
108
|
+
def all_subtests
|
109
|
+
raise "Not overridden"
|
110
|
+
end
|
111
|
+
|
112
|
+
def self.create(data, parent)
|
113
|
+
type = data["_type"]["_name"]
|
114
|
+
if type == "ActionTestSummaryGroup"
|
115
|
+
return ActionTestSummaryGroup.new(data, parent)
|
116
|
+
elsif type == "ActionTestMetadata"
|
117
|
+
return ActionTestMetadata.new(data, parent)
|
118
|
+
else
|
119
|
+
raise "Unsupported type: #{type}"
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# - ActionTestSummaryGroup
|
125
|
+
# * Supertype: ActionTestSummaryIdentifiableObject
|
126
|
+
# * Kind: object
|
127
|
+
# * Properties:
|
128
|
+
# + duration: Double
|
129
|
+
# + subtests: [ActionTestSummaryIdentifiableObject]
|
130
|
+
class ActionTestSummaryGroup < ActionTestSummaryIdentifiableObject
|
131
|
+
attr_accessor :duration
|
132
|
+
attr_accessor :subtests
|
133
|
+
def initialize(data, parent)
|
134
|
+
self.duration = fetch_value(data, "duration").to_f
|
135
|
+
self.subtests = fetch_values(data, "subtests").map do |subtests_data|
|
136
|
+
ActionTestSummaryIdentifiableObject.create(subtests_data, self)
|
137
|
+
end
|
138
|
+
super(data, parent)
|
139
|
+
end
|
140
|
+
|
141
|
+
def all_subtests
|
142
|
+
return subtests.map(&:all_subtests).flatten
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# - ActionTestMetadata
|
147
|
+
# * Supertype: ActionTestSummaryIdentifiableObject
|
148
|
+
# * Kind: object
|
149
|
+
# * Properties:
|
150
|
+
# + testStatus: String
|
151
|
+
# + duration: Double?
|
152
|
+
# + summaryRef: Reference?
|
153
|
+
# + performanceMetricsCount: Int
|
154
|
+
# + failureSummariesCount: Int
|
155
|
+
# + activitySummariesCount: Int
|
156
|
+
class ActionTestMetadata < ActionTestSummaryIdentifiableObject
|
157
|
+
attr_accessor :test_status
|
158
|
+
attr_accessor :duration
|
159
|
+
attr_accessor :performance_metrics_count
|
160
|
+
attr_accessor :failure_summaries_count
|
161
|
+
attr_accessor :activity_summaries_count
|
162
|
+
def initialize(data, parent)
|
163
|
+
self.test_status = fetch_value(data, "testStatus")
|
164
|
+
self.duration = fetch_value(data, "duration").to_f
|
165
|
+
self.performance_metrics_count = fetch_value(data, "performanceMetricsCount")
|
166
|
+
self.failure_summaries_count = fetch_value(data, "failureSummariesCount")
|
167
|
+
self.activity_summaries_count = fetch_value(data, "activitySummariesCount")
|
168
|
+
super(data, parent)
|
169
|
+
end
|
170
|
+
|
171
|
+
def all_subtests
|
172
|
+
return [self]
|
173
|
+
end
|
174
|
+
|
175
|
+
def find_failure(failures)
|
176
|
+
if self.test_status == "Failure"
|
177
|
+
# Tries to match failure on test case name
|
178
|
+
# Example TestFailureIssueSummary:
|
179
|
+
# producingTarget: "TestThisDude"
|
180
|
+
# test_case_name: "TestThisDude.testFailureJosh2()" (when Swift)
|
181
|
+
# or "-[TestThisDudeTests testFailureJosh2]" (when Objective-C)
|
182
|
+
# Example ActionTestMetadata
|
183
|
+
# identifier: "TestThisDude/testFailureJosh2()" (when Swift)
|
184
|
+
# or identifier: "TestThisDude/testFailureJosh2" (when Objective-C)
|
185
|
+
|
186
|
+
found_failure = failures.find do |failure|
|
187
|
+
# Clean test_case_name to match identifier format
|
188
|
+
# Sanitize for Swift by replacing "." for "/"
|
189
|
+
# Sanitize for Objective-C by removing "-", "[", "]", and replacing " " for ?/
|
190
|
+
sanitized_test_case_name = failure.test_case_name
|
191
|
+
.tr(".", "/")
|
192
|
+
.tr("-", "")
|
193
|
+
.tr("[", "")
|
194
|
+
.tr("]", "")
|
195
|
+
.tr(" ", "/")
|
196
|
+
self.identifier == sanitized_test_case_name
|
197
|
+
end
|
198
|
+
return found_failure
|
199
|
+
else
|
200
|
+
return nil
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
# - ActionsInvocationRecord
|
206
|
+
# * Kind: object
|
207
|
+
# * Properties:
|
208
|
+
# + metadataRef: Reference?
|
209
|
+
# + metrics: ResultMetrics
|
210
|
+
# + issues: ResultIssueSummaries
|
211
|
+
# + actions: [ActionRecord]
|
212
|
+
# + archive: ArchiveInfo?
|
213
|
+
class ActionsInvocationRecord < AbstractObject
|
214
|
+
attr_accessor :actions
|
215
|
+
attr_accessor :issues
|
216
|
+
def initialize(data)
|
217
|
+
self.actions = fetch_values(data, "actions").map do |action_data|
|
218
|
+
ActionRecord.new(action_data)
|
219
|
+
end
|
220
|
+
self.issues = ResultIssueSummaries.new(data["issues"])
|
221
|
+
super
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
# - ActionRecord
|
226
|
+
# * Kind: object
|
227
|
+
# * Properties:
|
228
|
+
# + schemeCommandName: String
|
229
|
+
# + schemeTaskName: String
|
230
|
+
# + title: String?
|
231
|
+
# + startedTime: Date
|
232
|
+
# + endedTime: Date
|
233
|
+
# + runDestination: ActionRunDestinationRecord
|
234
|
+
# + buildResult: ActionResult
|
235
|
+
# + actionResult: ActionResult
|
236
|
+
class ActionRecord < AbstractObject
|
237
|
+
attr_accessor :scheme_command_name
|
238
|
+
attr_accessor :scheme_task_name
|
239
|
+
attr_accessor :title
|
240
|
+
attr_accessor :build_result
|
241
|
+
attr_accessor :action_result
|
242
|
+
def initialize(data)
|
243
|
+
self.scheme_command_name = fetch_value(data, "schemeCommandName")
|
244
|
+
self.scheme_task_name = fetch_value(data, "schemeTaskName")
|
245
|
+
self.title = fetch_value(data, "title")
|
246
|
+
self.build_result = ActionResult.new(data["buildResult"])
|
247
|
+
self.action_result = ActionResult.new(data["actionResult"])
|
248
|
+
super
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
# - ActionResult
|
253
|
+
# * Kind: object
|
254
|
+
# * Properties:
|
255
|
+
# + resultName: String
|
256
|
+
# + status: String
|
257
|
+
# + metrics: ResultMetrics
|
258
|
+
# + issues: ResultIssueSummaries
|
259
|
+
# + coverage: CodeCoverageInfo
|
260
|
+
# + timelineRef: Reference?
|
261
|
+
# + logRef: Reference?
|
262
|
+
# + testsRef: Reference?
|
263
|
+
# + diagnosticsRef: Reference?
|
264
|
+
class ActionResult < AbstractObject
|
265
|
+
attr_accessor :result_name
|
266
|
+
attr_accessor :status
|
267
|
+
attr_accessor :issues
|
268
|
+
attr_accessor :timeline_ref
|
269
|
+
attr_accessor :log_ref
|
270
|
+
attr_accessor :tests_ref
|
271
|
+
attr_accessor :diagnostics_ref
|
272
|
+
def initialize(data)
|
273
|
+
self.result_name = fetch_value(data, "resultName")
|
274
|
+
self.status = fetch_value(data, "status")
|
275
|
+
self.issues = ResultIssueSummaries.new(data["issues"])
|
276
|
+
|
277
|
+
self.timeline_ref = Reference.new(data["timelineRef"]) if data["timelineRef"]
|
278
|
+
self.log_ref = Reference.new(data["logRef"]) if data["logRef"]
|
279
|
+
self.tests_ref = Reference.new(data["testsRef"]) if data["testsRef"]
|
280
|
+
self.diagnostics_ref = Reference.new(data["diagnosticsRef"]) if data["diagnosticsRef"]
|
281
|
+
super
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
# - Reference
|
286
|
+
# * Kind: object
|
287
|
+
# * Properties:
|
288
|
+
# + id: String
|
289
|
+
# + targetType: TypeDefinition?
|
290
|
+
class Reference < AbstractObject
|
291
|
+
attr_accessor :id
|
292
|
+
attr_accessor :target_type
|
293
|
+
def initialize(data)
|
294
|
+
self.id = fetch_value(data, "id")
|
295
|
+
self.target_type = TypeDefinition.new(data["targetType"]) if data["targetType"]
|
296
|
+
super
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
# - TypeDefinition
|
301
|
+
# * Kind: object
|
302
|
+
# * Properties:
|
303
|
+
# + name: String
|
304
|
+
# + supertype: TypeDefinition?
|
305
|
+
class TypeDefinition < AbstractObject
|
306
|
+
attr_accessor :name
|
307
|
+
attr_accessor :supertype
|
308
|
+
def initialize(data)
|
309
|
+
self.name = fetch_value(data, "name")
|
310
|
+
self.supertype = TypeDefinition.new(data["supertype"]) if data["supertype"]
|
311
|
+
super
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
# - DocumentLocation
|
316
|
+
# * Kind: object
|
317
|
+
# * Properties:
|
318
|
+
# + url: String
|
319
|
+
# + concreteTypeName: String
|
320
|
+
class DocumentLocation < AbstractObject
|
321
|
+
attr_accessor :url
|
322
|
+
attr_accessor :concrete_type_name
|
323
|
+
def initialize(data)
|
324
|
+
self.url = fetch_value(data, "url")
|
325
|
+
self.concrete_type_name = data["concreteTypeName"]["_value"]
|
326
|
+
super
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
# - IssueSummary
|
331
|
+
# * Kind: object
|
332
|
+
# * Properties:
|
333
|
+
# + issueType: String
|
334
|
+
# + message: String
|
335
|
+
# + producingTarget: String?
|
336
|
+
# + documentLocationInCreatingWorkspace: DocumentLocation?
|
337
|
+
class IssueSummary < AbstractObject
|
338
|
+
attr_accessor :issue_type
|
339
|
+
attr_accessor :message
|
340
|
+
attr_accessor :producing_target
|
341
|
+
attr_accessor :document_location_in_creating_workspace
|
342
|
+
def initialize(data)
|
343
|
+
self.issue_type = fetch_value(data, "issueType")
|
344
|
+
self.message = fetch_value(data, "message")
|
345
|
+
self.producing_target = fetch_value(data, "producingTarget")
|
346
|
+
self.document_location_in_creating_workspace = DocumentLocation.new(data["documentLocationInCreatingWorkspace"]) if data["documentLocationInCreatingWorkspace"]
|
347
|
+
super
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
# - ResultIssueSummaries
|
352
|
+
# * Kind: object
|
353
|
+
# * Properties:
|
354
|
+
# + analyzerWarningSummaries: [IssueSummary]
|
355
|
+
# + errorSummaries: [IssueSummary]
|
356
|
+
# + testFailureSummaries: [TestFailureIssueSummary]
|
357
|
+
# + warningSummaries: [IssueSummary]
|
358
|
+
class ResultIssueSummaries < AbstractObject
|
359
|
+
attr_accessor :analyzer_warning_summaries
|
360
|
+
attr_accessor :error_summaries
|
361
|
+
attr_accessor :test_failure_summaries
|
362
|
+
attr_accessor :warning_summaries
|
363
|
+
def initialize(data)
|
364
|
+
self.analyzer_warning_summaries = fetch_values(data, "analyzerWarningSummaries").map do |summary_data|
|
365
|
+
IssueSummary.new(summary_data)
|
366
|
+
end
|
367
|
+
self.error_summaries = fetch_values(data, "errorSummaries").map do |summary_data|
|
368
|
+
IssueSummary.new(summary_data)
|
369
|
+
end
|
370
|
+
self.test_failure_summaries = fetch_values(data, "testFailureSummaries").map do |summary_data|
|
371
|
+
TestFailureIssueSummary.new(summary_data)
|
372
|
+
end
|
373
|
+
self.warning_summaries = fetch_values(data, "warningSummaries").map do |summary_data|
|
374
|
+
IssueSummary.new(summary_data)
|
375
|
+
end
|
376
|
+
super
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
# - TestFailureIssueSummary
|
381
|
+
# * Supertype: IssueSummary
|
382
|
+
# * Kind: object
|
383
|
+
# * Properties:
|
384
|
+
# + testCaseName: String
|
385
|
+
class TestFailureIssueSummary < IssueSummary
|
386
|
+
attr_accessor :test_case_name
|
387
|
+
def initialize(data)
|
388
|
+
self.test_case_name = fetch_value(data, "testCaseName")
|
389
|
+
super
|
390
|
+
end
|
391
|
+
|
392
|
+
def failure_message
|
393
|
+
new_message = self.message
|
394
|
+
if self.document_location_in_creating_workspace
|
395
|
+
file_path = self.document_location_in_creating_workspace.url.gsub("file://", "")
|
396
|
+
new_message += " (#{file_path})"
|
397
|
+
end
|
398
|
+
|
399
|
+
return new_message
|
400
|
+
end
|
401
|
+
end
|
402
|
+
end
|
403
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fastlane
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.201.0.rc1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jimmy Dee
|
@@ -1225,6 +1225,7 @@ files:
|
|
1225
1225
|
- fastlane/lib/fastlane/actions/team_name.rb
|
1226
1226
|
- fastlane/lib/fastlane/actions/testfairy.rb
|
1227
1227
|
- fastlane/lib/fastlane/actions/testflight.rb
|
1228
|
+
- fastlane/lib/fastlane/actions/trainer.rb
|
1228
1229
|
- fastlane/lib/fastlane/actions/tryouts.rb
|
1229
1230
|
- fastlane/lib/fastlane/actions/twitter.rb
|
1230
1231
|
- fastlane/lib/fastlane/actions/typetalk.rb
|
@@ -1288,6 +1289,7 @@ files:
|
|
1288
1289
|
- fastlane/lib/fastlane/helper/podspec_helper.rb
|
1289
1290
|
- fastlane/lib/fastlane/helper/s3_client_helper.rb
|
1290
1291
|
- fastlane/lib/fastlane/helper/sh_helper.rb
|
1292
|
+
- fastlane/lib/fastlane/helper/xcodebuild_formatter_helper.rb
|
1291
1293
|
- fastlane/lib/fastlane/helper/xcodeproj_helper.rb
|
1292
1294
|
- fastlane/lib/fastlane/helper/xcversion_helper.rb
|
1293
1295
|
- fastlane/lib/fastlane/junit_generator.rb
|
@@ -1842,6 +1844,14 @@ files:
|
|
1842
1844
|
- supply/lib/supply/setup.rb
|
1843
1845
|
- supply/lib/supply/uploader.rb
|
1844
1846
|
- trainer/lib/.DS_Store
|
1847
|
+
- trainer/lib/assets/junit.xml.erb
|
1848
|
+
- trainer/lib/trainer.rb
|
1849
|
+
- trainer/lib/trainer/commands_generator.rb
|
1850
|
+
- trainer/lib/trainer/junit_generator.rb
|
1851
|
+
- trainer/lib/trainer/module.rb
|
1852
|
+
- trainer/lib/trainer/options.rb
|
1853
|
+
- trainer/lib/trainer/test_parser.rb
|
1854
|
+
- trainer/lib/trainer/xcresult.rb
|
1845
1855
|
homepage: https://fastlane.tools
|
1846
1856
|
licenses:
|
1847
1857
|
- MIT
|
@@ -1880,9 +1890,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
1880
1890
|
version: '2.5'
|
1881
1891
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
1882
1892
|
requirements:
|
1883
|
-
- - "
|
1893
|
+
- - ">"
|
1884
1894
|
- !ruby/object:Gem::Version
|
1885
|
-
version:
|
1895
|
+
version: 1.3.1
|
1886
1896
|
requirements: []
|
1887
1897
|
rubygems_version: 3.2.3
|
1888
1898
|
signing_key:
|