knapsack_pro 2.2.1 → 2.7.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: e72536de9d4d9ec4a02e935742375b9d8023522f9c21ac8340a991bfdc7982cb
4
+ data.tar.gz: b7694088ff854a5579ec160fbb08c3219986a95512c2feea15ac6a359dc7aff5
5
5
  SHA512:
6
- metadata.gz: bed442bb1ea7c2aacd84f8ee7989f03cf8fe1ef4ebe051d07f1b1261e9cee94abd355625c31d682faf9c077e978dd3876c2b6fd18497590dd919692e76640812
7
- data.tar.gz: 3e3938594bc73b62871689fb649fe6e5b74ce5c4fac8e935f805d2a3030e19f96db5424f8c78d32fd74cbe7922f3385483d2deb91d85c9d2920eaf3085e2d61a
6
+ metadata.gz: 408aaada7954066b2a3266897aa9b145ce53f2f7409f99f4c8915e122c5deef0818bc14503da59cab1f20c1376a4b205466089c14eaa8c9cd1943699298f8d86
7
+ data.tar.gz: 85eef879c155557825347ede8671f1b65d9832a8e8b379e94efaf61573cbd676082d43d6219099a35cad008266ef8e16cd719553397c5b71f775ad0ab76f7e79
@@ -1,5 +1,47 @@
1
1
  # Change Log
2
2
 
3
+ ### 2.7.0
4
+
5
+ * Add support for env var `KNAPSACK_PRO_TEST_FILE_LIST_SOURCE_FILE` to allow accepting file containing test files to run
6
+
7
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/129
8
+
9
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v2.6.0...v2.7.0
10
+
11
+ ### 2.6.0
12
+
13
+ * Improve logger to show failed requests URL and when retry will happen
14
+
15
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/127
16
+
17
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v2.5.0...v2.6.0
18
+
19
+ ### 2.5.0
20
+
21
+ * Add production branch to non encryptable branches names
22
+
23
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/126
24
+
25
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v2.4.0...v2.5.0
26
+
27
+ ### 2.4.0
28
+
29
+ * Update list of non encryptable branches
30
+
31
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/125
32
+
33
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v2.3.0...v2.4.0
34
+
35
+ ### 2.3.0
36
+
37
+ * When you use Regular Mode then try 6 attempts to connect to the API instead of 3 attempts
38
+
39
+ 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 rely on Fallback Mode.
40
+
41
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/124
42
+
43
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v2.2.1...v2.3.0
44
+
3
45
  ### 2.2.1
4
46
 
5
47
  * 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 switches 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 loses connection to Knapsack Pro API but others don't, then some of the test files may 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
 
@@ -2464,12 +2472,13 @@ Below example is for rspec. You can change `$KNAPSACK_PRO_TEST_SUITE_TOKEN_RSPEC
2464
2472
  if [ "$KNAPSACK_PRO_TEST_SUITE_TOKEN_RSPEC" = "" ]; then
2465
2473
  KNAPSACK_PRO_ENDPOINT=https://api-disabled-for-fork.knapsackpro.com \
2466
2474
  KNAPSACK_PRO_TEST_SUITE_TOKEN_RSPEC=disabled-for-fork \
2475
+ KNAPSACK_PRO_MAX_REQUEST_RETRIES=0 \
2467
2476
  bundle exec rake knapsack_pro:rspec # use Regular Mode here always
2468
2477
  else
2469
2478
  # Regular Mode
2470
2479
  bundle exec rake knapsack_pro:rspec
2471
2480
 
2472
- # You can use Queue Mode instead of Regular Mode if you like
2481
+ # or you can use Queue Mode instead of Regular Mode if you like
2473
2482
  # bundle exec rake knapsack_pro:queue:rspec
2474
2483
  fi
2475
2484
  ```
