knapsack_pro 2.5.0 → 2.10.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 +40 -0
- data/README.md +24 -3
- data/lib/knapsack_pro/base_allocator_builder.rb +8 -0
- data/lib/knapsack_pro/client/api/v1/queues.rb +4 -1
- data/lib/knapsack_pro/client/connection.rb +12 -2
- data/lib/knapsack_pro/config/env.rb +4 -0
- data/lib/knapsack_pro/queue_allocator.rb +38 -11
- data/lib/knapsack_pro/queue_allocator_builder.rb +2 -2
- data/lib/knapsack_pro/test_case_detectors/rspec_test_example_detector.rb +10 -1
- data/lib/knapsack_pro/test_file_finder.rb +4 -0
- data/lib/knapsack_pro/tracker.rb +1 -5
- data/lib/knapsack_pro/version.rb +1 -1
- data/spec/fixtures/test_file_list_source_file.txt +6 -0
- data/spec/knapsack_pro/client/api/v1/queues_spec.rb +31 -2
- data/spec/knapsack_pro/client/connection_spec.rb +83 -83
- data/spec/knapsack_pro/config/env_spec.rb +14 -0
- data/spec/knapsack_pro/queue_allocator_builder_spec.rb +6 -6
- data/spec/knapsack_pro/queue_allocator_spec.rb +260 -65
- data/spec/knapsack_pro/test_case_detectors/rspec_test_example_detector_spec.rb +1 -1
- data/spec/knapsack_pro/test_file_finder_spec.rb +18 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ab52ffbbe5618da1d1c70e11493e6dcd474542a8fe19dc11b57c673f3fc5b939
|
4
|
+
data.tar.gz: e53495530e21c903b56921a47a6cd27de056f3cc2cbb3f2804df99f0bc6d4542
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 732b7ce526fa01c176e5a958bd6cf71eab989fce6bcf160334157dd1e7b65b37c6b31ecc0ad603b4780df0a925059eaf5f212174d1bff37f89ab86c807d4ac30
|
7
|
+
data.tar.gz: baa2ef028990a02e332f0f5e1d985db760f44ae3c1b090128c696dea5f77e2a89659381e7a081a2c67eb1d870cec09b9a16d9b11e0dbe4315622fd7a458889b1
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,45 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
### 2.10.0
|
4
|
+
|
5
|
+
* Add support for an attempt to connect to existing Queue on API side to reduce slow requests number
|
6
|
+
|
7
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/pull/133
|
8
|
+
|
9
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v2.9.0...v2.10.0
|
10
|
+
|
11
|
+
### 2.9.0
|
12
|
+
|
13
|
+
* Use `Process.clock_gettime` to measure track execution time
|
14
|
+
|
15
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/pull/132
|
16
|
+
|
17
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v2.8.0...v2.9.0
|
18
|
+
|
19
|
+
### 2.8.0
|
20
|
+
|
21
|
+
* More actionable error message when RSpec split by examples is not working due to RSpec dry-run failure
|
22
|
+
|
23
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/pull/130
|
24
|
+
|
25
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v2.7.0...v2.8.0
|
26
|
+
|
27
|
+
### 2.7.0
|
28
|
+
|
29
|
+
* Add support for env var `KNAPSACK_PRO_TEST_FILE_LIST_SOURCE_FILE` to allow accepting file containing test files to run
|
30
|
+
|
31
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/pull/129
|
32
|
+
|
33
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v2.6.0...v2.7.0
|
34
|
+
|
35
|
+
### 2.6.0
|
36
|
+
|
37
|
+
* Improve logger to show failed requests URL and when retry will happen
|
38
|
+
|
39
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/pull/127
|
40
|
+
|
41
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v2.5.0...v2.6.0
|
42
|
+
|
3
43
|
### 2.5.0
|
4
44
|
|
5
45
|
* Add production branch to non encryptable branches names
|
data/README.md
CHANGED
@@ -50,7 +50,7 @@ We keep this old FAQ in README to not break old links spread across the web. You
|
|
50
50
|
|
51
51
|
# Requirements
|
52
52
|
|
53
|
-
`>= Ruby 2.
|
53
|
+
`>= Ruby 2.1.0`
|
54
54
|
|
55
55
|
# Table of Contents
|
56
56
|
|
@@ -3082,7 +3082,9 @@ The test file pattern and exclude pattern support any glob pattern handled by [`
|
|
3082
3082
|
|
3083
3083
|
#### How to run a specific list of test files or only some tests from test file?
|
3084
3084
|
|
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.
|
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:**
|
3086
3088
|
|
3087
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:
|
3088
3090
|
|
@@ -3090,7 +3092,24 @@ If you want to run a specific list of test files that are explicitly defined by
|
|
3090
3092
|
|
3091
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.
|
3092
3094
|
|
3093
|
-
|
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
|
+
|
3094
3113
|
* `KNAPSACK_PRO_TEST_FILE_PATTERN`
|
3095
3114
|
* `KNAPSACK_PRO_TEST_FILE_EXCLUDE_PATTERN`
|
3096
3115
|
|
@@ -3258,6 +3277,8 @@ $ gem build knapsack_pro.gemspec
|
|
3258
3277
|
$ gem push knapsack_pro-X.X.X.gem
|
3259
3278
|
```
|
3260
3279
|
|
3280
|
+
Update the latest available gem version in `TestSuiteClientVersionChecker` for the Knapsack Pro API repository.
|
3281
|
+
|
3261
3282
|
## Mentions
|
3262
3283
|
|
3263
3284
|
List of articles where people mentioned Knapsack Pro:
|
@@ -28,6 +28,10 @@ module KnapsackPro
|
|
28
28
|
all_test_files_to_run
|
29
29
|
end
|
30
30
|
|
31
|
+
def lazy_fallback_mode_test_files
|
32
|
+
lambda { fallback_mode_test_files }
|
33
|
+
end
|
34
|
+
|
31
35
|
# detect test files present on the disk that should be run
|
32
36
|
# this may include some fast test files + slow test files split by test cases
|
33
37
|
def fast_and_slow_test_files_to_run
|
@@ -63,6 +67,10 @@ module KnapsackPro
|
|
63
67
|
end
|
64
68
|
end
|
65
69
|
|
70
|
+
def lazy_fast_and_slow_test_files_to_run
|
71
|
+
lambda { fast_and_slow_test_files_to_run }
|
72
|
+
end
|
73
|
+
|
66
74
|
private
|
67
75
|
|
68
76
|
attr_reader :adapter_class
|
@@ -3,11 +3,14 @@ module KnapsackPro
|
|
3
3
|
module API
|
4
4
|
module V1
|
5
5
|
class Queues < Base
|
6
|
+
CODE_ATTEMPT_CONNECT_TO_QUEUE_FAILED = 'ATTEMPT_CONNECT_TO_QUEUE_FAILED'
|
7
|
+
|
6
8
|
class << self
|
7
9
|
def queue(args)
|
8
10
|
request_hash = {
|
9
11
|
:fixed_queue_split => KnapsackPro::Config::Env.fixed_queue_split,
|
10
12
|
:can_initialize_queue => args.fetch(:can_initialize_queue),
|
13
|
+
:attempt_connect_to_queue => args.fetch(:attempt_connect_to_queue),
|
11
14
|
:commit_hash => args.fetch(:commit_hash),
|
12
15
|
:branch => args.fetch(:branch),
|
13
16
|
:node_total => args.fetch(:node_total),
|
@@ -15,7 +18,7 @@ module KnapsackPro
|
|
15
18
|
:node_build_id => KnapsackPro::Config::Env.ci_node_build_id,
|
16
19
|
}
|
17
20
|
|
18
|
-
if request_hash[:can_initialize_queue]
|
21
|
+
if request_hash[:can_initialize_queue] && !request_hash[:attempt_connect_to_queue]
|
19
22
|
request_hash.merge!({
|
20
23
|
:test_files => args.fetch(:test_files)
|
21
24
|
})
|
@@ -25,6 +25,11 @@ module KnapsackPro
|
|
25
25
|
!!(response_body && (response_body['errors'] || response_body['error']))
|
26
26
|
end
|
27
27
|
|
28
|
+
def api_code
|
29
|
+
return unless response_body
|
30
|
+
response_body['code']
|
31
|
+
end
|
32
|
+
|
28
33
|
def server_error?
|
29
34
|
status = http_response.code.to_i
|
30
35
|
status >= 500 && status < 600
|
@@ -115,14 +120,19 @@ module KnapsackPro
|
|
115
120
|
|
116
121
|
response_body
|
117
122
|
rescue ServerError, Errno::ECONNREFUSED, Errno::ETIMEDOUT, Errno::EPIPE, EOFError, SocketError, Net::OpenTimeout, Net::ReadTimeout, OpenSSL::SSL::SSLError => e
|
123
|
+
logger.warn("#{action.http_method.to_s.upcase} #{endpoint_url}")
|
124
|
+
logger.warn('Request failed due to:')
|
118
125
|
logger.warn(e.inspect)
|
119
126
|
retries += 1
|
120
127
|
if retries < max_request_retries
|
121
128
|
wait = retries * REQUEST_RETRY_TIMEBOX
|
122
|
-
logger.warn("Wait #{wait}s and retry request to Knapsack Pro API.")
|
123
129
|
print_every = 2 # seconds
|
124
130
|
(wait / print_every).ceil.times do |i|
|
125
|
-
|
131
|
+
if i == 0
|
132
|
+
logger.warn("Wait for #{wait}s before retrying the request to Knapsack Pro API.")
|
133
|
+
else
|
134
|
+
logger.warn("#{wait - i * print_every}s left before retry...")
|
135
|
+
end
|
126
136
|
Kernel.sleep(print_every)
|
127
137
|
end
|
128
138
|
retry
|
@@ -1,8 +1,8 @@
|
|
1
1
|
module KnapsackPro
|
2
2
|
class QueueAllocator
|
3
3
|
def initialize(args)
|
4
|
-
@
|
5
|
-
@
|
4
|
+
@lazy_fast_and_slow_test_files_to_run = args.fetch(:lazy_fast_and_slow_test_files_to_run)
|
5
|
+
@lazy_fallback_mode_test_files = args.fetch(:lazy_fallback_mode_test_files)
|
6
6
|
@ci_node_total = args.fetch(:ci_node_total)
|
7
7
|
@ci_node_index = args.fetch(:ci_node_index)
|
8
8
|
@ci_node_build_id = args.fetch(:ci_node_build_id)
|
@@ -11,9 +11,18 @@ module KnapsackPro
|
|
11
11
|
|
12
12
|
def test_file_paths(can_initialize_queue, executed_test_files)
|
13
13
|
return [] if @fallback_activated
|
14
|
-
action = build_action(can_initialize_queue)
|
14
|
+
action = build_action(can_initialize_queue, attempt_connect_to_queue: can_initialize_queue)
|
15
15
|
connection = KnapsackPro::Client::Connection.new(action)
|
16
16
|
response = connection.call
|
17
|
+
|
18
|
+
# when attempt to connect to existing queue on API side failed because queue does not exist yet
|
19
|
+
if can_initialize_queue && connection.success? && connection.api_code == KnapsackPro::Client::API::V1::Queues::CODE_ATTEMPT_CONNECT_TO_QUEUE_FAILED
|
20
|
+
# make attempt to initalize a new queue on API side
|
21
|
+
action = build_action(can_initialize_queue, attempt_connect_to_queue: false)
|
22
|
+
connection = KnapsackPro::Client::Connection.new(action)
|
23
|
+
response = connection.call
|
24
|
+
end
|
25
|
+
|
17
26
|
if connection.success?
|
18
27
|
raise ArgumentError.new(response) if connection.errors?
|
19
28
|
prepare_test_files(response)
|
@@ -37,40 +46,58 @@ module KnapsackPro
|
|
37
46
|
|
38
47
|
private
|
39
48
|
|
40
|
-
attr_reader :
|
41
|
-
:
|
49
|
+
attr_reader :lazy_fast_and_slow_test_files_to_run,
|
50
|
+
:lazy_fallback_mode_test_files,
|
42
51
|
:ci_node_total,
|
43
52
|
:ci_node_index,
|
44
53
|
:ci_node_build_id,
|
45
54
|
:repository_adapter
|
46
55
|
|
56
|
+
# This method might be slow because it reads test files from disk.
|
57
|
+
# This method can be very slow (a few seconds or more) when you use RSpec split by test examples feature because RSpec needs to generate JSON report with test examples ids
|
58
|
+
def lazy_loaded_fast_and_slow_test_files_to_run
|
59
|
+
@lazy_loaded_fast_and_slow_test_files_to_run ||= lazy_fast_and_slow_test_files_to_run.call
|
60
|
+
end
|
61
|
+
|
47
62
|
def encrypted_test_files
|
48
|
-
KnapsackPro::Crypto::Encryptor.call(
|
63
|
+
KnapsackPro::Crypto::Encryptor.call(lazy_loaded_fast_and_slow_test_files_to_run)
|
49
64
|
end
|
50
65
|
|
51
66
|
def encrypted_branch
|
52
67
|
KnapsackPro::Crypto::BranchEncryptor.call(repository_adapter.branch)
|
53
68
|
end
|
54
69
|
|
55
|
-
def build_action(can_initialize_queue)
|
70
|
+
def build_action(can_initialize_queue, attempt_connect_to_queue:)
|
71
|
+
# read test files from disk only when needed because it can be slow operation
|
72
|
+
test_files =
|
73
|
+
if can_initialize_queue && !attempt_connect_to_queue
|
74
|
+
encrypted_test_files
|
75
|
+
end
|
76
|
+
|
56
77
|
KnapsackPro::Client::API::V1::Queues.queue(
|
57
78
|
can_initialize_queue: can_initialize_queue,
|
79
|
+
attempt_connect_to_queue: attempt_connect_to_queue,
|
58
80
|
commit_hash: repository_adapter.commit_hash,
|
59
81
|
branch: encrypted_branch,
|
60
82
|
node_total: ci_node_total,
|
61
83
|
node_index: ci_node_index,
|
62
84
|
node_build_id: ci_node_build_id,
|
63
|
-
test_files:
|
85
|
+
test_files: test_files,
|
64
86
|
)
|
65
87
|
end
|
66
88
|
|
67
89
|
def prepare_test_files(response)
|
68
|
-
|
69
|
-
KnapsackPro::
|
90
|
+
# when encryption is disabled we can avoid calling slow method lazy_loaded_fast_and_slow_test_files_to_run
|
91
|
+
if KnapsackPro::Config::Env.test_files_encrypted?
|
92
|
+
decrypted_test_files = KnapsackPro::Crypto::Decryptor.call(lazy_loaded_fast_and_slow_test_files_to_run, response['test_files'])
|
93
|
+
KnapsackPro::TestFilePresenter.paths(decrypted_test_files)
|
94
|
+
else
|
95
|
+
KnapsackPro::TestFilePresenter.paths(response['test_files'])
|
96
|
+
end
|
70
97
|
end
|
71
98
|
|
72
99
|
def fallback_test_files(executed_test_files)
|
73
|
-
test_flat_distributor = KnapsackPro::TestFlatDistributor.new(
|
100
|
+
test_flat_distributor = KnapsackPro::TestFlatDistributor.new(lazy_fallback_mode_test_files.call, ci_node_total)
|
74
101
|
test_files_for_node_index = test_flat_distributor.test_files_for_node(ci_node_index)
|
75
102
|
KnapsackPro::TestFilePresenter.paths(test_files_for_node_index) - executed_test_files
|
76
103
|
end
|
@@ -2,8 +2,8 @@ module KnapsackPro
|
|
2
2
|
class QueueAllocatorBuilder < BaseAllocatorBuilder
|
3
3
|
def allocator
|
4
4
|
KnapsackPro::QueueAllocator.new(
|
5
|
-
|
6
|
-
|
5
|
+
lazy_fast_and_slow_test_files_to_run: lazy_fast_and_slow_test_files_to_run,
|
6
|
+
lazy_fallback_mode_test_files: lazy_fallback_mode_test_files,
|
7
7
|
ci_node_total: env.ci_node_total,
|
8
8
|
ci_node_index: env.ci_node_index,
|
9
9
|
ci_node_build_id: env.ci_node_build_id,
|
@@ -33,7 +33,16 @@ module KnapsackPro
|
|
33
33
|
options = ::RSpec::Core::ConfigurationOptions.new(cli_args)
|
34
34
|
exit_code = ::RSpec::Core::Runner.new(options).run($stderr, $stdout)
|
35
35
|
if exit_code != 0
|
36
|
-
|
36
|
+
debug_cmd = ([
|
37
|
+
'bundle exec rspec',
|
38
|
+
] + cli_args).join(' ')
|
39
|
+
|
40
|
+
KnapsackPro.logger.error('-'*10 + ' START of actionable error message ' + '-'*50)
|
41
|
+
KnapsackPro.logger.error('There was a problem while generating test examples for the slow test files using the RSpec dry-run flag. To reproduce the error triggered by the RSpec, please try to run below command (this way, you can find out what is causing the error):')
|
42
|
+
KnapsackPro.logger.error(debug_cmd)
|
43
|
+
KnapsackPro.logger.error('-'*10 + ' END of actionable error message ' + '-'*50)
|
44
|
+
|
45
|
+
raise 'There was a problem while generating test examples for the slow test files. Please read actionable error message above.'
|
37
46
|
end
|
38
47
|
end
|
39
48
|
|
@@ -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 =
|
data/lib/knapsack_pro/tracker.rb
CHANGED
data/lib/knapsack_pro/version.rb
CHANGED
@@ -11,6 +11,7 @@ describe KnapsackPro::Client::API::V1::Queues do
|
|
11
11
|
subject do
|
12
12
|
described_class.queue(
|
13
13
|
can_initialize_queue: can_initialize_queue,
|
14
|
+
attempt_connect_to_queue: attempt_connect_to_queue,
|
14
15
|
commit_hash: commit_hash,
|
15
16
|
branch: branch,
|
16
17
|
node_total: node_total,
|
@@ -24,8 +25,33 @@ describe KnapsackPro::Client::API::V1::Queues do
|
|
24
25
|
expect(KnapsackPro::Config::Env).to receive(:ci_node_build_id).and_return(node_build_id)
|
25
26
|
end
|
26
27
|
|
27
|
-
context 'when can_initialize_queue=true' do
|
28
|
+
context 'when can_initialize_queue=true and attempt_connect_to_queue=true' do
|
28
29
|
let(:can_initialize_queue) { true }
|
30
|
+
let(:attempt_connect_to_queue) { true }
|
31
|
+
|
32
|
+
it 'does not send test_files among other params' do
|
33
|
+
action = double
|
34
|
+
expect(KnapsackPro::Client::API::Action).to receive(:new).with({
|
35
|
+
endpoint_path: '/v1/queues/queue',
|
36
|
+
http_method: :post,
|
37
|
+
request_hash: {
|
38
|
+
fixed_queue_split: fixed_queue_split,
|
39
|
+
can_initialize_queue: can_initialize_queue,
|
40
|
+
attempt_connect_to_queue: attempt_connect_to_queue,
|
41
|
+
commit_hash: commit_hash,
|
42
|
+
branch: branch,
|
43
|
+
node_total: node_total,
|
44
|
+
node_index: node_index,
|
45
|
+
node_build_id: node_build_id,
|
46
|
+
}
|
47
|
+
}).and_return(action)
|
48
|
+
expect(subject).to eq action
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'when can_initialize_queue=true and attempt_connect_to_queue=false' do
|
53
|
+
let(:can_initialize_queue) { true }
|
54
|
+
let(:attempt_connect_to_queue) { false }
|
29
55
|
|
30
56
|
it 'sends test_files among other params' do
|
31
57
|
action = double
|
@@ -35,6 +61,7 @@ describe KnapsackPro::Client::API::V1::Queues do
|
|
35
61
|
request_hash: {
|
36
62
|
fixed_queue_split: fixed_queue_split,
|
37
63
|
can_initialize_queue: can_initialize_queue,
|
64
|
+
attempt_connect_to_queue: attempt_connect_to_queue,
|
38
65
|
commit_hash: commit_hash,
|
39
66
|
branch: branch,
|
40
67
|
node_total: node_total,
|
@@ -47,8 +74,9 @@ describe KnapsackPro::Client::API::V1::Queues do
|
|
47
74
|
end
|
48
75
|
end
|
49
76
|
|
50
|
-
context 'when can_initialize_queue=false' do
|
77
|
+
context 'when can_initialize_queue=false and attempt_connect_to_queue=false' do
|
51
78
|
let(:can_initialize_queue) { false }
|
79
|
+
let(:attempt_connect_to_queue) { false }
|
52
80
|
|
53
81
|
it 'does not send test_files among other params' do
|
54
82
|
action = double
|
@@ -58,6 +86,7 @@ describe KnapsackPro::Client::API::V1::Queues do
|
|
58
86
|
request_hash: {
|
59
87
|
fixed_queue_split: fixed_queue_split,
|
60
88
|
can_initialize_queue: can_initialize_queue,
|
89
|
+
attempt_connect_to_queue: attempt_connect_to_queue,
|
61
90
|
commit_hash: commit_hash,
|
62
91
|
branch: branch,
|
63
92
|
node_total: node_total,
|
@@ -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
|
90
|
-
expect(logger).to receive(:warn).with("
|
91
|
-
expect(logger).to receive(:warn).with("
|
92
|
-
expect(logger).to receive(:warn).with("
|
93
|
-
expect(logger).to receive(:warn).with("
|
94
|
-
expect(logger).to receive(:warn).with("
|
95
|
-
expect(logger).to receive(:warn).with("
|
96
|
-
expect(logger).to receive(:warn).with("
|
97
|
-
expect(logger).to receive(:warn).with("
|
98
|
-
expect(logger).to receive(:warn).with("
|
99
|
-
expect(logger).to receive(:warn).with("
|
100
|
-
expect(logger).to receive(:warn).with("
|
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)
|
@@ -123,27 +123,27 @@ shared_examples 'when retry request' do
|
|
123
123
|
expect(logger).to receive(:error).exactly(4).with(parsed_response)
|
124
124
|
|
125
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:')
|
126
128
|
expect(logger).to receive(:warn).exactly(4).with(server_error.inspect)
|
127
129
|
|
128
|
-
expect(logger).to receive(:warn).with("Wait 8s
|
129
|
-
expect(logger).to receive(:warn).with("
|
130
|
-
expect(logger).to receive(:warn).with("
|
131
|
-
expect(logger).to receive(:warn).with("
|
132
|
-
|
133
|
-
|
134
|
-
expect(logger).to receive(:warn).with("
|
135
|
-
expect(logger).to receive(:warn).with("
|
136
|
-
expect(logger).to receive(:warn).with("
|
137
|
-
expect(logger).to receive(:warn).with("
|
138
|
-
expect(logger).to receive(:warn).with("
|
139
|
-
expect(logger).to receive(:warn).with("
|
140
|
-
expect(logger).to receive(:warn).with("
|
141
|
-
|
142
|
-
expect(logger).to receive(:warn).with("
|
143
|
-
|
144
|
-
|
145
|
-
12.times do |i|
|
146
|
-
expect(logger).to receive(:warn).with("Next request in #{(i+1)*2}s...")
|
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
147
|
end
|
148
148
|
|
149
149
|
expect(Kernel).to receive(:sleep).exactly(4+8+12).with(2)
|
@@ -170,37 +170,37 @@ shared_examples 'when retry request' do
|
|
170
170
|
expect(logger).to receive(:error).exactly(6).with(parsed_response)
|
171
171
|
|
172
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:')
|
173
175
|
expect(logger).to receive(:warn).exactly(6).with(server_error.inspect)
|
174
176
|
|
175
|
-
expect(logger).to receive(:warn).with("Wait 8s
|
176
|
-
expect(logger).to receive(:warn).with("
|
177
|
-
expect(logger).to receive(:warn).with("
|
178
|
-
expect(logger).to receive(:warn).with("
|
179
|
-
|
180
|
-
|
181
|
-
expect(logger).to receive(:warn).with("
|
182
|
-
expect(logger).to receive(:warn).with("
|
183
|
-
expect(logger).to receive(:warn).with("
|
184
|
-
expect(logger).to receive(:warn).with("
|
185
|
-
expect(logger).to receive(:warn).with("
|
186
|
-
expect(logger).to receive(:warn).with("
|
187
|
-
expect(logger).to receive(:warn).with("
|
188
|
-
|
189
|
-
expect(logger).to receive(:warn).with("
|
190
|
-
|
191
|
-
|
192
|
-
12.times do |i|
|
193
|
-
expect(logger).to receive(:warn).with("Next request in #{(i+1)*2}s...")
|
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
194
|
end
|
195
195
|
|
196
|
-
expect(logger).to receive(:warn).with("Wait 32s
|
197
|
-
|
198
|
-
expect(logger).to receive(:warn).with("
|
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
199
|
end
|
200
200
|
|
201
|
-
expect(logger).to receive(:warn).with("Wait 40s
|
202
|
-
|
203
|
-
expect(logger).to receive(:warn).with("
|
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
204
|
end
|
205
205
|
|
206
206
|
expect(Kernel).to receive(:sleep).exactly(60).with(2)
|
@@ -227,37 +227,37 @@ shared_examples 'when retry request' do
|
|
227
227
|
expect(logger).to receive(:error).exactly(6).with(parsed_response)
|
228
228
|
|
229
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:')
|
230
232
|
expect(logger).to receive(:warn).exactly(6).with(server_error.inspect)
|
231
233
|
|
232
|
-
expect(logger).to receive(:warn).with("Wait 8s
|
233
|
-
expect(logger).to receive(:warn).with("
|
234
|
-
expect(logger).to receive(:warn).with("
|
235
|
-
expect(logger).to receive(:warn).with("
|
236
|
-
|
237
|
-
|
238
|
-
expect(logger).to receive(:warn).with("
|
239
|
-
expect(logger).to receive(:warn).with("
|
240
|
-
expect(logger).to receive(:warn).with("
|
241
|
-
expect(logger).to receive(:warn).with("
|
242
|
-
expect(logger).to receive(:warn).with("
|
243
|
-
expect(logger).to receive(:warn).with("
|
244
|
-
expect(logger).to receive(:warn).with("
|
245
|
-
|
246
|
-
expect(logger).to receive(:warn).with("
|
247
|
-
|
248
|
-
|
249
|
-
12.times do |i|
|
250
|
-
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...")
|
251
251
|
end
|
252
252
|
|
253
|
-
expect(logger).to receive(:warn).with("Wait 32s
|
254
|
-
|
255
|
-
expect(logger).to receive(:warn).with("
|
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...")
|
256
256
|
end
|
257
257
|
|
258
|
-
expect(logger).to receive(:warn).with("Wait 40s
|
259
|
-
|
260
|
-
expect(logger).to receive(:warn).with("
|
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...")
|
261
261
|
end
|
262
262
|
|
263
263
|
expect(Kernel).to receive(:sleep).exactly(60).with(2)
|
@@ -238,6 +238,20 @@ describe KnapsackPro::Config::Env do
|
|
238
238
|
end
|
239
239
|
end
|
240
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
|
+
|
241
255
|
describe '.test_dir' do
|
242
256
|
subject { described_class.test_dir }
|
243
257
|
|
@@ -8,11 +8,11 @@ describe KnapsackPro::QueueAllocatorBuilder do
|
|
8
8
|
subject { allocator_builder.allocator }
|
9
9
|
|
10
10
|
before do
|
11
|
-
|
12
|
-
expect(allocator_builder).to receive(:
|
11
|
+
lazy_fast_and_slow_test_files_to_run = double
|
12
|
+
expect(allocator_builder).to receive(:lazy_fast_and_slow_test_files_to_run).and_return(lazy_fast_and_slow_test_files_to_run)
|
13
13
|
|
14
|
-
|
15
|
-
expect(allocator_builder).to receive(:
|
14
|
+
lazy_fallback_mode_test_files = double
|
15
|
+
expect(allocator_builder).to receive(:lazy_fallback_mode_test_files).and_return(lazy_fallback_mode_test_files)
|
16
16
|
|
17
17
|
repository_adapter = double
|
18
18
|
expect(KnapsackPro::RepositoryAdapterInitiator).to receive(:call).and_return(repository_adapter)
|
@@ -25,8 +25,8 @@ describe KnapsackPro::QueueAllocatorBuilder do
|
|
25
25
|
expect(KnapsackPro::Config::Env).to receive(:ci_node_build_id).and_return(ci_node_build_id)
|
26
26
|
|
27
27
|
expect(KnapsackPro::QueueAllocator).to receive(:new).with(
|
28
|
-
|
29
|
-
|
28
|
+
lazy_fast_and_slow_test_files_to_run: lazy_fast_and_slow_test_files_to_run,
|
29
|
+
lazy_fallback_mode_test_files: lazy_fallback_mode_test_files,
|
30
30
|
ci_node_total: ci_node_total,
|
31
31
|
ci_node_index: ci_node_index,
|
32
32
|
ci_node_build_id: ci_node_build_id,
|
@@ -1,6 +1,8 @@
|
|
1
1
|
describe KnapsackPro::QueueAllocator do
|
2
|
-
let(:
|
3
|
-
let(:
|
2
|
+
let(:lazy_loaded_fast_and_slow_test_files_to_run) { double }
|
3
|
+
let(:lazy_fast_and_slow_test_files_to_run) { double(call: lazy_loaded_fast_and_slow_test_files_to_run) }
|
4
|
+
let(:lazy_loaded_fallback_mode_test_files) { double }
|
5
|
+
let(:lazy_fallback_mode_test_files) { double(call: lazy_loaded_fallback_mode_test_files) }
|
4
6
|
let(:ci_node_total) { double }
|
5
7
|
let(:ci_node_index) { double }
|
6
8
|
let(:ci_node_build_id) { double }
|
@@ -8,8 +10,8 @@ describe KnapsackPro::QueueAllocator do
|
|
8
10
|
|
9
11
|
let(:queue_allocator) do
|
10
12
|
described_class.new(
|
11
|
-
|
12
|
-
|
13
|
+
lazy_fast_and_slow_test_files_to_run: lazy_fast_and_slow_test_files_to_run,
|
14
|
+
lazy_fallback_mode_test_files: lazy_fallback_mode_test_files,
|
13
15
|
ci_node_total: ci_node_total,
|
14
16
|
ci_node_index: ci_node_index,
|
15
17
|
ci_node_build_id: ci_node_build_id,
|
@@ -18,71 +20,13 @@ describe KnapsackPro::QueueAllocator do
|
|
18
20
|
end
|
19
21
|
|
20
22
|
describe '#test_file_paths' do
|
21
|
-
let(:can_initialize_queue) { double }
|
22
23
|
let(:executed_test_files) { [] }
|
23
24
|
let(:response) { double }
|
25
|
+
let(:api_code) { nil }
|
24
26
|
|
25
27
|
subject { queue_allocator.test_file_paths(can_initialize_queue, executed_test_files) }
|
26
28
|
|
27
|
-
|
28
|
-
encrypted_test_files = double
|
29
|
-
expect(KnapsackPro::Crypto::Encryptor).to receive(:call).with(fast_and_slow_test_files_to_run).and_return(encrypted_test_files)
|
30
|
-
|
31
|
-
encrypted_branch = double
|
32
|
-
expect(KnapsackPro::Crypto::BranchEncryptor).to receive(:call).with(repository_adapter.branch).and_return(encrypted_branch)
|
33
|
-
|
34
|
-
action = double
|
35
|
-
expect(KnapsackPro::Client::API::V1::Queues).to receive(:queue).with(
|
36
|
-
can_initialize_queue: can_initialize_queue,
|
37
|
-
commit_hash: repository_adapter.commit_hash,
|
38
|
-
branch: encrypted_branch,
|
39
|
-
node_total: ci_node_total,
|
40
|
-
node_index: ci_node_index,
|
41
|
-
node_build_id: ci_node_build_id,
|
42
|
-
test_files: encrypted_test_files,
|
43
|
-
).and_return(action)
|
44
|
-
|
45
|
-
connection = instance_double(KnapsackPro::Client::Connection,
|
46
|
-
call: response,
|
47
|
-
success?: success?,
|
48
|
-
errors?: errors?)
|
49
|
-
expect(KnapsackPro::Client::Connection).to receive(:new).with(action).and_return(connection)
|
50
|
-
end
|
51
|
-
|
52
|
-
context 'when successful request to API' do
|
53
|
-
let(:success?) { true }
|
54
|
-
|
55
|
-
context 'when response has errors' do
|
56
|
-
let(:errors?) { true }
|
57
|
-
|
58
|
-
it do
|
59
|
-
expect { subject }.to raise_error(ArgumentError)
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
context 'when response has no errors' do
|
64
|
-
let(:errors?) { false }
|
65
|
-
let(:response) do
|
66
|
-
{
|
67
|
-
'test_files' => [
|
68
|
-
{ 'path' => 'a_spec.rb' },
|
69
|
-
{ 'path' => 'b_spec.rb' },
|
70
|
-
]
|
71
|
-
}
|
72
|
-
end
|
73
|
-
|
74
|
-
before do
|
75
|
-
expect(KnapsackPro::Crypto::Decryptor).to receive(:call).with(fast_and_slow_test_files_to_run, response['test_files']).and_call_original
|
76
|
-
end
|
77
|
-
|
78
|
-
it { should eq ['a_spec.rb', 'b_spec.rb'] }
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
context 'when not successful request to API' do
|
83
|
-
let(:success?) { false }
|
84
|
-
let(:errors?) { false }
|
85
|
-
|
29
|
+
shared_examples_for 'when connection to API failed (fallback mode)' do
|
86
30
|
context 'when fallback mode is disabled' do
|
87
31
|
before do
|
88
32
|
expect(KnapsackPro::Config::Env).to receive(:fallback_mode_enabled?).and_return(false)
|
@@ -122,7 +66,7 @@ describe KnapsackPro::QueueAllocator do
|
|
122
66
|
context 'when fallback mode started' do
|
123
67
|
before do
|
124
68
|
test_flat_distributor = instance_double(KnapsackPro::TestFlatDistributor)
|
125
|
-
expect(KnapsackPro::TestFlatDistributor).to receive(:new).with(
|
69
|
+
expect(KnapsackPro::TestFlatDistributor).to receive(:new).with(lazy_loaded_fallback_mode_test_files, ci_node_total).and_return(test_flat_distributor)
|
126
70
|
expect(test_flat_distributor).to receive(:test_files_for_node).with(ci_node_index).and_return([
|
127
71
|
{ 'path' => 'c_spec.rb' },
|
128
72
|
{ 'path' => 'd_spec.rb' },
|
@@ -146,5 +90,256 @@ describe KnapsackPro::QueueAllocator do
|
|
146
90
|
end
|
147
91
|
end
|
148
92
|
end
|
93
|
+
|
94
|
+
context 'when can_initialize_queue=true' do
|
95
|
+
let(:can_initialize_queue) { true }
|
96
|
+
|
97
|
+
before do
|
98
|
+
encrypted_branch = double
|
99
|
+
expect(KnapsackPro::Crypto::BranchEncryptor).to receive(:call).with(repository_adapter.branch).and_return(encrypted_branch)
|
100
|
+
|
101
|
+
action = double
|
102
|
+
expect(KnapsackPro::Client::API::V1::Queues).to receive(:queue).with(
|
103
|
+
can_initialize_queue: can_initialize_queue,
|
104
|
+
attempt_connect_to_queue: true, # when can_initialize_queue=true then expect attempt_connect_to_queue=true
|
105
|
+
commit_hash: repository_adapter.commit_hash,
|
106
|
+
branch: encrypted_branch,
|
107
|
+
node_total: ci_node_total,
|
108
|
+
node_index: ci_node_index,
|
109
|
+
node_build_id: ci_node_build_id,
|
110
|
+
test_files: nil, # when attempt_connect_to_queue=true then expect test_files is nil to make fast request to API
|
111
|
+
).and_return(action)
|
112
|
+
|
113
|
+
connection = instance_double(KnapsackPro::Client::Connection,
|
114
|
+
call: response,
|
115
|
+
success?: success?,
|
116
|
+
errors?: errors?,
|
117
|
+
api_code: api_code)
|
118
|
+
expect(KnapsackPro::Client::Connection).to receive(:new).with(action).and_return(connection)
|
119
|
+
end
|
120
|
+
|
121
|
+
context 'when successful request to API' do
|
122
|
+
let(:success?) { true }
|
123
|
+
|
124
|
+
context 'when response has errors' do
|
125
|
+
let(:errors?) { true }
|
126
|
+
|
127
|
+
it do
|
128
|
+
expect { subject }.to raise_error(ArgumentError)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
context 'when response has no errors' do
|
133
|
+
let(:errors?) { false }
|
134
|
+
|
135
|
+
context 'when response returns test files (successful attempt to connect to queue already existing on the API side)' do
|
136
|
+
let(:test_files) do
|
137
|
+
[
|
138
|
+
{ 'path' => 'a_spec.rb' },
|
139
|
+
{ 'path' => 'b_spec.rb' },
|
140
|
+
]
|
141
|
+
end
|
142
|
+
let(:response) do
|
143
|
+
{ 'test_files' => test_files }
|
144
|
+
end
|
145
|
+
|
146
|
+
context 'when test files encryption is enabled' do
|
147
|
+
before do
|
148
|
+
expect(KnapsackPro::Config::Env).to receive(:test_files_encrypted?).and_return(true)
|
149
|
+
expect(KnapsackPro::Crypto::Decryptor).to receive(:call).with(lazy_loaded_fast_and_slow_test_files_to_run, response['test_files']).and_return(test_files)
|
150
|
+
end
|
151
|
+
|
152
|
+
it { should eq ['a_spec.rb', 'b_spec.rb'] }
|
153
|
+
end
|
154
|
+
|
155
|
+
context 'when test files encryption is disabled' do
|
156
|
+
before do
|
157
|
+
expect(KnapsackPro::Config::Env).to receive(:test_files_encrypted?).and_return(false)
|
158
|
+
end
|
159
|
+
|
160
|
+
it { should eq ['a_spec.rb', 'b_spec.rb'] }
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
context 'when response has code=ATTEMPT_CONNECT_TO_QUEUE_FAILED' do
|
165
|
+
let(:response) do
|
166
|
+
{ 'code' => 'ATTEMPT_CONNECT_TO_QUEUE_FAILED' }
|
167
|
+
end
|
168
|
+
let(:api_code) { 'ATTEMPT_CONNECT_TO_QUEUE_FAILED' }
|
169
|
+
|
170
|
+
before do
|
171
|
+
encrypted_branch = double
|
172
|
+
expect(KnapsackPro::Crypto::BranchEncryptor).to receive(:call).with(repository_adapter.branch).and_return(encrypted_branch)
|
173
|
+
|
174
|
+
encrypted_test_files = double
|
175
|
+
expect(KnapsackPro::Crypto::Encryptor).to receive(:call).with(lazy_loaded_fast_and_slow_test_files_to_run).and_return(encrypted_test_files)
|
176
|
+
|
177
|
+
# 2nd request is no more an attempt to connect to queue.
|
178
|
+
# We want to try to initalize a new queue so we will also send list of test files from disk.
|
179
|
+
action = double
|
180
|
+
expect(KnapsackPro::Client::API::V1::Queues).to receive(:queue).with(
|
181
|
+
can_initialize_queue: can_initialize_queue,
|
182
|
+
attempt_connect_to_queue: false,
|
183
|
+
commit_hash: repository_adapter.commit_hash,
|
184
|
+
branch: encrypted_branch,
|
185
|
+
node_total: ci_node_total,
|
186
|
+
node_index: ci_node_index,
|
187
|
+
node_build_id: ci_node_build_id,
|
188
|
+
test_files: encrypted_test_files,
|
189
|
+
).and_return(action)
|
190
|
+
|
191
|
+
connection = instance_double(KnapsackPro::Client::Connection,
|
192
|
+
call: response2,
|
193
|
+
success?: response2_success?,
|
194
|
+
errors?: response2_errors?,
|
195
|
+
api_code: nil)
|
196
|
+
expect(KnapsackPro::Client::Connection).to receive(:new).with(action).and_return(connection)
|
197
|
+
end
|
198
|
+
|
199
|
+
context 'when successful 2nd request to API' do
|
200
|
+
let(:response2_success?) { true }
|
201
|
+
|
202
|
+
context 'when 2nd response has errors' do
|
203
|
+
let(:response2_errors?) { true }
|
204
|
+
let(:response2) { nil }
|
205
|
+
|
206
|
+
it do
|
207
|
+
expect { subject }.to raise_error(ArgumentError)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
context 'when 2nd response has no errors' do
|
212
|
+
let(:response2_errors?) { false }
|
213
|
+
|
214
|
+
context 'when 2nd response returns test files (successful attempt to connect to queue already existing on the API side)' do
|
215
|
+
let(:test_files) do
|
216
|
+
[
|
217
|
+
{ 'path' => 'a_spec.rb' },
|
218
|
+
{ 'path' => 'b_spec.rb' },
|
219
|
+
]
|
220
|
+
end
|
221
|
+
let(:response2) do
|
222
|
+
{ 'test_files' => test_files }
|
223
|
+
end
|
224
|
+
|
225
|
+
context 'when test files encryption is enabled' do
|
226
|
+
before do
|
227
|
+
expect(KnapsackPro::Config::Env).to receive(:test_files_encrypted?).and_return(true)
|
228
|
+
expect(KnapsackPro::Crypto::Decryptor).to receive(:call).with(lazy_loaded_fast_and_slow_test_files_to_run, response2['test_files']).and_return(test_files)
|
229
|
+
end
|
230
|
+
|
231
|
+
it { should eq ['a_spec.rb', 'b_spec.rb'] }
|
232
|
+
end
|
233
|
+
|
234
|
+
context 'when test files encryption is disabled' do
|
235
|
+
before do
|
236
|
+
expect(KnapsackPro::Config::Env).to receive(:test_files_encrypted?).and_return(false)
|
237
|
+
end
|
238
|
+
|
239
|
+
it { should eq ['a_spec.rb', 'b_spec.rb'] }
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
context 'when not successful 2nd request to API' do
|
246
|
+
let(:response2_success?) { false }
|
247
|
+
let(:response2_errors?) { false }
|
248
|
+
let(:response2) { nil }
|
249
|
+
|
250
|
+
it_behaves_like 'when connection to API failed (fallback mode)'
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
context 'when not successful request to API' do
|
257
|
+
let(:success?) { false }
|
258
|
+
let(:errors?) { false }
|
259
|
+
|
260
|
+
it_behaves_like 'when connection to API failed (fallback mode)'
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
context 'when can_initialize_queue=false' do
|
265
|
+
let(:can_initialize_queue) { false }
|
266
|
+
let(:api_code) { nil }
|
267
|
+
|
268
|
+
before do
|
269
|
+
encrypted_branch = double
|
270
|
+
expect(KnapsackPro::Crypto::BranchEncryptor).to receive(:call).with(repository_adapter.branch).and_return(encrypted_branch)
|
271
|
+
|
272
|
+
action = double
|
273
|
+
expect(KnapsackPro::Client::API::V1::Queues).to receive(:queue).with(
|
274
|
+
can_initialize_queue: can_initialize_queue,
|
275
|
+
attempt_connect_to_queue: false, # when can_initialize_queue=false then expect attempt_connect_to_queue=false
|
276
|
+
commit_hash: repository_adapter.commit_hash,
|
277
|
+
branch: encrypted_branch,
|
278
|
+
node_total: ci_node_total,
|
279
|
+
node_index: ci_node_index,
|
280
|
+
node_build_id: ci_node_build_id,
|
281
|
+
test_files: nil, # when can_initialize_queue=false then expect test_files is nil to make fast request to API
|
282
|
+
).and_return(action)
|
283
|
+
|
284
|
+
connection = instance_double(KnapsackPro::Client::Connection,
|
285
|
+
call: response,
|
286
|
+
success?: success?,
|
287
|
+
errors?: errors?,
|
288
|
+
api_code: api_code)
|
289
|
+
expect(KnapsackPro::Client::Connection).to receive(:new).with(action).and_return(connection)
|
290
|
+
end
|
291
|
+
|
292
|
+
context 'when successful request to API' do
|
293
|
+
let(:success?) { true }
|
294
|
+
|
295
|
+
context 'when response has errors' do
|
296
|
+
let(:errors?) { true }
|
297
|
+
|
298
|
+
it do
|
299
|
+
expect { subject }.to raise_error(ArgumentError)
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
context 'when response has no errors' do
|
304
|
+
let(:errors?) { false }
|
305
|
+
|
306
|
+
context 'when response returns test files (successful attempt to connect to queue already existing on the API side)' do
|
307
|
+
let(:test_files) do
|
308
|
+
[
|
309
|
+
{ 'path' => 'a_spec.rb' },
|
310
|
+
{ 'path' => 'b_spec.rb' },
|
311
|
+
]
|
312
|
+
end
|
313
|
+
let(:response) do
|
314
|
+
{ 'test_files' => test_files }
|
315
|
+
end
|
316
|
+
|
317
|
+
context 'when test files encryption is enabled' do
|
318
|
+
before do
|
319
|
+
expect(KnapsackPro::Config::Env).to receive(:test_files_encrypted?).and_return(true)
|
320
|
+
expect(KnapsackPro::Crypto::Decryptor).to receive(:call).with(lazy_loaded_fast_and_slow_test_files_to_run, response['test_files']).and_return(test_files)
|
321
|
+
end
|
322
|
+
|
323
|
+
it { should eq ['a_spec.rb', 'b_spec.rb'] }
|
324
|
+
end
|
325
|
+
|
326
|
+
context 'when test files encryption is disabled' do
|
327
|
+
before do
|
328
|
+
expect(KnapsackPro::Config::Env).to receive(:test_files_encrypted?).and_return(false)
|
329
|
+
end
|
330
|
+
|
331
|
+
it { should eq ['a_spec.rb', 'b_spec.rb'] }
|
332
|
+
end
|
333
|
+
end
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
context 'when not successful request to API' do
|
338
|
+
let(:success?) { false }
|
339
|
+
let(:errors?) { false }
|
340
|
+
|
341
|
+
it_behaves_like 'when connection to API failed (fallback mode)'
|
342
|
+
end
|
343
|
+
end
|
149
344
|
end
|
150
345
|
end
|
@@ -67,7 +67,7 @@ describe KnapsackPro::TestCaseDetectors::RSpecTestExampleDetector do
|
|
67
67
|
let(:exit_code) { 1 }
|
68
68
|
|
69
69
|
it do
|
70
|
-
expect { subject }.to raise_error(RuntimeError, 'There was problem
|
70
|
+
expect { subject }.to raise_error(RuntimeError, 'There was a problem while generating test examples for the slow test files. Please read actionable error message above.')
|
71
71
|
end
|
72
72
|
end
|
73
73
|
end
|
@@ -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.
|
4
|
+
version: 2.10.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-
|
11
|
+
date: 2020-11-25 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
|