knapsack_pro 8.3.3 → 9.0.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/.circleci/config.yml +1 -2
- data/.gitignore +0 -1
- data/CHANGELOG.md +23 -2
- data/README.md +1 -1
- data/knapsack_pro.gemspec +1 -1
- data/lib/knapsack_pro/client/api/v1/queues.rb +1 -0
- data/lib/knapsack_pro/client/connection.rb +97 -52
- data/lib/knapsack_pro/config/ci/github_actions.rb +6 -4
- data/lib/knapsack_pro/queue_allocator.rb +13 -12
- data/lib/knapsack_pro/version.rb +1 -1
- data/lib/knapsack_pro.rb +9 -3
- data/spec/integration/runners/fallback_spec.rb +4 -4
- data/spec/integration/runners/queue/cucumber_runner_fallback_spec.rb +4 -4
- data/spec/integration/runners/queue/minitest_runner_fallback_spec.rb +4 -4
- data/spec/integration/runners/queue/rspec_runner_fallback_spec.rb +4 -4
- data/spec/integration/runners/queue/rspec_runner_spec.rb +20 -20
- data/spec/knapsack_pro/client/api/v1/queues_spec.rb +3 -1
- data/spec/knapsack_pro/client/connection_spec.rb +19 -15
- data/spec/knapsack_pro/config/ci/github_actions_spec.rb +40 -18
- data/spec/knapsack_pro/config/env_spec.rb +330 -352
- data/spec/knapsack_pro/formatters/time_tracker_spec.rb +448 -0
- data/spec/knapsack_pro/pure/queue/rspec_pure_spec.rb +5 -5
- data/spec/knapsack_pro/test_case_detectors/rspec_test_example_detector_spec.rb +1 -1
- data/spec/knapsack_pro_spec.rb +63 -39
- data/spec_time_tracker/spec_helper.rb +29 -0
- metadata +6 -9
- data/bin/test +0 -15
- data/lib/knapsack_pro/logger_wrapper.rb +0 -22
- data/spec/knapsack_pro/formatters/time_tracker_specs.rb +0 -545
- data/spec/knapsack_pro/logger_wrapper_spec.rb +0 -21
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3f83ec80d7b3dcbd9415335f5f340e48908fbeaeee13e92203cb78df1232f82e
|
|
4
|
+
data.tar.gz: 19c08fe18b1555fd1a5d218b32d8baf1534e9cc87b63fc9d17d1c7ddb0129f46
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d00064e828c1a90a3f2001cbbbee5086f7ac565b6f6ffe015237b6cab12bbdcc48a6a6199f615aaf1ff73ec4bdf4c666c84df44a8e6bc792e4d33387f4c55d71
|
|
7
|
+
data.tar.gz: b5dd5757440d7e38a54a44c69fe0c650185ade87dc00b00ebf24242fb637e3a062cdb45b7b85e39eae28547cd8513ad888aa8c6488a3734750a44530c64b6596
|
data/.circleci/config.yml
CHANGED
|
@@ -65,7 +65,6 @@ jobs:
|
|
|
65
65
|
- run: bundle update rspec
|
|
66
66
|
- run: bundle exec rspec --version
|
|
67
67
|
- run: bundle exec rspec spec
|
|
68
|
-
- run: bundle exec ruby spec/knapsack_pro/formatters/time_tracker_specs.rb
|
|
69
68
|
|
|
70
69
|
integration-rspec:
|
|
71
70
|
parallelism: 1
|
|
@@ -292,7 +291,7 @@ jobs:
|
|
|
292
291
|
working_directory: ~/rails-app-with-knapsack_pro
|
|
293
292
|
command: |
|
|
294
293
|
# split by test examples AND a single CI node ||
|
|
295
|
-
export KNAPSACK_PRO_BRANCH="$CIRCLE_BRANCH--$CIRCLE_BUILD_NUM--queue--split--single-node"
|
|
294
|
+
export KNAPSACK_PRO_BRANCH="$CIRCLE_BRANCH--$CIRCLE_BUILD_NUM--queue--split--single-node--$CIRCLE_NODE_INDEX"
|
|
296
295
|
export KNAPSACK_PRO_FIXED_QUEUE_SPLIT=true
|
|
297
296
|
export KNAPSACK_PRO_RSPEC_SPLIT_BY_TEST_EXAMPLES=true
|
|
298
297
|
export KNAPSACK_PRO_CI_NODE_TOTAL=1
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -1,10 +1,31 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
###
|
|
3
|
+
### 9.0.0
|
|
4
|
+
|
|
5
|
+
* __(breaking change)__ Require Ruby >=3.0.0
|
|
6
|
+
* Implement IP rotation for Ruby <3.4 to mitigate connection errors
|
|
7
|
+
* Upon connection failure, log additional diagnostics to gather more context
|
|
8
|
+
* Change log format from `LEVEL -- : [knapsack_pro] ...` to `ERROR -- knapsack_pro: ...`
|
|
9
|
+
|
|
10
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/pull/313
|
|
11
|
+
|
|
12
|
+
* GitHub Actions: Detect either head branch in Pull Requests or short ref name (vs fully-formed ref) in the other cases
|
|
13
|
+
|
|
14
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/pull/308
|
|
15
|
+
|
|
16
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v8.4.0...v9.0.0
|
|
17
|
+
|
|
18
|
+
### 8.4.0
|
|
19
|
+
|
|
20
|
+
* Add a batch UUID to the V1 Queue API request payload to improve handling of retried requests
|
|
21
|
+
|
|
22
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/pull/307
|
|
23
|
+
|
|
24
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v8.3.3...v8.4.0
|
|
4
25
|
|
|
5
26
|
### 8.3.3
|
|
6
27
|
|
|
7
|
-
*
|
|
28
|
+
* Replace `Hash#sum` with `Hash#reduce` to fix a rare bug in the RSpec time tracker for a specific project
|
|
8
29
|
|
|
9
30
|
https://github.com/KnapsackPro/knapsack_pro-ruby/pull/305
|
|
10
31
|
|
data/README.md
CHANGED
|
@@ -67,7 +67,7 @@ bundle update knapsack_pro
|
|
|
67
67
|
RSpec:
|
|
68
68
|
|
|
69
69
|
```bash
|
|
70
|
-
|
|
70
|
+
bundle exec rspec
|
|
71
71
|
```
|
|
72
72
|
|
|
73
73
|
Scripted tests can be found in the [Rails App With Knapsack Pro repository](https://github.com/KnapsackPro/rails-app-with-knapsack_pro/blob/master/bin/knapsack_pro_all.rb).
|
data/knapsack_pro.gemspec
CHANGED
|
@@ -6,7 +6,7 @@ require 'knapsack_pro/version'
|
|
|
6
6
|
Gem::Specification.new do |spec|
|
|
7
7
|
spec.name = 'knapsack_pro'
|
|
8
8
|
spec.version = KnapsackPro::VERSION
|
|
9
|
-
spec.required_ruby_version = '>=
|
|
9
|
+
spec.required_ruby_version = '>= 3.0.0'
|
|
10
10
|
spec.authors = ['ArturT']
|
|
11
11
|
spec.email = ['support@knapsackpro.com']
|
|
12
12
|
spec.summary = %q{Knapsack Pro splits tests across parallel CI nodes and ensures each parallel job finish work at a similar time.}
|
|
@@ -19,6 +19,7 @@ module KnapsackPro
|
|
|
19
19
|
:node_index => args.fetch(:node_index),
|
|
20
20
|
:node_build_id => KnapsackPro::Config::Env.ci_node_build_id,
|
|
21
21
|
:user_seat => KnapsackPro::Config::Env.masked_user_seat,
|
|
22
|
+
batch_uuid: args.fetch(:batch_uuid)
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
if request_hash[:can_initialize_queue] && !request_hash[:attempt_connect_to_queue]
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'stringio'
|
|
4
|
+
|
|
3
5
|
module KnapsackPro
|
|
4
6
|
module Client
|
|
5
7
|
class Connection
|
|
@@ -10,6 +12,7 @@ module KnapsackPro
|
|
|
10
12
|
|
|
11
13
|
def initialize(action)
|
|
12
14
|
@action = action
|
|
15
|
+
@http_debug_output = StringIO.new
|
|
13
16
|
end
|
|
14
17
|
|
|
15
18
|
def call
|
|
@@ -17,7 +20,7 @@ module KnapsackPro
|
|
|
17
20
|
end
|
|
18
21
|
|
|
19
22
|
def success?
|
|
20
|
-
return false
|
|
23
|
+
return false unless response_body
|
|
21
24
|
|
|
22
25
|
status = http_response.code.to_i
|
|
23
26
|
status >= 200 && status < 500
|
|
@@ -29,6 +32,7 @@ module KnapsackPro
|
|
|
29
32
|
|
|
30
33
|
def api_code
|
|
31
34
|
return unless response_body
|
|
35
|
+
|
|
32
36
|
response_body['code']
|
|
33
37
|
end
|
|
34
38
|
|
|
@@ -45,20 +49,8 @@ module KnapsackPro
|
|
|
45
49
|
KnapsackPro.logger
|
|
46
50
|
end
|
|
47
51
|
|
|
48
|
-
def
|
|
49
|
-
KnapsackPro::Config::Env.endpoint
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def endpoint_url
|
|
53
|
-
endpoint + action.endpoint_path
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def request_hash
|
|
57
|
-
action.request_hash
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def request_body
|
|
61
|
-
request_hash.to_json
|
|
52
|
+
def endpoint_uri
|
|
53
|
+
URI.parse(KnapsackPro::Config::Env.endpoint + action.endpoint_path)
|
|
62
54
|
end
|
|
63
55
|
|
|
64
56
|
def json_headers
|
|
@@ -68,19 +60,20 @@ module KnapsackPro
|
|
|
68
60
|
'KNAPSACK-PRO-CLIENT-NAME' => client_name,
|
|
69
61
|
'KNAPSACK-PRO-CLIENT-VERSION' => KnapsackPro::VERSION,
|
|
70
62
|
'KNAPSACK-PRO-TEST-SUITE-TOKEN' => KnapsackPro::Config::Env.test_suite_token,
|
|
71
|
-
'KNAPSACK-PRO-CI-PROVIDER' => KnapsackPro::Config::Env.ci_provider
|
|
63
|
+
'KNAPSACK-PRO-CI-PROVIDER' => KnapsackPro::Config::Env.ci_provider
|
|
72
64
|
}.compact
|
|
73
65
|
end
|
|
74
66
|
|
|
75
67
|
def client_name
|
|
76
68
|
[
|
|
77
69
|
'knapsack_pro-ruby',
|
|
78
|
-
ENV['KNAPSACK_PRO_TEST_RUNNER']
|
|
70
|
+
ENV['KNAPSACK_PRO_TEST_RUNNER']
|
|
79
71
|
].compact.join('/')
|
|
80
72
|
end
|
|
81
73
|
|
|
82
74
|
def parse_response_body(body)
|
|
83
75
|
return '' if body == '' || body.nil?
|
|
76
|
+
|
|
84
77
|
JSON.parse(body)
|
|
85
78
|
rescue JSON::ParserError
|
|
86
79
|
nil
|
|
@@ -88,11 +81,8 @@ module KnapsackPro
|
|
|
88
81
|
|
|
89
82
|
def seed
|
|
90
83
|
return if @response_body.nil? || @response_body == ''
|
|
91
|
-
response_body['build_distribution_id']
|
|
92
|
-
end
|
|
93
84
|
|
|
94
|
-
|
|
95
|
-
!seed.nil?
|
|
85
|
+
response_body['build_distribution_id']
|
|
96
86
|
end
|
|
97
87
|
|
|
98
88
|
def make_request(&block)
|
|
@@ -103,9 +93,9 @@ module KnapsackPro
|
|
|
103
93
|
|
|
104
94
|
request_uuid = http_response.header['X-Request-Id'] || 'N/A'
|
|
105
95
|
|
|
106
|
-
logger.debug("#{action.http_method.to_s.upcase} #{
|
|
96
|
+
logger.debug("#{action.http_method.to_s.upcase} #{endpoint_uri}")
|
|
107
97
|
logger.debug("API request UUID: #{request_uuid}")
|
|
108
|
-
logger.debug("Test suite split seed: #{seed}")
|
|
98
|
+
logger.debug("Test suite split seed: #{seed}") unless seed.nil?
|
|
109
99
|
logger.debug('API response:')
|
|
110
100
|
if errors?
|
|
111
101
|
logger.error(response_body)
|
|
@@ -113,39 +103,95 @@ module KnapsackPro
|
|
|
113
103
|
logger.debug(response_body)
|
|
114
104
|
end
|
|
115
105
|
|
|
116
|
-
if server_error?
|
|
117
|
-
raise ServerError.new(response_body)
|
|
118
|
-
end
|
|
106
|
+
raise ServerError.new(response_body) if server_error?
|
|
119
107
|
|
|
120
108
|
response_body
|
|
121
|
-
rescue ServerError, Errno::ECONNREFUSED, Errno::ECONNRESET, Errno::ETIMEDOUT, Errno::EPIPE, EOFError,
|
|
122
|
-
|
|
123
|
-
logger.warn('Request failed due to:')
|
|
124
|
-
logger.warn(e.inspect)
|
|
109
|
+
rescue ServerError, Errno::ECONNREFUSED, Errno::ECONNRESET, Errno::ETIMEDOUT, Errno::EPIPE, EOFError,
|
|
110
|
+
SocketError, Net::OpenTimeout, Net::ReadTimeout, OpenSSL::SSL::SSLError => e
|
|
125
111
|
retries += 1
|
|
112
|
+
log_diagnostics(e, retries)
|
|
113
|
+
@http.set_debug_output(@http_debug_output) if retries == max_request_retries - 1
|
|
126
114
|
if retries < max_request_retries
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
(wait / print_every).ceil.times do |i|
|
|
130
|
-
if i == 0
|
|
131
|
-
logger.warn("Wait for #{wait}s before retrying the request to Knapsack Pro API.")
|
|
132
|
-
else
|
|
133
|
-
logger.warn("#{wait - i * print_every}s left before retry...")
|
|
134
|
-
end
|
|
135
|
-
Kernel.sleep(print_every)
|
|
136
|
-
end
|
|
115
|
+
backoff(retries)
|
|
116
|
+
rotate_ip
|
|
137
117
|
retry
|
|
138
118
|
else
|
|
139
119
|
response_body
|
|
140
120
|
end
|
|
141
121
|
end
|
|
142
122
|
|
|
123
|
+
def log_diagnostics(error, retries)
|
|
124
|
+
message = [
|
|
125
|
+
action.http_method.to_s.upcase,
|
|
126
|
+
endpoint_uri,
|
|
127
|
+
@http.ipaddr # value from @http.ipaddr= or nil
|
|
128
|
+
].compact.join(' ')
|
|
129
|
+
logger.warn(message)
|
|
130
|
+
logger.warn('Request failed due to:')
|
|
131
|
+
logger.warn(error.inspect)
|
|
132
|
+
return if retries < max_request_retries
|
|
133
|
+
|
|
134
|
+
error.backtrace.each { |line| logger.warn(line) }
|
|
135
|
+
logger.warn('Net::HTTP debug output:')
|
|
136
|
+
@http_debug_output.string.each_line { |line| logger.warn(line.chomp) }
|
|
137
|
+
|
|
138
|
+
require 'open3'
|
|
139
|
+
[
|
|
140
|
+
"dig #{endpoint_uri.host}",
|
|
141
|
+
"nslookup #{endpoint_uri.host}",
|
|
142
|
+
"curl -v #{endpoint_uri.host}:#{endpoint_uri.port}",
|
|
143
|
+
"nc -vz #{endpoint_uri.host} #{endpoint_uri.port}",
|
|
144
|
+
"openssl s_client -connect #{endpoint_uri.host}:#{endpoint_uri.port} < /dev/null",
|
|
145
|
+
'env'
|
|
146
|
+
].each do |cmd|
|
|
147
|
+
logger.warn(cmd)
|
|
148
|
+
logger.warn('=' * cmd.size)
|
|
149
|
+
begin
|
|
150
|
+
outerr, status = Open3.capture2e(cmd)
|
|
151
|
+
logger.warn("Exit status: #{status.exitstatus}")
|
|
152
|
+
outerr.each_line { |line| logger.warn(line.chomp) }
|
|
153
|
+
rescue Errno::ENOENT => e
|
|
154
|
+
logger.warn("Error: #{e}")
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def backoff(retries)
|
|
160
|
+
wait = retries * REQUEST_RETRY_TIMEBOX
|
|
161
|
+
print_every = 2 # seconds
|
|
162
|
+
(wait / print_every).ceil.times do |i|
|
|
163
|
+
if i.zero?
|
|
164
|
+
logger.warn("Wait for #{wait}s before retrying the request to the Knapsack Pro API.")
|
|
165
|
+
else
|
|
166
|
+
logger.warn("#{wait - i * print_every}s left before retry...")
|
|
167
|
+
end
|
|
168
|
+
Kernel.sleep(print_every)
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
143
172
|
def build_http(uri)
|
|
144
|
-
http = net_http.new(uri.host, uri.port)
|
|
145
|
-
http.use_ssl = (uri.scheme == 'https')
|
|
146
|
-
http.open_timeout = TIMEOUT
|
|
147
|
-
http.read_timeout = TIMEOUT
|
|
148
|
-
|
|
173
|
+
@http = net_http.new(uri.host, uri.port)
|
|
174
|
+
@http.use_ssl = (uri.scheme == 'https')
|
|
175
|
+
@http.open_timeout = TIMEOUT
|
|
176
|
+
@http.read_timeout = TIMEOUT
|
|
177
|
+
rotate_ip
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def rotate_ip
|
|
181
|
+
# Ruby v3.4 implements Happy Eyeballs Version 2 (RFC 8305)
|
|
182
|
+
return if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.4')
|
|
183
|
+
|
|
184
|
+
@ipaddrs ||=
|
|
185
|
+
begin
|
|
186
|
+
require 'resolv'
|
|
187
|
+
resolvers = [
|
|
188
|
+
Resolv::Hosts.new,
|
|
189
|
+
Resolv::DNS.new(Resolv::DNS::Config.default_config_hash.merge(use_ipv6: false))
|
|
190
|
+
]
|
|
191
|
+
Resolv.new(resolvers).getaddresses(endpoint_uri.host).shuffle
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
@http.ipaddr = @ipaddrs.rotate!.first
|
|
149
195
|
end
|
|
150
196
|
|
|
151
197
|
def net_http
|
|
@@ -157,19 +203,18 @@ module KnapsackPro
|
|
|
157
203
|
end
|
|
158
204
|
|
|
159
205
|
def post
|
|
160
|
-
|
|
161
|
-
http = build_http(uri)
|
|
206
|
+
build_http(endpoint_uri)
|
|
162
207
|
make_request do
|
|
163
|
-
http.post(
|
|
208
|
+
@http.post(endpoint_uri.path, action.request_hash.to_json, json_headers)
|
|
164
209
|
end
|
|
165
210
|
end
|
|
166
211
|
|
|
167
212
|
def get
|
|
168
|
-
uri =
|
|
169
|
-
uri.query = URI.encode_www_form(request_hash)
|
|
170
|
-
|
|
213
|
+
uri = endpoint_uri
|
|
214
|
+
uri.query = URI.encode_www_form(action.request_hash)
|
|
215
|
+
build_http(uri)
|
|
171
216
|
make_request do
|
|
172
|
-
http.get(uri, json_headers)
|
|
217
|
+
@http.get(uri, json_headers)
|
|
173
218
|
end
|
|
174
219
|
end
|
|
175
220
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# https://
|
|
3
|
+
# https://docs.github.com/en/actions/reference/workflows-and-actions/variables
|
|
4
4
|
module KnapsackPro
|
|
5
5
|
module Config
|
|
6
6
|
module CI
|
|
@@ -31,9 +31,11 @@ module KnapsackPro
|
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
def branch
|
|
34
|
-
#
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
# `on: push` has `GITHUB_HEAD_REF=`
|
|
35
|
+
head_ref = ENV.fetch('GITHUB_HEAD_REF', '')
|
|
36
|
+
return head_ref unless head_ref == ''
|
|
37
|
+
|
|
38
|
+
ENV['GITHUB_REF_NAME'] || ENV['GITHUB_SHA']
|
|
37
39
|
end
|
|
38
40
|
|
|
39
41
|
def project_dir
|
|
@@ -41,26 +41,26 @@ module KnapsackPro
|
|
|
41
41
|
@fallback_mode = false
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
-
def test_file_paths(can_initialize_queue, executed_test_files)
|
|
44
|
+
def test_file_paths(can_initialize_queue, executed_test_files, batch_uuid: SecureRandom.uuid)
|
|
45
45
|
return [] if @fallback_mode
|
|
46
46
|
|
|
47
|
-
batch = pull_tests_from_queue(can_initialize_queue)
|
|
47
|
+
batch = pull_tests_from_queue(can_initialize_queue, batch_uuid)
|
|
48
48
|
|
|
49
49
|
return switch_to_fallback_mode(executed_test_files: executed_test_files) if batch.connection_failed?
|
|
50
50
|
return normalize_test_files(batch.test_files) if batch.queue_exists?
|
|
51
51
|
|
|
52
52
|
test_files_result = test_suite.calculate_test_files
|
|
53
53
|
|
|
54
|
-
return try_initializing_queue(test_files_result.test_files) if test_files_result.quick?
|
|
54
|
+
return try_initializing_queue(test_files_result.test_files, batch_uuid) if test_files_result.quick?
|
|
55
55
|
|
|
56
56
|
# The tests to run were found slowly. By that time, the queue could have already been initialized by another CI node.
|
|
57
57
|
# Attempt to pull tests from the queue to avoid the attempt to initialize the queue unnecessarily (queue initialization is an expensive request with a big test files payload).
|
|
58
|
-
batch = pull_tests_from_queue(can_initialize_queue)
|
|
58
|
+
batch = pull_tests_from_queue(can_initialize_queue, batch_uuid)
|
|
59
59
|
|
|
60
60
|
return switch_to_fallback_mode(executed_test_files: executed_test_files) if batch.connection_failed?
|
|
61
61
|
return normalize_test_files(batch.test_files) if batch.queue_exists?
|
|
62
62
|
|
|
63
|
-
try_initializing_queue(test_files_result.test_files)
|
|
63
|
+
try_initializing_queue(test_files_result.test_files, batch_uuid)
|
|
64
64
|
end
|
|
65
65
|
|
|
66
66
|
private
|
|
@@ -80,7 +80,7 @@ module KnapsackPro
|
|
|
80
80
|
KnapsackPro::TestFilePresenter.paths(decrypted_test_files)
|
|
81
81
|
end
|
|
82
82
|
|
|
83
|
-
def build_action(can_initialize_queue:, attempt_connect_to_queue:, test_files: nil)
|
|
83
|
+
def build_action(can_initialize_queue:, attempt_connect_to_queue:, batch_uuid:, test_files: nil)
|
|
84
84
|
if can_initialize_queue && !attempt_connect_to_queue
|
|
85
85
|
raise 'Test files are required when initializing a new queue.' if test_files.nil?
|
|
86
86
|
test_files = KnapsackPro::Crypto::Encryptor.call(test_files)
|
|
@@ -95,25 +95,26 @@ module KnapsackPro
|
|
|
95
95
|
node_index: ci_node_index,
|
|
96
96
|
node_build_id: ci_node_build_id,
|
|
97
97
|
test_files: test_files,
|
|
98
|
+
batch_uuid: batch_uuid
|
|
98
99
|
)
|
|
99
100
|
end
|
|
100
101
|
|
|
101
|
-
def pull_tests_from_queue(can_initialize_queue)
|
|
102
|
-
action = build_action(can_initialize_queue: can_initialize_queue, attempt_connect_to_queue: can_initialize_queue)
|
|
102
|
+
def pull_tests_from_queue(can_initialize_queue, batch_uuid)
|
|
103
|
+
action = build_action(can_initialize_queue: can_initialize_queue, attempt_connect_to_queue: can_initialize_queue, batch_uuid: batch_uuid)
|
|
103
104
|
connection = KnapsackPro::Client::Connection.new(action)
|
|
104
105
|
response = connection.call
|
|
105
106
|
Batch.new(connection, response)
|
|
106
107
|
end
|
|
107
108
|
|
|
108
|
-
def initialize_queue(tests_to_run)
|
|
109
|
-
action = build_action(can_initialize_queue: true, attempt_connect_to_queue: false, test_files: tests_to_run)
|
|
109
|
+
def initialize_queue(tests_to_run, batch_uuid)
|
|
110
|
+
action = build_action(can_initialize_queue: true, attempt_connect_to_queue: false, batch_uuid: batch_uuid, test_files: tests_to_run)
|
|
110
111
|
connection = KnapsackPro::Client::Connection.new(action)
|
|
111
112
|
response = connection.call
|
|
112
113
|
Batch.new(connection, response)
|
|
113
114
|
end
|
|
114
115
|
|
|
115
|
-
def try_initializing_queue(tests)
|
|
116
|
-
result = initialize_queue(tests)
|
|
116
|
+
def try_initializing_queue(tests, batch_uuid)
|
|
117
|
+
result = initialize_queue(tests, batch_uuid)
|
|
117
118
|
|
|
118
119
|
return switch_to_fallback_mode(executed_test_files: []) if result.connection_failed?
|
|
119
120
|
|
data/lib/knapsack_pro/version.rb
CHANGED
data/lib/knapsack_pro.rb
CHANGED
|
@@ -29,7 +29,6 @@ require_relative 'knapsack_pro/config/ci/heroku'
|
|
|
29
29
|
require_relative 'knapsack_pro/config/env'
|
|
30
30
|
require_relative 'knapsack_pro/config/env_generator'
|
|
31
31
|
require_relative 'knapsack_pro/config/temp_files'
|
|
32
|
-
require_relative 'knapsack_pro/logger_wrapper'
|
|
33
32
|
require_relative 'knapsack_pro/client/api/action'
|
|
34
33
|
require_relative 'knapsack_pro/client/api/v1/base'
|
|
35
34
|
require_relative 'knapsack_pro/client/api/v1/build_distributions'
|
|
@@ -91,6 +90,11 @@ require 'knapsack_pro/railtie' if defined?(Rails::Railtie)
|
|
|
91
90
|
|
|
92
91
|
module KnapsackPro
|
|
93
92
|
class << self
|
|
93
|
+
attr_writer :stdout
|
|
94
|
+
def stdout
|
|
95
|
+
@stdout ||= STDOUT
|
|
96
|
+
end
|
|
97
|
+
|
|
94
98
|
def root
|
|
95
99
|
File.expand_path('../..', __FILE__)
|
|
96
100
|
end
|
|
@@ -103,15 +107,17 @@ module KnapsackPro
|
|
|
103
107
|
end
|
|
104
108
|
|
|
105
109
|
unless @logger
|
|
106
|
-
default_logger = ::Logger.new(
|
|
110
|
+
default_logger = ::Logger.new(stdout)
|
|
107
111
|
default_logger.level = KnapsackPro::Config::Env.log_level
|
|
108
112
|
self.logger = default_logger
|
|
109
113
|
end
|
|
114
|
+
|
|
110
115
|
@logger
|
|
111
116
|
end
|
|
112
117
|
|
|
113
118
|
def logger=(logger)
|
|
114
|
-
@logger =
|
|
119
|
+
@logger = logger
|
|
120
|
+
@logger.progname = 'knapsack_pro'
|
|
115
121
|
end
|
|
116
122
|
|
|
117
123
|
def reset_logger!
|
|
@@ -68,7 +68,7 @@ require 'tempfile'
|
|
|
68
68
|
|
|
69
69
|
expect(actual.exit_code).to eq 1
|
|
70
70
|
|
|
71
|
-
expect(actual.stdout).to include('ERROR -- :
|
|
71
|
+
expect(actual.stdout).to include('ERROR -- knapsack_pro: Fallback Mode was disabled with KNAPSACK_PRO_FALLBACK_MODE_ENABLED=false. Please restart this CI node to retry tests. Most likely Fallback Mode was disabled due to https://knapsackpro.com/perma/ruby/regular-mode-connection-error-with-fallback-enabled-false')
|
|
72
72
|
end
|
|
73
73
|
|
|
74
74
|
context 'with a user defined exit code' do
|
|
@@ -85,7 +85,7 @@ require 'tempfile'
|
|
|
85
85
|
|
|
86
86
|
expect(actual.exit_code).to eq 123
|
|
87
87
|
|
|
88
|
-
expect(actual.stdout).to include('ERROR -- :
|
|
88
|
+
expect(actual.stdout).to include('ERROR -- knapsack_pro: Fallback Mode was disabled with KNAPSACK_PRO_FALLBACK_MODE_ENABLED=false. Please restart this CI node to retry tests. Most likely Fallback Mode was disabled due to https://knapsackpro.com/perma/ruby/regular-mode-connection-error-with-fallback-enabled-false')
|
|
89
89
|
end
|
|
90
90
|
end
|
|
91
91
|
end
|
|
@@ -106,7 +106,7 @@ require 'tempfile'
|
|
|
106
106
|
|
|
107
107
|
expect(actual.exit_code).to eq 1
|
|
108
108
|
|
|
109
|
-
expect(actual.stdout).to include('ERROR -- :
|
|
109
|
+
expect(actual.stdout).to include('ERROR -- knapsack_pro: knapsack_pro gem could not connect to Knapsack Pro API and the Fallback Mode cannot be used this time. Running tests in Fallback Mode are not allowed for retried parallel CI node to avoid running the wrong set of tests. Please manually retry this parallel job on your CI server then knapsack_pro gem will try to connect to Knapsack Pro API again and will run a correct set of tests for this CI node. Learn more https://knapsackpro.com/perma/ruby/regular-mode-connection-error-with-fallback-enabled-true-and-positive-retry-count')
|
|
110
110
|
end
|
|
111
111
|
|
|
112
112
|
context 'with a user defined exit code' do
|
|
@@ -123,7 +123,7 @@ require 'tempfile'
|
|
|
123
123
|
|
|
124
124
|
expect(actual.exit_code).to eq 123
|
|
125
125
|
|
|
126
|
-
expect(actual.stdout).to include('ERROR -- :
|
|
126
|
+
expect(actual.stdout).to include('ERROR -- knapsack_pro: knapsack_pro gem could not connect to Knapsack Pro API and the Fallback Mode cannot be used this time. Running tests in Fallback Mode are not allowed for retried parallel CI node to avoid running the wrong set of tests. Please manually retry this parallel job on your CI server then knapsack_pro gem will try to connect to Knapsack Pro API again and will run a correct set of tests for this CI node. Learn more https://knapsackpro.com/perma/ruby/regular-mode-connection-error-with-fallback-enabled-true-and-positive-retry-count')
|
|
127
127
|
end
|
|
128
128
|
end
|
|
129
129
|
end
|
|
@@ -67,7 +67,7 @@ describe "#{KnapsackPro::Runners::Queue::CucumberRunner} Fallback - Integration
|
|
|
67
67
|
|
|
68
68
|
expect(actual.exit_code).to eq 1
|
|
69
69
|
|
|
70
|
-
expect(actual.stdout).to include('ERROR -- :
|
|
70
|
+
expect(actual.stdout).to include('ERROR -- knapsack_pro: Fallback Mode was disabled with KNAPSACK_PRO_FALLBACK_MODE_ENABLED=false. Please restart this CI node to retry tests. Most likely Fallback Mode was disabled due to https://knapsackpro.com/perma/ruby/queue-mode-connection-error-with-fallback-enabled-false')
|
|
71
71
|
end
|
|
72
72
|
|
|
73
73
|
context 'with a user defined exit code' do
|
|
@@ -84,7 +84,7 @@ describe "#{KnapsackPro::Runners::Queue::CucumberRunner} Fallback - Integration
|
|
|
84
84
|
|
|
85
85
|
expect(actual.exit_code).to eq 123
|
|
86
86
|
|
|
87
|
-
expect(actual.stdout).to include('ERROR -- :
|
|
87
|
+
expect(actual.stdout).to include('ERROR -- knapsack_pro: Fallback Mode was disabled with KNAPSACK_PRO_FALLBACK_MODE_ENABLED=false. Please restart this CI node to retry tests. Most likely Fallback Mode was disabled due to https://knapsackpro.com/perma/ruby/queue-mode-connection-error-with-fallback-enabled-false')
|
|
88
88
|
end
|
|
89
89
|
end
|
|
90
90
|
end
|
|
@@ -105,7 +105,7 @@ describe "#{KnapsackPro::Runners::Queue::CucumberRunner} Fallback - Integration
|
|
|
105
105
|
|
|
106
106
|
expect(actual.exit_code).to eq 1
|
|
107
107
|
|
|
108
|
-
expect(actual.stdout).to include('ERROR -- :
|
|
108
|
+
expect(actual.stdout).to include('ERROR -- knapsack_pro: knapsack_pro gem could not connect to Knapsack Pro API and the Fallback Mode cannot be used this time. Running tests in Fallback Mode are not allowed for retried parallel CI node to avoid running the wrong set of tests. Please manually retry this parallel job on your CI server then knapsack_pro gem will try to connect to Knapsack Pro API again and will run a correct set of tests for this CI node. Learn more https://knapsackpro.com/perma/ruby/queue-mode-connection-error-with-fallback-enabled-true-and-positive-retry-count')
|
|
109
109
|
end
|
|
110
110
|
|
|
111
111
|
context 'with a user defined exit code' do
|
|
@@ -122,7 +122,7 @@ describe "#{KnapsackPro::Runners::Queue::CucumberRunner} Fallback - Integration
|
|
|
122
122
|
|
|
123
123
|
expect(actual.exit_code).to eq 123
|
|
124
124
|
|
|
125
|
-
expect(actual.stdout).to include('ERROR -- :
|
|
125
|
+
expect(actual.stdout).to include('ERROR -- knapsack_pro: knapsack_pro gem could not connect to Knapsack Pro API and the Fallback Mode cannot be used this time. Running tests in Fallback Mode are not allowed for retried parallel CI node to avoid running the wrong set of tests. Please manually retry this parallel job on your CI server then knapsack_pro gem will try to connect to Knapsack Pro API again and will run a correct set of tests for this CI node. Learn more https://knapsackpro.com/perma/ruby/queue-mode-connection-error-with-fallback-enabled-true-and-positive-retry-count')
|
|
126
126
|
end
|
|
127
127
|
end
|
|
128
128
|
end
|
|
@@ -67,7 +67,7 @@ describe "#{KnapsackPro::Runners::Queue::MinitestRunner} Fallback - Integration
|
|
|
67
67
|
|
|
68
68
|
expect(actual.exit_code).to eq 1
|
|
69
69
|
|
|
70
|
-
expect(actual.stdout).to include('ERROR -- :
|
|
70
|
+
expect(actual.stdout).to include('ERROR -- knapsack_pro: Fallback Mode was disabled with KNAPSACK_PRO_FALLBACK_MODE_ENABLED=false. Please restart this CI node to retry tests. Most likely Fallback Mode was disabled due to https://knapsackpro.com/perma/ruby/queue-mode-connection-error-with-fallback-enabled-false')
|
|
71
71
|
end
|
|
72
72
|
|
|
73
73
|
context 'with a user defined exit code' do
|
|
@@ -84,7 +84,7 @@ describe "#{KnapsackPro::Runners::Queue::MinitestRunner} Fallback - Integration
|
|
|
84
84
|
|
|
85
85
|
expect(actual.exit_code).to eq 123
|
|
86
86
|
|
|
87
|
-
expect(actual.stdout).to include('ERROR -- :
|
|
87
|
+
expect(actual.stdout).to include('ERROR -- knapsack_pro: Fallback Mode was disabled with KNAPSACK_PRO_FALLBACK_MODE_ENABLED=false. Please restart this CI node to retry tests. Most likely Fallback Mode was disabled due to https://knapsackpro.com/perma/ruby/queue-mode-connection-error-with-fallback-enabled-false')
|
|
88
88
|
end
|
|
89
89
|
end
|
|
90
90
|
end
|
|
@@ -105,7 +105,7 @@ describe "#{KnapsackPro::Runners::Queue::MinitestRunner} Fallback - Integration
|
|
|
105
105
|
|
|
106
106
|
expect(actual.exit_code).to eq 1
|
|
107
107
|
|
|
108
|
-
expect(actual.stdout).to include('ERROR -- :
|
|
108
|
+
expect(actual.stdout).to include('ERROR -- knapsack_pro: knapsack_pro gem could not connect to Knapsack Pro API and the Fallback Mode cannot be used this time. Running tests in Fallback Mode are not allowed for retried parallel CI node to avoid running the wrong set of tests. Please manually retry this parallel job on your CI server then knapsack_pro gem will try to connect to Knapsack Pro API again and will run a correct set of tests for this CI node. Learn more https://knapsackpro.com/perma/ruby/queue-mode-connection-error-with-fallback-enabled-true-and-positive-retry-count')
|
|
109
109
|
end
|
|
110
110
|
|
|
111
111
|
context 'with a user defined exit code' do
|
|
@@ -122,7 +122,7 @@ describe "#{KnapsackPro::Runners::Queue::MinitestRunner} Fallback - Integration
|
|
|
122
122
|
|
|
123
123
|
expect(actual.exit_code).to eq 123
|
|
124
124
|
|
|
125
|
-
expect(actual.stdout).to include('ERROR -- :
|
|
125
|
+
expect(actual.stdout).to include('ERROR -- knapsack_pro: knapsack_pro gem could not connect to Knapsack Pro API and the Fallback Mode cannot be used this time. Running tests in Fallback Mode are not allowed for retried parallel CI node to avoid running the wrong set of tests. Please manually retry this parallel job on your CI server then knapsack_pro gem will try to connect to Knapsack Pro API again and will run a correct set of tests for this CI node. Learn more https://knapsackpro.com/perma/ruby/queue-mode-connection-error-with-fallback-enabled-true-and-positive-retry-count')
|
|
126
126
|
end
|
|
127
127
|
end
|
|
128
128
|
end
|
|
@@ -67,7 +67,7 @@ describe "#{KnapsackPro::Runners::Queue::RSpecRunner} Fallback - Integration tes
|
|
|
67
67
|
|
|
68
68
|
expect(actual.exit_code).to eq 1
|
|
69
69
|
|
|
70
|
-
expect(actual.stdout).to include('ERROR -- :
|
|
70
|
+
expect(actual.stdout).to include('ERROR -- knapsack_pro: Fallback Mode was disabled with KNAPSACK_PRO_FALLBACK_MODE_ENABLED=false. Please restart this CI node to retry tests. Most likely Fallback Mode was disabled due to https://knapsackpro.com/perma/ruby/queue-mode-connection-error-with-fallback-enabled-false')
|
|
71
71
|
expect(actual.stdout).to include(/Finished in .* seconds \(files took .* seconds to load\)/)
|
|
72
72
|
expect(actual.stdout).to include('0 examples, 0 failures')
|
|
73
73
|
end
|
|
@@ -86,7 +86,7 @@ describe "#{KnapsackPro::Runners::Queue::RSpecRunner} Fallback - Integration tes
|
|
|
86
86
|
|
|
87
87
|
expect(actual.exit_code).to eq 123
|
|
88
88
|
|
|
89
|
-
expect(actual.stdout).to include('ERROR -- :
|
|
89
|
+
expect(actual.stdout).to include('ERROR -- knapsack_pro: Fallback Mode was disabled with KNAPSACK_PRO_FALLBACK_MODE_ENABLED=false. Please restart this CI node to retry tests. Most likely Fallback Mode was disabled due to https://knapsackpro.com/perma/ruby/queue-mode-connection-error-with-fallback-enabled-false')
|
|
90
90
|
expect(actual.stdout).to include(/Finished in .* seconds \(files took .* seconds to load\)/)
|
|
91
91
|
expect(actual.stdout).to include('0 examples, 0 failures')
|
|
92
92
|
end
|
|
@@ -109,7 +109,7 @@ describe "#{KnapsackPro::Runners::Queue::RSpecRunner} Fallback - Integration tes
|
|
|
109
109
|
|
|
110
110
|
expect(actual.exit_code).to eq 1
|
|
111
111
|
|
|
112
|
-
expect(actual.stdout).to include('ERROR -- :
|
|
112
|
+
expect(actual.stdout).to include('ERROR -- knapsack_pro: knapsack_pro gem could not connect to Knapsack Pro API and the Fallback Mode cannot be used this time. Running tests in Fallback Mode are not allowed for retried parallel CI node to avoid running the wrong set of tests. Please manually retry this parallel job on your CI server then knapsack_pro gem will try to connect to Knapsack Pro API again and will run a correct set of tests for this CI node. Learn more https://knapsackpro.com/perma/ruby/queue-mode-connection-error-with-fallback-enabled-true-and-positive-retry-count')
|
|
113
113
|
expect(actual.stdout).to include(/Finished in .* seconds \(files took .* seconds to load\)/)
|
|
114
114
|
expect(actual.stdout).to include('0 examples, 0 failures')
|
|
115
115
|
end
|
|
@@ -128,7 +128,7 @@ describe "#{KnapsackPro::Runners::Queue::RSpecRunner} Fallback - Integration tes
|
|
|
128
128
|
|
|
129
129
|
expect(actual.exit_code).to eq 123
|
|
130
130
|
|
|
131
|
-
expect(actual.stdout).to include('ERROR -- :
|
|
131
|
+
expect(actual.stdout).to include('ERROR -- knapsack_pro: knapsack_pro gem could not connect to Knapsack Pro API and the Fallback Mode cannot be used this time. Running tests in Fallback Mode are not allowed for retried parallel CI node to avoid running the wrong set of tests. Please manually retry this parallel job on your CI server then knapsack_pro gem will try to connect to Knapsack Pro API again and will run a correct set of tests for this CI node. Learn more https://knapsackpro.com/perma/ruby/queue-mode-connection-error-with-fallback-enabled-true-and-positive-retry-count')
|
|
132
132
|
expect(actual.stdout).to include(/Finished in .* seconds \(files took .* seconds to load\)/)
|
|
133
133
|
expect(actual.stdout).to include('0 examples, 0 failures')
|
|
134
134
|
end
|