@@ -3073,7 +3082,9 @@ The test file pattern and exclude pattern support any glob pattern handled by [`
3073
3082
 
3074
3083
  #### How to run a specific list of test files or only some tests from test file?
3075
3084
 
3076
- :information_source: If you don't want to use the pattern [`KNAPSACK_PRO_TEST_FILE_PATTERN`](#how-can-i-run-tests-from-multiple-directories) to define a list of tests to run then read below.
3085
+ :information_source: If you don't want to use the pattern [`KNAPSACK_PRO_TEST_FILE_PATTERN`](#how-can-i-run-tests-from-multiple-directories) to define a list of tests to run then read below two options.
3086
+
3087
+ **Option 1:**
3077
3088
 
3078
3089
  If you want to run a specific list of test files that are explicitly defined by you or auto-generated by some kind of script you created then please use:
3079
3090
 
@@ -3081,7 +3092,24 @@ If you want to run a specific list of test files that are explicitly defined by
3081
3092
 
3082
3093
  Note `KNAPSACK_PRO_TEST_FILE_LIST` must be a list of test files comma separated. You can provide line number for tests inside of spec file in case of RSpec (this way you can run only one test or a group of tests from RSpec spec file). You can provide the same file a few times with different test line number.
3083
3094
 
3084
- Note when you set `KNAPSACK_PRO_TEST_FILE_LIST` then below environment variables are ignored:
3095
+ **Option 2:**
3096
+
3097
+ Similarly, you can also provide a source file containing the test files that you would like to run. For example:
3098
+ `KNAPSACK_PRO_TEST_FILE_LIST_SOURCE_FILE=spec/fixtures/test_file_list_source_file.txt`
3099
+ And the content of the source file can be any of the format below:
3100
+
3101
+ ```
3102
+ ./spec/test1_spec.rb
3103
+ spec/test2_spec.rb[1]
3104
+ ./spec/test3_spec.rb[1:2:3:4]
3105
+ ./spec/test4_spec.rb:4
3106
+ ./spec/test4_spec.rb:5
3107
+ ```
3108
+
3109
+ > Note that each of the line must be ending with `\n` the new line.
3110
+
3111
+ Note when you set `KNAPSACK_PRO_TEST_FILE_LIST` or `KNAPSACK_PRO_TEST_FILE_LIST_SOURCE_FILE` then below environment variables are ignored:
3112
+
3085
3113
  * `KNAPSACK_PRO_TEST_FILE_PATTERN`
3086
3114
  * `KNAPSACK_PRO_TEST_FILE_EXCLUDE_PATTERN`
3087
3115
 
@@ -3249,6 +3277,8 @@ $ gem build knapsack_pro.gemspec
3249
3277
  $ gem push knapsack_pro-X.X.X.gem
3250
3278
  ```
3251
3279
 
3280
+ Update the latest available gem version in `TestSuiteClientVersionChecker` for the Knapsack Pro API repository.
3281
+
3252
3282
  ## Mentions
3253
3283
 
3254
3284
  List of articles where people mentioned Knapsack Pro:
@@ -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)
@@ -116,14 +115,19 @@ module KnapsackPro
116
115
 
117
116
  response_body
118
117
  rescue ServerError, Errno::ECONNREFUSED, Errno::ETIMEDOUT, Errno::EPIPE, EOFError, SocketError, Net::OpenTimeout, Net::ReadTimeout, OpenSSL::SSL::SSLError => e
118
+ logger.warn("#{action.http_method.to_s.upcase} #{endpoint_url}")
119
+ logger.warn('Request failed due to:')
119
120
  logger.warn(e.inspect)
120
121
  retries += 1
121
- if retries < MAX_RETRY.call
122
+ if retries < max_request_retries
122
123
  wait = retries * REQUEST_RETRY_TIMEBOX
123
- logger.warn("Wait #{wait}s and retry request to Knapsack Pro API.")
124
124
  print_every = 2 # seconds
125
125
  (wait / print_every).ceil.times do |i|
126
- logger.warn("Next request in #{wait - i * print_every}s...")
126
+ if i == 0
127
+ logger.warn("Wait for #{wait}s before retrying the request to Knapsack Pro API.")
128
+ else
129
+ logger.warn("#{wait - i * print_every}s left before retry...")
130
+ end
127
131
  Kernel.sleep(print_every)
128
132
  end
129
133
  retry
@@ -156,6 +160,22 @@ module KnapsackPro
156
160
  http.get(uri, json_headers)
157
161
  end
158
162
  end
