knapsack_pro 2.2.1 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/README.md +10 -2
- data/lib/knapsack_pro/client/connection.rb +17 -2
- data/lib/knapsack_pro/config/env.rb +11 -0
- data/lib/knapsack_pro/version.rb +1 -1
- data/spec/knapsack_pro/client/connection_spec.rb +104 -0
- data/spec/knapsack_pro/config/env_spec.rb +32 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a36ff1388dd1ad1c95c0fd5041fc771d27f28b36c0d02773fa8205ae4812818b
|
4
|
+
data.tar.gz: c07a145c9d4f62d9901cb1bb2122662ca57c69a75d8dd500771799af215204a0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8aeb03d459916e73d5281fc28293300acc6e375747954afd070ef34cc062e08d603dee4bea5e614850ca723f15f3e926a69e7f0efee1399c02320baee0d18100
|
7
|
+
data.tar.gz: 1ac8483c14d798c0b4f8f163846e2f3e922223dad285516674568998ada15a917633a34b243b571b5f2e11f3d2a8d1086390ac1c39abd3205cb3c17aedf26c4f
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
### 2.3.0
|
4
|
+
|
5
|
+
* When you use Regular Mode then try 6 attempts to connect to the API instead of 3 attempts
|
6
|
+
|
7
|
+
Add `KNAPSACK_PRO_MAX_REQUEST_RETRIES` environment variable to let user define their own number of request retries to the API. It is useful to set it to `0` for [forked repos](https://knapsackpro.com/faq/question/how-to-make-knapsack_pro-works-for-forked-repositories-of-my-project) when you want to relay on Fallback Mode.
|
8
|
+
|
9
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/pull/124
|
10
|
+
|
11
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v2.2.1...v2.3.0
|
12
|
+
|
3
13
|
### 2.2.1
|
4
14
|
|
5
15
|
* Improve detection of test file path in test-unit runner for test files with shared examples
|
data/README.md
CHANGED
@@ -2320,11 +2320,19 @@ There are a few ways to reproduce tests executed on CI node in your development
|
|
2320
2320
|
|
2321
2321
|
##### for knapsack_pro regular mode
|
2322
2322
|
|
2323
|
-
knapsack_pro gem will retry requests to Knapsack Pro API multiple times every few seconds
|
2323
|
+
knapsack_pro gem will retry requests to Knapsack Pro API multiple times every few seconds till it switchs to fallback behavior (Fallback Mode) and it will split test files across CI nodes based on popular test directory names. When knapsack_pro starts Fallback Mode then you will see a warning in the output.
|
2324
|
+
|
2325
|
+
Note there is an unlikely scenario when some of the CI nodes may start in Fallback Mode but others don't and then it could happen that some of test files might be skipped. You should [read this to learn more](https://github.com/KnapsackPro/knapsack_pro-ruby/pull/124) and decide if you like to use Fallback Mode when running tests with knapsack_pro Regular Mode.
|
2326
|
+
|
2327
|
+
If your CI provider allows to retry only one of parallel CI nodes then please [read about this edge case as well](#required-ci-configuration-if-you-use-retry-single-failed-ci-node-feature-on-your-ci-server-when-knapsack_pro_fixed_queue_splittrue-in-queue-mode-or-knapsack_pro_fixed_test_suite_splittrue-in-regular-mode).
|
2324
2328
|
|
2325
2329
|
##### for knapsack_pro queue mode
|
2326
2330
|
|
2327
|
-
knapsack_pro gem will retry requests to Knapsack Pro API multiple times every few seconds till it switches to fallback behavior and it will split test files across CI nodes based on popular test directory names.
|
2331
|
+
knapsack_pro gem will retry requests to Knapsack Pro API multiple times every few seconds till it switches to fallback behavior (Fallback Mode) and it will split test files across CI nodes based on popular test directory names.
|
2332
|
+
|
2333
|
+
Note that if one of the CI nodes will lose connection to Knapsack Pro API but other not then you may see that some of the test files will be executed on multiple CI nodes. **Fallback Mode guarantees each of the test files is run at least once across CI nodes when you use knapsack_pro in Queue Mode.** Thanks to that we know if the whole test suite is green or not. When knapsack_pro starts Fallback Mode then you will see a warning in the output.
|
2334
|
+
|
2335
|
+
If your CI provider allows to retry only one of parallel CI nodes then please [read about this edge case as well](#required-ci-configuration-if-you-use-retry-single-failed-ci-node-feature-on-your-ci-server-when-knapsack_pro_fixed_queue_splittrue-in-queue-mode-or-knapsack_pro_fixed_test_suite_splittrue-in-regular-mode).
|
2328
2336
|
|
2329
2337
|
#### How can I change log level?
|
2330
2338
|
|
@@ -4,7 +4,6 @@ module KnapsackPro
|
|
4
4
|
class ServerError < StandardError; end
|
5
5
|
|
6
6
|
TIMEOUT = 15
|
7
|
-
MAX_RETRY = -> { KnapsackPro::Config::Env.fallback_mode_enabled? ? 3 : 6 }
|
8
7
|
REQUEST_RETRY_TIMEBOX = 8
|
9
8
|
|
10
9
|
def initialize(action)
|
@@ -118,7 +117,7 @@ module KnapsackPro
|
|
118
117
|
rescue ServerError, Errno::ECONNREFUSED, Errno::ETIMEDOUT, Errno::EPIPE, EOFError, SocketError, Net::OpenTimeout, Net::ReadTimeout, OpenSSL::SSL::SSLError => e
|
119
118
|
logger.warn(e.inspect)
|
120
119
|
retries += 1
|
121
|
-
if retries <
|
120
|
+
if retries < max_request_retries
|
122
121
|
wait = retries * REQUEST_RETRY_TIMEBOX
|
123
122
|
logger.warn("Wait #{wait}s and retry request to Knapsack Pro API.")
|
124
123
|
print_every = 2 # seconds
|
@@ -156,6 +155,22 @@ module KnapsackPro
|
|
156
155
|
http.get(uri, json_headers)
|
157
156
|
end
|
158
157
|
end
|
158
|
+
|
159
|
+
def max_request_retries
|
160
|
+
# when user defined max request retries
|
161
|
+
return KnapsackPro::Config::Env.max_request_retries if KnapsackPro::Config::Env.max_request_retries
|
162
|
+
|
163
|
+
# when Fallback Mode is disabled then try more attempts to connect to the API
|
164
|
+
return 6 unless KnapsackPro::Config::Env.fallback_mode_enabled?
|
165
|
+
|
166
|
+
# when Regular Mode then try more attempts to connect to the API
|
167
|
+
# if only one CI node starts Fallback Mode instead of all then we can't guarantee all test files will be run
|
168
|
+
# https://github.com/KnapsackPro/knapsack_pro-ruby/pull/124
|
169
|
+
return 6 if KnapsackPro::Config::Env.regular_mode?
|
170
|
+
|
171
|
+
# default number of attempts
|
172
|
+
3
|
173
|
+
end
|
159
174
|
end
|
160
175
|
end
|
161
176
|
end
|
@@ -36,6 +36,13 @@ module KnapsackPro
|
|
36
36
|
).to_i
|
37
37
|
end
|
38
38
|
|
39
|
+
def max_request_retries
|
40
|
+
number = ENV['KNAPSACK_PRO_MAX_REQUEST_RETRIES']
|
41
|
+
if number
|
42
|
+
number.to_i
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
39
46
|
def commit_hash
|
40
47
|
ENV['KNAPSACK_PRO_COMMIT_HASH'] ||
|
41
48
|
ci_env_for(:commit_hash)
|
@@ -83,6 +90,10 @@ module KnapsackPro
|
|
83
90
|
recording_enabled == 'true'
|
84
91
|
end
|
85
92
|
|
93
|
+
def regular_mode?
|
94
|
+
recording_enabled?
|
95
|
+
end
|
96
|
+
|
86
97
|
def queue_recording_enabled
|
87
98
|
ENV['KNAPSACK_PRO_QUEUE_RECORDING_ENABLED']
|
88
99
|
end
|
data/lib/knapsack_pro/version.rb
CHANGED
@@ -108,6 +108,53 @@ shared_examples 'when retry request' do
|
|
108
108
|
expect(connection.errors?).to be true
|
109
109
|
end
|
110
110
|
|
111
|
+
context 'when max request retries defined' do
|
112
|
+
before do
|
113
|
+
expect(KnapsackPro::Config::Env).to receive(:max_request_retries).at_least(1).and_return(4)
|
114
|
+
end
|
115
|
+
|
116
|
+
it do
|
117
|
+
expect(logger).to receive(:debug).exactly(4).with("#{expected_http_method} http://api.knapsackpro.test:3000/v1/fake_endpoint")
|
118
|
+
expect(logger).to receive(:debug).exactly(4).with('API request UUID: fake-uuid')
|
119
|
+
expect(logger).to receive(:debug).exactly(4).with('API response:')
|
120
|
+
|
121
|
+
parsed_response = { 'error' => 'Internal Server Error' }
|
122
|
+
|
123
|
+
expect(logger).to receive(:error).exactly(4).with(parsed_response)
|
124
|
+
|
125
|
+
server_error = described_class::ServerError.new(parsed_response)
|
126
|
+
expect(logger).to receive(:warn).exactly(4).with(server_error.inspect)
|
127
|
+
|
128
|
+
expect(logger).to receive(:warn).with("Wait 8s and retry request to Knapsack Pro API.")
|
129
|
+
expect(logger).to receive(:warn).with("Next request in 8s...")
|
130
|
+
expect(logger).to receive(:warn).with("Next request in 6s...")
|
131
|
+
expect(logger).to receive(:warn).with("Next request in 4s...")
|
132
|
+
expect(logger).to receive(:warn).with("Next request in 2s...")
|
133
|
+
|
134
|
+
expect(logger).to receive(:warn).with("Wait 16s and retry request to Knapsack Pro API.")
|
135
|
+
expect(logger).to receive(:warn).with("Next request in 16s...")
|
136
|
+
expect(logger).to receive(:warn).with("Next request in 14s...")
|
137
|
+
expect(logger).to receive(:warn).with("Next request in 12s...")
|
138
|
+
expect(logger).to receive(:warn).with("Next request in 10s...")
|
139
|
+
expect(logger).to receive(:warn).with("Next request in 8s...")
|
140
|
+
expect(logger).to receive(:warn).with("Next request in 6s...")
|
141
|
+
expect(logger).to receive(:warn).with("Next request in 4s...")
|
142
|
+
expect(logger).to receive(:warn).with("Next request in 2s...")
|
143
|
+
|
144
|
+
expect(logger).to receive(:warn).with("Wait 24s and retry request to Knapsack Pro API.")
|
145
|
+
12.times do |i|
|
146
|
+
expect(logger).to receive(:warn).with("Next request in #{(i+1)*2}s...")
|
147
|
+
end
|
148
|
+
|
149
|
+
expect(Kernel).to receive(:sleep).exactly(4+8+12).with(2)
|
150
|
+
|
151
|
+
expect(subject).to eq(parsed_response)
|
152
|
+
|
153
|
+
expect(connection.success?).to be false
|
154
|
+
expect(connection.errors?).to be true
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
111
158
|
context 'when Fallback Mode is disabled' do
|
112
159
|
before do
|
113
160
|
expect(KnapsackPro::Config::Env).to receive(:fallback_mode_enabled?).at_least(1).and_return(false)
|
@@ -164,6 +211,63 @@ shared_examples 'when retry request' do
|
|
164
211
|
expect(connection.errors?).to be true
|
165
212
|
end
|
166
213
|
end
|
214
|
+
|
215
|
+
context 'when Regular Mode' do
|
216
|
+
before do
|
217
|
+
expect(KnapsackPro::Config::Env).to receive(:regular_mode?).at_least(1).and_return(true)
|
218
|
+
end
|
219
|
+
|
220
|
+
it do
|
221
|
+
expect(logger).to receive(:debug).exactly(6).with("#{expected_http_method} http://api.knapsackpro.test:3000/v1/fake_endpoint")
|
222
|
+
expect(logger).to receive(:debug).exactly(6).with('API request UUID: fake-uuid')
|
223
|
+
expect(logger).to receive(:debug).exactly(6).with('API response:')
|
224
|
+
|
225
|
+
parsed_response = { 'error' => 'Internal Server Error' }
|
226
|
+
|
227
|
+
expect(logger).to receive(:error).exactly(6).with(parsed_response)
|
228
|
+
|
229
|
+
server_error = described_class::ServerError.new(parsed_response)
|
230
|
+
expect(logger).to receive(:warn).exactly(6).with(server_error.inspect)
|
231
|
+
|
232
|
+
expect(logger).to receive(:warn).with("Wait 8s and retry request to Knapsack Pro API.")
|
233
|
+
expect(logger).to receive(:warn).with("Next request in 8s...")
|
234
|
+
expect(logger).to receive(:warn).with("Next request in 6s...")
|
235
|
+
expect(logger).to receive(:warn).with("Next request in 4s...")
|
236
|
+
expect(logger).to receive(:warn).with("Next request in 2s...")
|
237
|
+
|
238
|
+
expect(logger).to receive(:warn).with("Wait 16s and retry request to Knapsack Pro API.")
|
239
|
+
expect(logger).to receive(:warn).with("Next request in 16s...")
|
240
|
+
expect(logger).to receive(:warn).with("Next request in 14s...")
|
241
|
+
expect(logger).to receive(:warn).with("Next request in 12s...")
|
242
|
+
expect(logger).to receive(:warn).with("Next request in 10s...")
|
243
|
+
expect(logger).to receive(:warn).with("Next request in 8s...")
|
244
|
+
expect(logger).to receive(:warn).with("Next request in 6s...")
|
245
|
+
expect(logger).to receive(:warn).with("Next request in 4s...")
|
246
|
+
expect(logger).to receive(:warn).with("Next request in 2s...")
|
247
|
+
|
248
|
+
expect(logger).to receive(:warn).with("Wait 24s and retry request to Knapsack Pro API.")
|
249
|
+
12.times do |i|
|
250
|
+
expect(logger).to receive(:warn).with("Next request in #{(i+1)*2}s...")
|
251
|
+
end
|
252
|
+
|
253
|
+
expect(logger).to receive(:warn).with("Wait 32s and retry request to Knapsack Pro API.")
|
254
|
+
16.times do |i|
|
255
|
+
expect(logger).to receive(:warn).with("Next request in #{(i+1)*2}s...")
|
256
|
+
end
|
257
|
+
|
258
|
+
expect(logger).to receive(:warn).with("Wait 40s and retry request to Knapsack Pro API.")
|
259
|
+
20.times do |i|
|
260
|
+
expect(logger).to receive(:warn).with("Next request in #{(i+1)*2}s...")
|
261
|
+
end
|
262
|
+
|
263
|
+
expect(Kernel).to receive(:sleep).exactly(60).with(2)
|
264
|
+
|
265
|
+
expect(subject).to eq(parsed_response)
|
266
|
+
|
267
|
+
expect(connection.success?).to be false
|
268
|
+
expect(connection.errors?).to be true
|
269
|
+
end
|
270
|
+
end
|
167
271
|
end
|
168
272
|
end
|
169
273
|
|
@@ -100,6 +100,19 @@ describe KnapsackPro::Config::Env do
|
|
100
100
|
end
|
101
101
|
end
|
102
102
|
|
103
|
+
describe '.max_request_retries' do
|
104
|
+
subject { described_class.max_request_retries }
|
105
|
+
|
106
|
+
context 'when ENV exists' do
|
107
|
+
before { stub_const("ENV", { 'KNAPSACK_PRO_MAX_REQUEST_RETRIES' => '2' }) }
|
108
|
+
it { should eq 2 }
|
109
|
+
end
|
110
|
+
|
111
|
+
context "when ENV doesn't exist" do
|
112
|
+
it { should be_nil }
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
103
116
|
describe '.commit_hash' do
|
104
117
|
subject { described_class.commit_hash }
|
105
118
|
|
@@ -267,6 +280,25 @@ describe KnapsackPro::Config::Env do
|
|
267
280
|
end
|
268
281
|
end
|
269
282
|
|
283
|
+
|
284
|
+
describe '.regular_mode?' do
|
285
|
+
subject { described_class.regular_mode? }
|
286
|
+
|
287
|
+
before do
|
288
|
+
expect(described_class).to receive(:recording_enabled?).and_return(recording_enabled)
|
289
|
+
end
|
290
|
+
|
291
|
+
context 'when recording is enabled' do
|
292
|
+
let(:recording_enabled) { true }
|
293
|
+
it { should be true }
|
294
|
+
end
|
295
|
+
|
296
|
+
context 'when recording is not enabled' do
|
297
|
+
let(:recording_enabled) { false }
|
298
|
+
it { should be false }
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
270
302
|
describe '.recording_enabled?' do
|
271
303
|
subject { described_class.recording_enabled? }
|
272
304
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: knapsack_pro
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ArturT
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-09-
|
11
|
+
date: 2020-09-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|