fastlane-plugin-try_scan 0.1.0 → 0.4.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 +9 -24
- data/lib/fastlane/plugin/try_scan/actions/try_scan_action.rb +17 -51
- data/lib/fastlane/plugin/try_scan/helper/scan_helper.rb +1 -35
- data/lib/fastlane/plugin/try_scan/helper/try_scan_runner.rb +72 -76
- data/lib/fastlane/plugin/try_scan/version.rb +1 -1
- metadata +16 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f1cf8ffd4f2e1a0558797b6bdd7094d7b36f42306d28d10bea3172be11c42688
|
4
|
+
data.tar.gz: c286e3609e7900a837322e36dc86ed3ead3a17fe0a32a3239a87de8feb8a742a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 27fea4e492a529eee6953d601914075b0042549345bfb4fc91e28bf0562fc514c943bbebdb929777c5973d863ec8b09795b9445e46c76cd3da142a14c42d08fa
|
7
|
+
data.tar.gz: 12bab09a883ab80263e01a65b07ec9670df952a2800d1296a87688af7bf8736de240ebf35f05cf6f54df822d405cc3cf3c50f40b2c6ca3f908b0db69e1288d32
|
data/README.md
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
## Getting Started
|
6
6
|
|
7
|
-
This project is a [_fastlane_](https://github.com/fastlane/fastlane) plugin. To get started with `
|
7
|
+
This project is a [_fastlane_](https://github.com/fastlane/fastlane) plugin. To get started with `try_scan`, add it to your project by running:
|
8
8
|
|
9
9
|
```bash
|
10
10
|
fastlane add_plugin try_scan
|
@@ -12,27 +12,16 @@ fastlane add_plugin try_scan
|
|
12
12
|
|
13
13
|
## About try_scan
|
14
14
|
|
15
|
-
Simple way to retry your scan action
|
15
|
+
Simple way to retry your scan action 🚀
|
16
16
|
|
17
|
-
|
17
|
+
## Usage
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
## Run tests for this plugin
|
26
|
-
|
27
|
-
To run both the tests, and code style validation, run
|
28
|
-
|
29
|
-
```
|
30
|
-
rake
|
31
|
-
```
|
32
|
-
|
33
|
-
To automatically fix many of the styling issues, use
|
34
|
-
```
|
35
|
-
rubocop -a
|
19
|
+
```ruby
|
20
|
+
try_scan(
|
21
|
+
workspace: "Example.xcworkspace",
|
22
|
+
devices: ["iPhone 6s", "iPad Air"],
|
23
|
+
try_count: 3
|
24
|
+
)
|
36
25
|
```
|
37
26
|
|
38
27
|
## Issues and Feedback
|
@@ -43,10 +32,6 @@ For any other issues and feedback about this plugin, please submit it to this re
|
|
43
32
|
|
44
33
|
If you have trouble using plugins, check out the [Plugins Troubleshooting](https://docs.fastlane.tools/plugins/plugins-troubleshooting/) guide.
|
45
34
|
|
46
|
-
## Using _fastlane_ Plugins
|
47
|
-
|
48
|
-
For more information about how the `fastlane` plugin system works, check out the [Plugins documentation](https://docs.fastlane.tools/plugins/create-plugin/).
|
49
|
-
|
50
35
|
## About _fastlane_
|
51
36
|
|
52
37
|
_fastlane_ is the easiest way to automate beta deployments and releases for your iOS and Android apps. To learn more, check out [fastlane.tools](https://fastlane.tools).
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module Fastlane
|
2
2
|
module Actions
|
3
3
|
|
4
|
+
require 'json'
|
4
5
|
require 'fastlane/actions/scan'
|
5
6
|
require_relative '../helper/scan_helper'
|
6
7
|
require_relative '../helper/try_scan_runner'
|
@@ -9,61 +10,31 @@ module Fastlane
|
|
9
10
|
|
10
11
|
class TryScanAction < Action
|
11
12
|
def self.run(params)
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
turn_off_concurrent_workers(params.values)
|
22
|
-
prepare_scan_config(params.values)
|
23
|
-
coerce_destination_to_array(params)
|
13
|
+
if Helper.xcode_at_least?('11.0.0')
|
14
|
+
prepare_scan_config(params.values)
|
15
|
+
prepare_destination(params)
|
16
|
+
success = TryScanManager::Runner.new(params.values).run
|
17
|
+
|
18
|
+
raise FastlaneCore::UI.test_failure!('Tests have failed') if params[:fail_build] && !success
|
19
|
+
else
|
20
|
+
raise FastlaneCore::UI.user_error!("Minimum supported Xcode: `v11.0.0` (used: `v#{Helper.xcode_version}`)")
|
21
|
+
end
|
24
22
|
end
|
25
23
|
|
26
|
-
def self.
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
elsif params[:output_types]&.include?('xcresult')
|
32
|
-
FastlaneCore::UI.important("The 'xcresult' :output_type is only supported for Xcode 11 and greater. You are using #{FastlaneCore::Helper.xcode_version}.")
|
33
|
-
end
|
24
|
+
def self.prepare_scan_config(scan_options)
|
25
|
+
Scan.config = FastlaneCore::Configuration.create(
|
26
|
+
Fastlane::Actions::ScanAction.available_options,
|
27
|
+
FastlaneScanHelper.scan_options_from_try_scan_options(scan_options)
|
28
|
+
)
|
34
29
|
end
|
35
30
|
|
36
|
-
def self.
|
31
|
+
def self.prepare_destination(params)
|
37
32
|
destination = params[:destination] || Scan.config[:destination] || []
|
38
33
|
unless destination.kind_of?(Array)
|
39
34
|
params[:destination] = Scan.config[:destination] = [destination]
|
40
35
|
end
|
41
36
|
end
|
42
37
|
|
43
|
-
def self.turn_off_concurrent_workers(scan_options)
|
44
|
-
if Gem::Version.new(Fastlane::VERSION) >= Gem::Version.new('2.142.0')
|
45
|
-
scan_options.delete(:concurrent_workers) if scan_options[:concurrent_workers].to_i > 0
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def self.use_scanfile_to_override_settings(scan_options)
|
50
|
-
overridden_options = FastlaneScanHelper.options_from_configuration_file(
|
51
|
-
FastlaneScanHelper.scan_options_from_try_scan_options(scan_options)
|
52
|
-
)
|
53
|
-
|
54
|
-
unless overridden_options.empty?
|
55
|
-
FastlaneCore::UI.important("Scanfile found: overriding try_scan options with it's values.")
|
56
|
-
overridden_options.each { |key, val| scan_options[key] = val }
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
def self.prepare_scan_config(scan_options)
|
61
|
-
Scan.config ||= FastlaneCore::Configuration.create(
|
62
|
-
Fastlane::Actions::ScanAction.available_options,
|
63
|
-
FastlaneScanHelper.scan_options_from_try_scan_options(scan_options)
|
64
|
-
)
|
65
|
-
end
|
66
|
-
|
67
38
|
#####################################################
|
68
39
|
# Documentation #
|
69
40
|
#####################################################
|
@@ -76,13 +47,8 @@ module Fastlane
|
|
76
47
|
["Alexey Alter-Pesotskiy"]
|
77
48
|
end
|
78
49
|
|
79
|
-
def self.scan_options
|
80
|
-
ScanAction.available_options.reject { |config| %i[output_types].include?(config.key) }
|
81
|
-
end
|
82
|
-
|
83
50
|
def self.available_options
|
84
|
-
|
85
|
-
scan_options + [
|
51
|
+
ScanAction.available_options + [
|
86
52
|
FastlaneCore::ConfigItem.new(
|
87
53
|
key: :try_count,
|
88
54
|
env_name: "FL_TRY_SCAN_TRY_COUNT",
|
@@ -19,31 +19,9 @@ module TryScanManager
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def self.scan_options_from_try_scan_options(params)
|
22
|
-
valid_scan_keys = Fastlane::Actions::ScanAction.available_options.map(&:key)
|
23
22
|
params.select { |key, _| valid_scan_keys.include?(key) }
|
24
23
|
end
|
25
24
|
|
26
|
-
def self.options_from_configuration_file(params)
|
27
|
-
config = FastlaneCore::Configuration.create(
|
28
|
-
Fastlane::Actions::ScanAction.available_options,
|
29
|
-
params
|
30
|
-
)
|
31
|
-
config_file = config.load_configuration_file(Scan.scanfile_name, nil, true)
|
32
|
-
overridden_options = config_file ? config_file.options : {}
|
33
|
-
|
34
|
-
FastlaneCore::Project.detect_projects(config)
|
35
|
-
project = FastlaneCore::Project.new(config)
|
36
|
-
|
37
|
-
imported_path = File.expand_path(Scan.scanfile_name)
|
38
|
-
Dir.chdir(File.expand_path("..", project.path)) do
|
39
|
-
if File.expand_path(Scan.scanfile_name) != imported_path
|
40
|
-
config_file = config.load_configuration_file(Scan.scanfile_name, nil, true)
|
41
|
-
end
|
42
|
-
overridden_options.merge!(config_file.options) if config_file
|
43
|
-
end
|
44
|
-
overridden_options
|
45
|
-
end
|
46
|
-
|
47
25
|
def self.remove_preexisting_simulator_logs(params)
|
48
26
|
return unless params[:include_simulator_logs]
|
49
27
|
|
@@ -88,18 +66,6 @@ module TryScanManager
|
|
88
66
|
end
|
89
67
|
end
|
90
68
|
end
|
91
|
-
|
92
|
-
def self.update_xctestrun_after_build(scan_options)
|
93
|
-
xctestrun_files = Dir.glob("#{Scan.config[:derived_data_path]}/Build/Products/*.xctestrun")
|
94
|
-
FastlaneCore::UI.verbose("After building, found xctestrun files #{xctestrun_files} (choosing 1st)")
|
95
|
-
scan_options[:xctestrun] = xctestrun_files.first
|
96
|
-
end
|
97
|
-
|
98
|
-
def self.remove_preexisting_xctestrun_files
|
99
|
-
xctestrun_files = Dir.glob("#{Scan.config[:derived_data_path]}/Build/Products/*.xctestrun")
|
100
|
-
FastlaneCore::UI.verbose("Before building, removing pre-existing xctestrun files: #{xctestrun_files}")
|
101
|
-
FileUtils.rm_rf(xctestrun_files)
|
102
|
-
end
|
103
69
|
end
|
104
70
|
end
|
105
|
-
end
|
71
|
+
end
|
@@ -5,30 +5,37 @@ module TryScanManager
|
|
5
5
|
|
6
6
|
def initialize(options = {})
|
7
7
|
@options = options
|
8
|
-
|
8
|
+
@options[:try_count] = 1 if @options[:try_count] < 1
|
9
9
|
end
|
10
10
|
|
11
11
|
def run
|
12
|
-
update_scan_config
|
13
12
|
print_summary
|
14
|
-
attempt = 1
|
13
|
+
@attempt = 1
|
15
14
|
begin
|
16
|
-
|
15
|
+
essential_scan_config_updates
|
16
|
+
warn_of_performing_attempts
|
17
17
|
clear_preexisting_data
|
18
18
|
Scan::Runner.new.run
|
19
|
+
print_try_scan_result
|
19
20
|
return true
|
20
|
-
rescue FastlaneCore::Interface::
|
21
|
-
|
22
|
-
|
21
|
+
rescue FastlaneCore::Interface::FastlaneTestFailure => _
|
22
|
+
failed_tests = failed_tests_from_xcresult_report
|
23
|
+
print_try_scan_result(failed_tests_count: failed_tests.size)
|
24
|
+
return false if finish?
|
23
25
|
|
24
|
-
attempt += 1
|
25
|
-
update_scan_options
|
26
|
+
@attempt += 1
|
27
|
+
update_scan_options(failed_tests)
|
28
|
+
retry
|
29
|
+
rescue FastlaneCore::Interface::FastlaneBuildFailure => _
|
30
|
+
return false if finish?
|
31
|
+
|
32
|
+
@attempt += 1
|
26
33
|
retry
|
27
34
|
end
|
28
35
|
end
|
29
36
|
|
30
|
-
def
|
31
|
-
|
37
|
+
def finish?
|
38
|
+
@attempt >= @options[:try_count]
|
32
39
|
end
|
33
40
|
|
34
41
|
def print_summary
|
@@ -47,15 +54,8 @@ module TryScanManager
|
|
47
54
|
)
|
48
55
|
end
|
49
56
|
|
50
|
-
def warn_of_performing_attempts
|
51
|
-
FastlaneCore::UI.important("TryScan
|
52
|
-
end
|
53
|
-
|
54
|
-
def warn_of_try_scan_option
|
55
|
-
if @options[:try_count] <= 0
|
56
|
-
FastlaneCore::UI.important(":try_count can't be less than or equal to zero. Setting a default value equal to `1`")
|
57
|
-
@options[:try_count] = 1
|
58
|
-
end
|
57
|
+
def warn_of_performing_attempts
|
58
|
+
FastlaneCore::UI.important("TryScan: Getting started #{ordinalized_attempt} shot\n")
|
59
59
|
end
|
60
60
|
|
61
61
|
def clear_preexisting_data
|
@@ -65,81 +65,77 @@ module TryScanManager
|
|
65
65
|
FastlaneScanHelper.remove_report_files
|
66
66
|
end
|
67
67
|
|
68
|
-
def
|
69
|
-
|
70
|
-
|
68
|
+
def print_try_scan_result(failed_tests_count: 0)
|
69
|
+
FastlaneCore::UI.important("TryScan: result after #{ordinalized_attempt} shot 👇")
|
70
|
+
FastlaneCore::PrintTable.print_values(
|
71
|
+
config: {"Number of tests" => tests_count_from_xcresult_report, "Number of failures" => failed_tests_count},
|
72
|
+
title: "Test Results"
|
73
|
+
)
|
74
|
+
end
|
75
|
+
|
76
|
+
def ordinalized_attempt
|
77
|
+
case @attempt
|
78
|
+
when 1
|
79
|
+
"#{@attempt}st"
|
80
|
+
when 2
|
81
|
+
"#{@attempt}nd"
|
82
|
+
when 3
|
83
|
+
"#{@attempt}rd"
|
84
|
+
else
|
85
|
+
"#{@attempt}th"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def update_scan_options(failed_tests)
|
90
|
+
scan_options = FastlaneScanHelper.scan_options_from_try_scan_options(@options)
|
91
|
+
scan_options[:only_testing] = failed_tests
|
71
92
|
scan_options[:skip_build] = true
|
72
93
|
scan_options[:test_without_building] = true
|
73
|
-
scan_options[:build_for_testing] = false
|
74
94
|
scan_options.delete(:skip_testing)
|
75
95
|
Scan.cache.clear
|
76
96
|
scan_options.each do |key, val|
|
77
97
|
next if val.nil?
|
78
98
|
|
79
|
-
Scan.config.set(key, val)
|
99
|
+
Scan.config.set(key, val)
|
80
100
|
FastlaneCore::UI.verbose("\tSetting #{key.to_s} to #{val}")
|
81
101
|
end
|
82
102
|
end
|
83
103
|
|
84
|
-
def
|
85
|
-
|
86
|
-
if
|
87
|
-
|
88
|
-
xcargs.slice!('build-for-testing')
|
89
|
-
end
|
90
|
-
if xcargs.include?('-quiet')
|
91
|
-
FastlaneCore::UI.important('Disabling -quiet as failing tests cannot be found with it enabled.')
|
92
|
-
xcargs.gsub!('-quiet', '')
|
93
|
-
end
|
94
|
-
xcargs.gsub!(/-parallel-testing-enabled(=|\s+)(YES|NO)/, '')
|
95
|
-
@options.select { |k,v| FastlaneScanHelper.valid_scan_keys.include?(k) }.merge({ xcargs: "#{xcargs} -parallel-testing-enabled NO " })
|
104
|
+
def essential_scan_config_updates
|
105
|
+
Scan.config[:result_bundle] = true
|
106
|
+
Scan.config[:build_for_testing] = nil if Scan.config[:build_for_testing]
|
107
|
+
Scan.config[:xcargs].slice!('build-for-testing') if Scan.config[:xcargs]&.include?('build-for-testing')
|
96
108
|
end
|
97
109
|
|
98
|
-
def
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
test_cases.each do |test_case|
|
104
|
-
next if test_case.xpath('failure').empty?
|
110
|
+
def parse_xcresult_report
|
111
|
+
report_options = FastlaneScanHelper.report_options
|
112
|
+
output_directory = report_options.instance_variable_get(:@output_directory)
|
113
|
+
xcresult_report_files = Dir["#{output_directory}/*.xcresult"]
|
114
|
+
raise FastlaneCore::UI.test_failure!('There are no xcresult reports to parse') if xcresult_report_files.empty?
|
105
115
|
|
106
|
-
|
107
|
-
|
108
|
-
only_testing << "#{suite_name}/#{test_class}/#{test_name}"
|
109
|
-
end
|
110
|
-
only_testing
|
116
|
+
FastlaneCore::UI.verbose("Parsing xcresult report by path: '#{xcresult_report_files.first}'")
|
117
|
+
JSON.parse(`xcrun xcresulttool get --format json --path #{xcresult_report_files.first}`)
|
111
118
|
end
|
112
119
|
|
113
|
-
def
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
def merge_junit_reports
|
126
|
-
old_junit_report = junit_report(cached: true)
|
127
|
-
new_junit_report = junit_report(cached: false)
|
128
|
-
|
129
|
-
new_junit_report.css("testsuites").zip(old_junit_report.css("testsuites")).each do |new_suites, old_suites|
|
130
|
-
old_suites.attributes["failures"].value = new_suites.attributes["failures"].value
|
131
|
-
new_suites.css("testsuite").zip(old_suites.css("testsuite")).each do |new_suite, old_suite|
|
132
|
-
old_suite.attributes["failures"].value = new_suite.attributes["failures"].value
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
new_junit_report.css('testcase').each do |node1|
|
137
|
-
old_junit_report.css('testcase').each do |node2|
|
138
|
-
node2.children = node1.children if node1['name'] == node2['name']
|
120
|
+
def failed_tests_from_xcresult_report
|
121
|
+
only_testing = []
|
122
|
+
parse_xcresult_report['issues']['testFailureSummaries']['_values'].each do |failed_test|
|
123
|
+
suite_name = failed_test['producingTarget']['_value']
|
124
|
+
test_path = failed_test['testCaseName']['_value']
|
125
|
+
begin
|
126
|
+
test_class = test_path.split('.').first
|
127
|
+
test_name = test_path.split('.')[1].split('(').first
|
128
|
+
rescue NoMethodError => _
|
129
|
+
test_class = test_path.split('[')[1].split(' ').first
|
130
|
+
test_name = test_path.split(' ')[1].split(']').first
|
139
131
|
end
|
132
|
+
only_testing << "#{suite_name}/#{test_class}/#{test_name}"
|
140
133
|
end
|
134
|
+
only_testing
|
135
|
+
end
|
141
136
|
|
142
|
-
|
137
|
+
def tests_count_from_xcresult_report
|
138
|
+
parse_xcresult_report['metrics']['testsCount']['_value']
|
143
139
|
end
|
144
140
|
end
|
145
141
|
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fastlane-plugin-try_scan
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexey Alter-Pesotskiy
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-06-
|
11
|
+
date: 2020-06-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: json
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: pry
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -122,20 +136,6 @@ dependencies:
|
|
122
136
|
- - ">="
|
123
137
|
- !ruby/object:Gem::Version
|
124
138
|
version: '0'
|
125
|
-
- !ruby/object:Gem::Dependency
|
126
|
-
name: nokogiri
|
127
|
-
requirement: !ruby/object:Gem::Requirement
|
128
|
-
requirements:
|
129
|
-
- - ">="
|
130
|
-
- !ruby/object:Gem::Version
|
131
|
-
version: '0'
|
132
|
-
type: :development
|
133
|
-
prerelease: false
|
134
|
-
version_requirements: !ruby/object:Gem::Requirement
|
135
|
-
requirements:
|
136
|
-
- - ">="
|
137
|
-
- !ruby/object:Gem::Version
|
138
|
-
version: '0'
|
139
139
|
- !ruby/object:Gem::Dependency
|
140
140
|
name: fastlane
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|