163
+
164
+ def max_request_retries
165
+ # when user defined max request retries
166
+ return KnapsackPro::Config::Env.max_request_retries if KnapsackPro::Config::Env.max_request_retries
167
+
168
+ # when Fallback Mode is disabled then try more attempts to connect to the API
169
+ return 6 unless KnapsackPro::Config::Env.fallback_mode_enabled?
170
+
171
+ # when Regular Mode then try more attempts to connect to the API
172
+ # if only one CI node starts Fallback Mode instead of all then we can't guarantee all test files will be run
173
+ # https://github.com/KnapsackPro/knapsack_pro-ruby/pull/124
174
+ return 6 if KnapsackPro::Config::Env.regular_mode?
175
+
176
+ # default number of attempts
177
+ 3
178
+ end
159
179
  end
160
180
  end
161
181
  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)
@@ -67,6 +74,10 @@ module KnapsackPro
67
74
  ENV['KNAPSACK_PRO_TEST_FILE_LIST']
68
75
  end
69
76
 
77
+ def test_file_list_source_file
78
+ ENV['KNAPSACK_PRO_TEST_FILE_LIST_SOURCE_FILE']
79
+ end
80
+
70
81
  def test_dir
71
82
  ENV['KNAPSACK_PRO_TEST_DIR']
72
83
  end
@@ -83,6 +94,10 @@ module KnapsackPro
83
94
  recording_enabled == 'true'
84
95
  end
85
96
 
97
+ def regular_mode?
98
+ recording_enabled?
99
+ end
100
+
86
101
  def queue_recording_enabled
87
102
  ENV['KNAPSACK_PRO_QUEUE_RECORDING_ENABLED']
88
103
  end
@@ -1,7 +1,23 @@
1
1
  module KnapsackPro
2
2
  module Crypto
3
3
  class BranchEncryptor
4
- NON_ENCRYPTABLE_BRANCHES = %w(develop development dev master staging)
4
+ NON_ENCRYPTABLE_BRANCHES = [
5
+ 'master',
6
+ 'main',
7
+ 'develop',
8
+ 'development',
9
+ 'dev',
10
+ 'staging',
11
+ 'production',
12
+ # GitHub Actions has branch names starting with refs/heads/
13
+ 'refs/heads/master',
14
+ 'refs/heads/main',
15
+ 'refs/heads/develop',
16
+ 'refs/heads/development',
17
+ 'refs/heads/dev',
18
+ 'refs/heads/staging',
19
+ 'refs/heads/production',
20
+ ]
5
21
 
6
22
  def self.call(branch)
7
23
  if KnapsackPro::Config::Env.branch_encrypted?
@@ -63,6 +63,10 @@ module KnapsackPro
63
63
  return KnapsackPro::Config::Env.test_file_list.split(',').map(&:strip)
64
64
  end
65
65
 
66
+ if test_file_list_enabled && KnapsackPro::Config::Env.test_file_list_source_file
67
+ return File.read(KnapsackPro::Config::Env.test_file_list_source_file).split(/\n/)
68
+ end
69
+
66
70
  test_file_paths = Dir.glob(test_file_pattern).uniq
67
71
 
68
72
  excluded_test_file_paths =
@@ -1,3 +1,3 @@
1
1
  module KnapsackPro
2
- VERSION = '2.2.1'
2
+ VERSION = '2.7.0'
3
3
  end
@@ -0,0 +1,6 @@
1
+ ./spec/test1_spec.rb
2
+ spec/test2_spec.rb[1]
3
+ ./spec/test3_spec.rb[1:2:3:4]
4
+ ./spec/test4_spec.rb:4
5
+ ./spec/test4_spec.rb:5
6
+
@@ -84,22 +84,22 @@ shared_examples 'when retry request' do
84
84
  expect(logger).to receive(:error).exactly(3).with(parsed_response)
85
85
 
86
86
  server_error = described_class::ServerError.new(parsed_response)
87
+ expect(logger).to receive(:warn).exactly(3).with("#{expected_http_method} http://api.knapsackpro.test:3000/v1/fake_endpoint")
88
+ expect(logger).to receive(:warn).exactly(3).with('Request failed due to:')
87
89
  expect(logger).to receive(:warn).exactly(3).with(server_error.inspect)
88
90
 
89
- expect(logger).to receive(:warn).with("Wait 8s and retry request to Knapsack Pro API.")
90
- expect(logger).to receive(:warn).with("Next request in 8s...")
91
- expect(logger).to receive(:warn).with("Next request in 6s...")
92
- expect(logger).to receive(:warn).with("Next request in 4s...")
93
- expect(logger).to receive(:warn).with("Next request in 2s...")
94
- expect(logger).to receive(:warn).with("Wait 16s and retry request to Knapsack Pro API.")
95
- expect(logger).to receive(:warn).with("Next request in 16s...")
96
- expect(logger).to receive(:warn).with("Next request in 14s...")
97
- expect(logger).to receive(:warn).with("Next request in 12s...")
98
- expect(logger).to receive(:warn).with("Next request in 10s...")
99
- expect(logger).to receive(:warn).with("Next request in 8s...")
100
- expect(logger).to receive(:warn).with("Next request in 6s...")
101
- expect(logger).to receive(:warn).with("Next request in 4s...")
102
- expect(logger).to receive(:warn).with("Next request in 2s...")
91
+ expect(logger).to receive(:warn).with("Wait for 8s before retrying the request to Knapsack Pro API.")
92
+ expect(logger).to receive(:warn).with("6s left before retry...")
93
+ expect(logger).to receive(:warn).with("4s left before retry...")
94
+ expect(logger).to receive(:warn).with("2s left before retry...")
95
+ expect(logger).to receive(:warn).with("Wait for 16s before retrying the request to Knapsack Pro API.")
96
+ expect(logger).to receive(:warn).with("14s left before retry...")
97
+ expect(logger).to receive(:warn).with("12s left before retry...")
98
+ expect(logger).to receive(:warn).with("10s left before retry...")
99
+ expect(logger).to receive(:warn).with("8s left before retry...")
100
+ expect(logger).to receive(:warn).with("6s left before retry...")
101
+ expect(logger).to receive(:warn).with("4s left before retry...")
102
+ expect(logger).to receive(:warn).with("2s left before retry...")
103
103
  expect(Kernel).to receive(:sleep).exactly(12).with(2)
104
104
 
105
105
  expect(subject).to eq(parsed_response)
@@ -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("#{expected_http_method} http://api.knapsackpro.test:3000/v1/fake_endpoint")
127
+ expect(logger).to receive(:warn).exactly(4).with('Request failed due to:')
128
+ expect(logger).to receive(:warn).exactly(4).with(server_error.inspect)
129
+
130
+ expect(logger).to receive(:warn).with("Wait for 8s before retrying the request to Knapsack Pro API.")
131
+ expect(logger).to receive(:warn).with("6s left before retry...")
132
+ expect(logger).to receive(:warn).with("4s left before retry...")
133
+ expect(logger).to receive(:warn).with("2s left before retry...")
134
+
135
+ expect(logger).to receive(:warn).with("Wait for 16s before retrying the request to Knapsack Pro API.")
136
+ expect(logger).to receive(:warn).with("14s left before retry...")
137
+ expect(logger).to receive(:warn).with("12s left before retry...")
138
+ expect(logger).to receive(:warn).with("10s left before retry...")
139
+ expect(logger).to receive(:warn).with("8s left before retry...")
140
+ expect(logger).to receive(:warn).with("6s left before retry...")
141
+ expect(logger).to receive(:warn).with("4s left before retry...")
142
+ expect(logger).to receive(:warn).with("2s left before retry...")
143
+
144
+ expect(logger).to receive(:warn).with("Wait for 24s before retrying the request to Knapsack Pro API.")
145
+ 11.times do |i|
146
+ expect(logger).to receive(:warn).with("#{(i+1)*2}s left before retry...")
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)
@@ -123,37 +170,94 @@ shared_examples 'when retry request' do
123
170
  expect(logger).to receive(:error).exactly(6).with(parsed_response)
124
171
 
125
172
  server_error = described_class::ServerError.new(parsed_response)
173
+ expect(logger).to receive(:warn).exactly(6).with("#{expected_http_method} http://api.knapsackpro.test:3000/v1/fake_endpoint")
174
+ expect(logger).to receive(:warn).exactly(6).with('Request failed due to:')
175
+ expect(logger).to receive(:warn).exactly(6).with(server_error.inspect)
176
+
177
+ expect(logger).to receive(:warn).with("Wait for 8s before retrying the request to Knapsack Pro API.")
178
+ expect(logger).to receive(:warn).with("6s left before retry...")
179
+ expect(logger).to receive(:warn).with("4s left before retry...")
180
+ expect(logger).to receive(:warn).with("2s left before retry...")
181
+
182
+ expect(logger).to receive(:warn).with("Wait for 16s before retrying the request to Knapsack Pro API.")
183
+ expect(logger).to receive(:warn).with("14s left before retry...")
184
+ expect(logger).to receive(:warn).with("12s left before retry...")
185
+ expect(logger).to receive(:warn).with("10s left before retry...")
186
+ expect(logger).to receive(:warn).with("8s left before retry...")
187
+ expect(logger).to receive(:warn).with("6s left before retry...")
188
+ expect(logger).to receive(:warn).with("4s left before retry...")
189
+ expect(logger).to receive(:warn).with("2s left before retry...")
190
+
191
+ expect(logger).to receive(:warn).with("Wait for 24s before retrying the request to Knapsack Pro API.")
192
+ 11.times do |i|
193
+ expect(logger).to receive(:warn).with("#{(i+1)*2}s left before retry...")
194
+ end
195
+
196
+ expect(logger).to receive(:warn).with("Wait for 32s before retrying the request to Knapsack Pro API.")
197
+ 15.times do |i|
198
+ expect(logger).to receive(:warn).with("#{(i+1)*2}s left before retry...")
199
+ end
200
+
201
+ expect(logger).to receive(:warn).with("Wait for 40s before retrying the request to Knapsack Pro API.")
202
+ 19.times do |i|
203
+ expect(logger).to receive(:warn).with("#{(i+1)*2}s left before retry...")
204
+ end
205
+
206
+ expect(Kernel).to receive(:sleep).exactly(60).with(2)
207
+
208
+ expect(subject).to eq(parsed_response)
209
+
210
+ expect(connection.success?).to be false
211
+ expect(connection.errors?).to be true
212
+ end
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("#{expected_http_method} http://api.knapsackpro.test:3000/v1/fake_endpoint")
231
+ expect(logger).to receive(:warn).exactly(6).with('Request failed due to:')
126
232
  expect(logger).to receive(:warn).exactly(6).with(server_error.inspect)
127
233
 
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...")
234
+ expect(logger).to receive(:warn).with("Wait for 8s before retrying the request to Knapsack Pro API.")
235
+ expect(logger).to receive(:warn).with("6s left before retry...")
236
+ expect(logger).to receive(:warn).with("4s left before retry...")
237
+ expect(logger).to receive(:warn).with("2s left before retry...")
238
+
239
+ expect(logger).to receive(:warn).with("Wait for 16s before retrying the request to Knapsack Pro API.")
240
+ expect(logger).to receive(:warn).with("14s left before retry...")
241
+ expect(logger).to receive(:warn).with("12s left before retry...")
242
+ expect(logger).to receive(:warn).with("10s left before retry...")
243
+ expect(logger).to receive(:warn).with("8s left before retry...")
244
+ expect(logger).to receive(:warn).with("6s left before retry...")
245
+ expect(logger).to receive(:warn).with("4s left before retry...")
246
+ expect(logger).to receive(:warn).with("2s left before retry...")
247
+
248
+ expect(logger).to receive(:warn).with("Wait for 24s before retrying the request to Knapsack Pro API.")
249
+ 11.times do |i|
250
+ expect(logger).to receive(:warn).with("#{(i+1)*2}s left before retry...")
147
251
  end
148
252
 
149
- expect(logger).to receive(:warn).with("Wait 32s and retry request to Knapsack Pro API.")
150
- 16.times do |i|
151
- expect(logger).to receive(:warn).with("Next request in #{(i+1)*2}s...")
253
+ expect(logger).to receive(:warn).with("Wait for 32s before retrying the request to Knapsack Pro API.")
254
+ 15.times do |i|
255
+ expect(logger).to receive(:warn).with("#{(i+1)*2}s left before retry...")
152
256
  end
153
257
 
154
- expect(logger).to receive(:warn).with("Wait 40s and retry request to Knapsack Pro API.")
155
- 20.times do |i|
156
- expect(logger).to receive(:warn).with("Next request in #{(i+1)*2}s...")
258
+ expect(logger).to receive(:warn).with("Wait for 40s before retrying the request to Knapsack Pro API.")
259
+ 19.times do |i|
260
+ expect(logger).to receive(:warn).with("#{(i+1)*2}s left before retry...")
157
261
  end
158
262
 
159
263
  expect(Kernel).to receive(:sleep).exactly(60).with(2)
@@ -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
 
@@ -225,6 +238,20 @@ describe KnapsackPro::Config::Env do
225
238
  end
226
239
  end
227
240
 
241
+ describe '.test_file_list_source_file' do
242
+ subject { described_class.test_file_list_source_file }
243
+
244
+ context 'when ENV exists' do
245
+ let(:test_file_list_source_file) { 'spec/fixtures/test_file_list_source_file.txt' }
246
+ before { stub_const("ENV", { 'KNAPSACK_PRO_TEST_FILE_LIST_SOURCE_FILE' => test_file_list_source_file }) }
247
+ it { should eq test_file_list_source_file }
248
+ end
249
+
250
+ context "when ENV doesn't exist" do
251
+ it { should be_nil }
252
+ end
253
+ end
254
+
228
255
  describe '.test_dir' do
229
256
  subject { described_class.test_dir }
230
257
 
@@ -267,6 +294,25 @@ describe KnapsackPro::Config::Env do
267
294
  end
268
295
  end
269
296
 
297
+
298
+ describe '.regular_mode?' do
299
+ subject { described_class.regular_mode? }
300
+
301
+ before do
302
+ expect(described_class).to receive(:recording_enabled?).and_return(recording_enabled)
303
+ end
304
+
305
+ context 'when recording is enabled' do
306
+ let(:recording_enabled) { true }
307
+ it { should be true }
308
+ end
309
+
310
+ context 'when recording is not enabled' do
311
+ let(:recording_enabled) { false }
312
+ it { should be false }
313
+ end
314
+ end
315
+
270
316
  describe '.recording_enabled?' do
271
317
  subject { described_class.recording_enabled? }
272
318
 
@@ -154,5 +154,23 @@ describe KnapsackPro::TestFileFinder do
154
154
  end
155
155
  end
156
156
  end
157
+
158
+ context 'when KNAPSACK_PRO_TEST_FILE_LIST_SOURCE_FILE is defined' do
159
+ let(:test_file_list_source_file) { 'spec/fixtures/test_file_list_source_file.txt' }
160
+
161
+ before do
162
+ stub_const("ENV", { 'KNAPSACK_PRO_TEST_FILE_LIST_SOURCE_FILE' => test_file_list_source_file })
163
+ end
164
+
165
+ it do
166
+ expect(subject).to eq([
167
+ { 'path' => 'spec/test1_spec.rb' },
168
+ { 'path' => 'spec/test2_spec.rb[1]' },
169
+ { 'path' => 'spec/test3_spec.rb[1:2:3:4]' },
170
+ { 'path' => 'spec/test4_spec.rb:4' },
171
+ { 'path' => 'spec/test4_spec.rb:5' },
172
+ ])
173
+ end
174
+ end
157
175
  end
158
176
  end
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.7.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-11-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -308,6 +308,7 @@ files:
308
308
  - lib/tasks/salt.rake
309
309
  - lib/tasks/spinach.rake
310
310
  - lib/tasks/test_unit.rake
311
+ - spec/fixtures/test_file_list_source_file.txt
311
312
  - spec/fixtures/vcr_cassettes/api/v1/build_distributions/subset/invalid_test_suite_token.yml
312
313
  - spec/fixtures/vcr_cassettes/api/v1/build_distributions/subset/success.yml
313
314
  - spec/fixtures/vcr_cassettes/api/v1/build_subsets/create/invalid_test_suite_token.yml
@@ -428,6 +429,7 @@ specification_version: 4
428
429
  summary: Knapsack Pro splits tests across parallel CI nodes and ensures each parallel
429
430
  job finish work at a similar time.
430
431
  test_files:
432
+ - spec/fixtures/test_file_list_source_file.txt
431
433
  - spec/fixtures/vcr_cassettes/api/v1/build_distributions/subset/invalid_test_suite_token.yml
432
434
  - spec/fixtures/vcr_cassettes/api/v1/build_distributions/subset/success.yml
433
435
  - spec/fixtures/vcr_cassettes/api/v1/build_subsets/create/invalid_test_suite_token.yml