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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: da894046fe3bb6c6f7d3042ed03e9181a795d039c53ccd11bb94e40f0435d7c8
4
- data.tar.gz: 246cc29e1c0d255e2a822847de009f4efe1c5bee09bf2c79453a2fa146e5c241
3
+ metadata.gz: a36ff1388dd1ad1c95c0fd5041fc771d27f28b36c0d02773fa8205ae4812818b
4
+ data.tar.gz: c07a145c9d4f62d9901cb1bb2122662ca57c69a75d8dd500771799af215204a0
5
5
  SHA512:
6
- metadata.gz: bed442bb1ea7c2aacd84f8ee7989f03cf8fe1ef4ebe051d07f1b1261e9cee94abd355625c31d682faf9c077e978dd3876c2b6fd18497590dd919692e76640812
7
- data.tar.gz: 3e3938594bc73b62871689fb649fe6e5b74ce5c4fac8e935f805d2a3030e19f96db5424f8c78d32fd74cbe7922f3385483d2deb91d85c9d2920eaf3085e2d61a
6
+ metadata.gz: 8aeb03d459916e73d5281fc28293300acc6e375747954afd070ef34cc062e08d603dee4bea5e614850ca723f15f3e926a69e7f0efee1399c02320baee0d18100
7
+ data.tar.gz: 1ac8483c14d798c0b4f8f163846e2f3e922223dad285516674568998ada15a917633a34b243b571b5f2e11f3d2a8d1086390ac1c39abd3205cb3c17aedf26c4f
@@ -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 til it switch to fallback behavior 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.
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. Note that if one of 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 test files is run at least once across CI nodes. 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.
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 < MAX_RETRY.call
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
@@ -1,3 +1,3 @@
1
1
  module KnapsackPro
2
- VERSION = '2.2.1'
2
+ VERSION = '2.3.0'
3
3
  end
@@ -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.2.1
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-04 00:00:00.000000000 Z
11
+ date: 2020-09-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake