knapsack_pro 3.5.0 → 3.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -0
- data/lib/knapsack_pro/adapters/rspec_adapter.rb +8 -4
- data/lib/knapsack_pro/allocator.rb +19 -3
- data/lib/knapsack_pro/client/api/v1/build_distributions.rb +19 -8
- data/lib/knapsack_pro/queue_allocator.rb +0 -1
- data/lib/knapsack_pro/tracker.rb +2 -1
- data/lib/knapsack_pro/version.rb +1 -1
- data/spec/fixtures/vcr_cassettes/api/v1/build_distributions/subset/invalid_test_suite_token.yml +25 -16
- data/spec/fixtures/vcr_cassettes/api/v1/build_distributions/subset/success.yml +27 -18
- data/spec/integration/api/build_distributions_subset_spec.rb +1 -0
- data/spec/knapsack_pro/adapters/rspec_adapter_spec.rb +4 -0
- data/spec/knapsack_pro/allocator_spec.rb +140 -57
- data/spec/knapsack_pro/client/api/v1/build_distributions_spec.rb +46 -15
- data/spec/knapsack_pro/queue_allocator_spec.rb +2 -5
- data/spec/knapsack_pro/tracker_spec.rb +1 -3
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 98e74bc85a91b0e94977b272f81e7efcd85a3ca242b4c7afc3d61340e56b02e4
|
4
|
+
data.tar.gz: 8732eb25ee525d4d3d73a7dc0c23ed92ebe3597bf4a24946a8ae7a291a7746ee
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 87f2bbebde7460541fa539fea85fa195b52e1e84cd4a40e296287ba6e35dd682ab7676b28822911483e2aee1ff711421995c3b75a7cd31b2a095e7c76971acdc
|
7
|
+
data.tar.gz: d4ed38d722c0b7a3bdad17bb292c20a5040f583ad3b3aa45371e364a0d9d0bac6168d1d37350a224d4494ff88cb2db1c641d2e45b88fe812eed2c5c3f37d2d50
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,21 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
### 3.7.0
|
4
|
+
|
5
|
+
* Adjust the timer behaviour in the RSpec adapter
|
6
|
+
|
7
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/pull/184
|
8
|
+
|
9
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v3.6.0...v3.7.0
|
10
|
+
|
11
|
+
### 3.6.0
|
12
|
+
|
13
|
+
* Add an attempt to read from the cache for Regular Mode API
|
14
|
+
|
15
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/pull/182
|
16
|
+
|
17
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v3.5.0...v3.6.0
|
18
|
+
|
3
19
|
### 3.5.0
|
4
20
|
|
5
21
|
* Add the `KnapsackPro::Hooks::Queue.before_subset_queue` hook in Queue Mode
|
@@ -48,12 +48,16 @@ module KnapsackPro
|
|
48
48
|
end
|
49
49
|
|
50
50
|
config.around(:each) do |example|
|
51
|
-
# stop timer to update time for a previously run test example
|
52
|
-
# this way we count time spend in runtime for the previous test example after around(:each) is already done
|
53
|
-
KnapsackPro.tracker.stop_timer
|
54
|
-
|
55
51
|
current_test_path = KnapsackPro::Adapters::RSpecAdapter.test_path(example)
|
56
52
|
|
53
|
+
# Stop timer to update time for a previously run test example.
|
54
|
+
# This way we count time spent in runtime for the previous test example after around(:each) is already done.
|
55
|
+
# Only do that if we're in the same test file. Otherwise, `before(:all)` execution time in the current file
|
56
|
+
# will be applied to the previously ran test file.
|
57
|
+
if KnapsackPro.tracker.current_test_path&.start_with?(KnapsackPro::TestFileCleaner.clean(current_test_path))
|
58
|
+
KnapsackPro.tracker.stop_timer
|
59
|
+
end
|
60
|
+
|
57
61
|
KnapsackPro.tracker.current_test_path =
|
58
62
|
if KnapsackPro::Config::Env.rspec_split_by_test_examples? && KnapsackPro::Adapters::RSpecAdapter.slow_test_file?(RSpecAdapter, current_test_path)
|
59
63
|
example.id
|
@@ -9,8 +9,18 @@ module KnapsackPro
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def test_file_paths
|
12
|
-
|
12
|
+
action = build_action(cache_read_attempt: true)
|
13
|
+
connection = KnapsackPro::Client::Connection.new(action)
|
13
14
|
response = connection.call
|
15
|
+
|
16
|
+
# when a cache miss because the test suite split was not cached yet
|
17
|
+
if connection.success? && connection.api_code == KnapsackPro::Client::API::V1::BuildDistributions::TEST_SUITE_SPLIT_CACHE_MISS_CODE
|
18
|
+
# make an attempt to initalize a new test suite split on the API side
|
19
|
+
action = build_action(cache_read_attempt: false)
|
20
|
+
connection = KnapsackPro::Client::Connection.new(action)
|
21
|
+
response = connection.call
|
22
|
+
end
|
23
|
+
|
14
24
|
if connection.success?
|
15
25
|
raise ArgumentError.new(response) if connection.errors?
|
16
26
|
prepare_test_files(response)
|
@@ -47,13 +57,19 @@ module KnapsackPro
|
|
47
57
|
KnapsackPro::Crypto::BranchEncryptor.call(repository_adapter.branch)
|
48
58
|
end
|
49
59
|
|
50
|
-
def build_action
|
60
|
+
def build_action(cache_read_attempt:)
|
61
|
+
test_files =
|
62
|
+
unless cache_read_attempt
|
63
|
+
encrypted_test_files
|
64
|
+
end
|
65
|
+
|
51
66
|
KnapsackPro::Client::API::V1::BuildDistributions.subset(
|
67
|
+
cache_read_attempt: cache_read_attempt,
|
52
68
|
commit_hash: repository_adapter.commit_hash,
|
53
69
|
branch: encrypted_branch,
|
54
70
|
node_total: ci_node_total,
|
55
71
|
node_index: ci_node_index,
|
56
|
-
test_files:
|
72
|
+
test_files: test_files,
|
57
73
|
)
|
58
74
|
end
|
59
75
|
|
@@ -3,19 +3,30 @@ module KnapsackPro
|
|
3
3
|
module API
|
4
4
|
module V1
|
5
5
|
class BuildDistributions < Base
|
6
|
+
TEST_SUITE_SPLIT_CACHE_MISS_CODE = 'TEST_SUITE_SPLIT_CACHE_MISS'
|
7
|
+
|
6
8
|
class << self
|
7
9
|
def subset(args)
|
10
|
+
request_hash = {
|
11
|
+
:fixed_test_suite_split => KnapsackPro::Config::Env.fixed_test_suite_split,
|
12
|
+
:cache_read_attempt => args.fetch(:cache_read_attempt),
|
13
|
+
:commit_hash => args.fetch(:commit_hash),
|
14
|
+
:branch => args.fetch(:branch),
|
15
|
+
:node_total => args.fetch(:node_total),
|
16
|
+
:node_index => args.fetch(:node_index),
|
17
|
+
:ci_build_id => KnapsackPro::Config::Env.ci_node_build_id,
|
18
|
+
}
|
19
|
+
|
20
|
+
unless request_hash[:cache_read_attempt]
|
21
|
+
request_hash.merge!({
|
22
|
+
:test_files => args.fetch(:test_files)
|
23
|
+
})
|
24
|
+
end
|
25
|
+
|
8
26
|
action_class.new(
|
9
27
|
endpoint_path: '/v1/build_distributions/subset',
|
10
28
|
http_method: :post,
|
11
|
-
request_hash:
|
12
|
-
:fixed_test_suite_split => KnapsackPro::Config::Env.fixed_test_suite_split,
|
13
|
-
:commit_hash => args.fetch(:commit_hash),
|
14
|
-
:branch => args.fetch(:branch),
|
15
|
-
:node_total => args.fetch(:node_total),
|
16
|
-
:node_index => args.fetch(:node_index),
|
17
|
-
:test_files => args.fetch(:test_files)
|
18
|
-
}
|
29
|
+
request_hash: request_hash
|
19
30
|
)
|
20
31
|
end
|
21
32
|
|
@@ -62,7 +62,6 @@ module KnapsackPro
|
|
62
62
|
end
|
63
63
|
|
64
64
|
def build_action(can_initialize_queue, attempt_connect_to_queue:)
|
65
|
-
# read test files from disk only when needed because it can be slow operation
|
66
65
|
test_files =
|
67
66
|
if can_initialize_queue && !attempt_connect_to_queue
|
68
67
|
encrypted_test_files
|
data/lib/knapsack_pro/tracker.rb
CHANGED
@@ -46,7 +46,8 @@ module KnapsackPro
|
|
46
46
|
end
|
47
47
|
|
48
48
|
def current_test_path
|
49
|
-
|
49
|
+
return unless @current_test_path
|
50
|
+
|
50
51
|
KnapsackPro::TestFileCleaner.clean(@current_test_path)
|
51
52
|
end
|
52
53
|
|
data/lib/knapsack_pro/version.rb
CHANGED
data/spec/fixtures/vcr_cassettes/api/v1/build_distributions/subset/invalid_test_suite_token.yml
CHANGED
@@ -5,12 +5,18 @@ http_interactions:
|
|
5
5
|
uri: http://api.knapsackpro.test:3000/v1/build_distributions/subset
|
6
6
|
body:
|
7
7
|
encoding: UTF-8
|
8
|
-
string: '{"commit_hash":"abcdefg","branch":"master","node_total":"2","node_index":"1","
|
8
|
+
string: '{"fixed_test_suite_split":true,"cache_read_attempt":true,"commit_hash":"abcdefg","branch":"master","node_total":"2","node_index":"1","ci_build_id":"missing-build-id"}'
|
9
9
|
headers:
|
10
10
|
Content-Type:
|
11
11
|
- application/json
|
12
12
|
Accept:
|
13
13
|
- application/json
|
14
|
+
Knapsack-Pro-Client-Name:
|
15
|
+
- knapsack_pro-ruby
|
16
|
+
Knapsack-Pro-Client-Version:
|
17
|
+
- 3.5.0
|
18
|
+
Knapsack-Pro-Test-Suite-Token:
|
19
|
+
- fake
|
14
20
|
Accept-Encoding:
|
15
21
|
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
16
22
|
User-Agent:
|
@@ -18,33 +24,36 @@ http_interactions:
|
|
18
24
|
response:
|
19
25
|
status:
|
20
26
|
code: 403
|
21
|
-
message:
|
27
|
+
message: Forbidden
|
22
28
|
headers:
|
23
29
|
X-Frame-Options:
|
24
30
|
- SAMEORIGIN
|
25
31
|
X-Xss-Protection:
|
26
|
-
-
|
32
|
+
- '0'
|
27
33
|
X-Content-Type-Options:
|
28
34
|
- nosniff
|
35
|
+
X-Download-Options:
|
36
|
+
- noopen
|
37
|
+
X-Permitted-Cross-Domain-Policies:
|
38
|
+
- none
|
39
|
+
Referrer-Policy:
|
40
|
+
- strict-origin-when-cross-origin
|
29
41
|
Content-Type:
|
30
42
|
- application/json; charset=utf-8
|
31
43
|
Cache-Control:
|
32
44
|
- no-cache
|
33
45
|
X-Request-Id:
|
34
|
-
-
|
46
|
+
- a5ffe97f-4558-426b-9475-166eb89ab7cb
|
35
47
|
X-Runtime:
|
36
|
-
- '0.
|
37
|
-
Server:
|
38
|
-
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
-
|
43
|
-
Connection:
|
44
|
-
- Keep-Alive
|
48
|
+
- '0.231483'
|
49
|
+
Server-Timing:
|
50
|
+
- sql.active_record;dur=24.31, start_processing.action_controller;dur=0.00,
|
51
|
+
instantiation.active_record;dur=0.02, halted_callback.action_controller;dur=0.00,
|
52
|
+
process_action.action_controller;dur=15.10
|
53
|
+
Transfer-Encoding:
|
54
|
+
- chunked
|
45
55
|
body:
|
46
56
|
encoding: UTF-8
|
47
57
|
string: '{"errors":["invalid test suite token"]}'
|
48
|
-
|
49
|
-
|
50
|
-
recorded_with: VCR 2.9.3
|
58
|
+
recorded_at: Thu, 08 Dec 2022 23:27:10 GMT
|
59
|
+
recorded_with: VCR 6.1.0
|
@@ -5,12 +5,18 @@ http_interactions:
|
|
5
5
|
uri: http://api.knapsackpro.test:3000/v1/build_distributions/subset
|
6
6
|
body:
|
7
7
|
encoding: UTF-8
|
8
|
-
string: '{"commit_hash":"abcdefg","branch":"master","node_total":"2","node_index":"1","
|
8
|
+
string: '{"fixed_test_suite_split":true,"cache_read_attempt":true,"commit_hash":"abcdefg","branch":"master","node_total":"2","node_index":"1","ci_build_id":"missing-build-id"}'
|
9
9
|
headers:
|
10
10
|
Content-Type:
|
11
11
|
- application/json
|
12
12
|
Accept:
|
13
13
|
- application/json
|
14
|
+
Knapsack-Pro-Client-Name:
|
15
|
+
- knapsack_pro-ruby
|
16
|
+
Knapsack-Pro-Client-Version:
|
17
|
+
- 3.5.0
|
18
|
+
Knapsack-Pro-Test-Suite-Token:
|
19
|
+
- 3fa64859337f6e56409d49f865d13fd7
|
14
20
|
Accept-Encoding:
|
15
21
|
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
16
22
|
User-Agent:
|
@@ -18,35 +24,38 @@ http_interactions:
|
|
18
24
|
response:
|
19
25
|
status:
|
20
26
|
code: 200
|
21
|
-
message:
|
27
|
+
message: OK
|
22
28
|
headers:
|
23
29
|
X-Frame-Options:
|
24
30
|
- SAMEORIGIN
|
25
31
|
X-Xss-Protection:
|
26
|
-
-
|
32
|
+
- '0'
|
27
33
|
X-Content-Type-Options:
|
28
34
|
- nosniff
|
35
|
+
X-Download-Options:
|
36
|
+
- noopen
|
37
|
+
X-Permitted-Cross-Domain-Policies:
|
38
|
+
- none
|
39
|
+
Referrer-Policy:
|
40
|
+
- strict-origin-when-cross-origin
|
29
41
|
Content-Type:
|
30
42
|
- application/json; charset=utf-8
|
31
43
|
Etag:
|
32
|
-
- W/"
|
44
|
+
- W/"1f643e3528e8ff45d9d2d67ab7e32be1"
|
33
45
|
Cache-Control:
|
34
46
|
- max-age=0, private, must-revalidate
|
35
47
|
X-Request-Id:
|
36
|
-
-
|
48
|
+
- 9b378323-c960-4868-894e-5ae0cdab8840
|
37
49
|
X-Runtime:
|
38
|
-
- '0.
|
39
|
-
Server:
|
40
|
-
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
-
|
45
|
-
Connection:
|
46
|
-
- Keep-Alive
|
50
|
+
- '0.273775'
|
51
|
+
Server-Timing:
|
52
|
+
- sql.active_record;dur=55.90, start_processing.action_controller;dur=0.00,
|
53
|
+
unpermitted_parameters.action_controller;dur=0.01, instantiation.active_record;dur=10.69,
|
54
|
+
process_action.action_controller;dur=92.24
|
55
|
+
Transfer-Encoding:
|
56
|
+
- chunked
|
47
57
|
body:
|
48
58
|
encoding: UTF-8
|
49
|
-
string: '{"
|
50
|
-
|
51
|
-
|
52
|
-
recorded_with: VCR 2.9.3
|
59
|
+
string: '{"code":"TEST_SUITE_SPLIT_CACHE_MISS"}'
|
60
|
+
recorded_at: Thu, 08 Dec 2022 23:27:07 GMT
|
61
|
+
recorded_with: VCR 6.1.0
|
@@ -243,6 +243,7 @@ describe KnapsackPro::Adapters::RSpecAdapter do
|
|
243
243
|
expect(config).to receive(:around).with(:each).and_yield(current_example)
|
244
244
|
expect(::RSpec).to receive(:configure).and_yield(config)
|
245
245
|
|
246
|
+
expect(tracker).to receive(:current_test_path).ordered.and_return(test_path)
|
246
247
|
expect(tracker).to receive(:stop_timer).ordered
|
247
248
|
|
248
249
|
expect(described_class).to receive(:test_path).with(current_example).and_return(test_path)
|
@@ -273,6 +274,7 @@ describe KnapsackPro::Adapters::RSpecAdapter do
|
|
273
274
|
expect(config).to receive(:after).with(:suite).and_yield
|
274
275
|
expect(::RSpec).to receive(:configure).and_yield(config)
|
275
276
|
|
277
|
+
expect(tracker).to receive(:current_test_path).ordered.and_return(test_path)
|
276
278
|
expect(tracker).to receive(:stop_timer).ordered
|
277
279
|
|
278
280
|
expect(described_class).to receive(:test_path).with(current_example).and_return(test_path)
|
@@ -316,6 +318,7 @@ describe KnapsackPro::Adapters::RSpecAdapter do
|
|
316
318
|
expect(config).to receive(:after).with(:suite).and_yield
|
317
319
|
expect(::RSpec).to receive(:configure).and_yield(config)
|
318
320
|
|
321
|
+
expect(tracker).to receive(:current_test_path).ordered.and_return(test_path)
|
319
322
|
expect(tracker).to receive(:stop_timer).ordered
|
320
323
|
|
321
324
|
expect(described_class).to receive(:test_path).with(current_example).and_return(test_path)
|
@@ -352,6 +355,7 @@ describe KnapsackPro::Adapters::RSpecAdapter do
|
|
352
355
|
|
353
356
|
expect(described_class).to receive(:test_path).with(current_example).and_return(test_path)
|
354
357
|
|
358
|
+
expect(tracker).to receive(:current_test_path).ordered.and_return(test_path)
|
355
359
|
expect(tracker).to receive(:stop_timer).ordered
|
356
360
|
|
357
361
|
expect(tracker).to receive(:current_test_path=).with(test_path).ordered
|
@@ -17,66 +17,11 @@ describe KnapsackPro::Allocator do
|
|
17
17
|
|
18
18
|
describe '#test_file_paths' do
|
19
19
|
let(:response) { double }
|
20
|
+
let(:api_code) { nil }
|
20
21
|
|
21
22
|
subject { allocator.test_file_paths }
|
22
23
|
|
23
|
-
|
24
|
-
encrypted_test_files = double
|
25
|
-
expect(KnapsackPro::Crypto::Encryptor).to receive(:call).with(fast_and_slow_test_files_to_run).and_return(encrypted_test_files)
|
26
|
-
|
27
|
-
encrypted_branch = double
|
28
|
-
expect(KnapsackPro::Crypto::BranchEncryptor).to receive(:call).with(repository_adapter.branch).and_return(encrypted_branch)
|
29
|
-
|
30
|
-
action = double
|
31
|
-
expect(KnapsackPro::Client::API::V1::BuildDistributions).to receive(:subset).with({
|
32
|
-
commit_hash: repository_adapter.commit_hash,
|
33
|
-
branch: encrypted_branch,
|
34
|
-
node_total: ci_node_total,
|
35
|
-
node_index: ci_node_index,
|
36
|
-
test_files: encrypted_test_files,
|
37
|
-
}).and_return(action)
|
38
|
-
|
39
|
-
connection = instance_double(KnapsackPro::Client::Connection,
|
40
|
-
call: response,
|
41
|
-
success?: success?,
|
42
|
-
errors?: errors?)
|
43
|
-
expect(KnapsackPro::Client::Connection).to receive(:new).with(action).and_return(connection)
|
44
|
-
end
|
45
|
-
|
46
|
-
context 'when successful request to API' do
|
47
|
-
let(:success?) { true }
|
48
|
-
|
49
|
-
context 'when response has errors' do
|
50
|
-
let(:errors?) { true }
|
51
|
-
|
52
|
-
it do
|
53
|
-
expect { subject }.to raise_error(ArgumentError)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
context 'when response has no errors' do
|
58
|
-
let(:errors?) { false }
|
59
|
-
let(:response) do
|
60
|
-
{
|
61
|
-
'test_files' => [
|
62
|
-
{ 'path' => 'a_spec.rb' },
|
63
|
-
{ 'path' => 'b_spec.rb' },
|
64
|
-
]
|
65
|
-
}
|
66
|
-
end
|
67
|
-
|
68
|
-
before do
|
69
|
-
expect(KnapsackPro::Crypto::Decryptor).to receive(:call).with(fast_and_slow_test_files_to_run, response['test_files']).and_call_original
|
70
|
-
end
|
71
|
-
|
72
|
-
it { should eq ['a_spec.rb', 'b_spec.rb'] }
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
context 'when not successful request to API' do
|
77
|
-
let(:success?) { false }
|
78
|
-
let(:errors?) { false }
|
79
|
-
|
24
|
+
shared_examples_for 'when connection to API failed (fallback mode)' do
|
80
25
|
context 'when fallback mode is disabled' do
|
81
26
|
before do
|
82
27
|
expect(KnapsackPro::Config::Env).to receive(:fallback_mode_enabled?).and_return(false)
|
@@ -126,5 +71,143 @@ describe KnapsackPro::Allocator do
|
|
126
71
|
it { should eq ['c_spec.rb', 'd_spec.rb'] }
|
127
72
|
end
|
128
73
|
end
|
74
|
+
|
75
|
+
before do
|
76
|
+
encrypted_branch = double
|
77
|
+
expect(KnapsackPro::Crypto::BranchEncryptor).to receive(:call).with(repository_adapter.branch).and_return(encrypted_branch)
|
78
|
+
|
79
|
+
action = double
|
80
|
+
expect(KnapsackPro::Client::API::V1::BuildDistributions).to receive(:subset).with({
|
81
|
+
cache_read_attempt: true,
|
82
|
+
commit_hash: repository_adapter.commit_hash,
|
83
|
+
branch: encrypted_branch,
|
84
|
+
node_total: ci_node_total,
|
85
|
+
node_index: ci_node_index,
|
86
|
+
test_files: nil, # when `cache_read_attempt=true`, then expect `test_files` is `nil` to make the request fast due to a small payload
|
87
|
+
}).and_return(action)
|
88
|
+
|
89
|
+
connection = instance_double(KnapsackPro::Client::Connection,
|
90
|
+
call: response,
|
91
|
+
success?: success?,
|
92
|
+
errors?: errors?,
|
93
|
+
api_code: api_code)
|
94
|
+
expect(KnapsackPro::Client::Connection).to receive(:new).with(action).and_return(connection)
|
95
|
+
end
|
96
|
+
|
97
|
+
context 'when successful request to API' do
|
98
|
+
let(:success?) { true }
|
99
|
+
|
100
|
+
context 'when response has errors' do
|
101
|
+
let(:errors?) { true }
|
102
|
+
|
103
|
+
it do
|
104
|
+
expect { subject }.to raise_error(ArgumentError)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context 'when response has no errors' do
|
109
|
+
let(:errors?) { false }
|
110
|
+
|
111
|
+
context 'when the response returns test files (successful attempt to read from the cache - the cached test suite split exists on the API side)' do
|
112
|
+
let(:response) do
|
113
|
+
{
|
114
|
+
'test_files' => [
|
115
|
+
{ 'path' => 'a_spec.rb' },
|
116
|
+
{ 'path' => 'b_spec.rb' },
|
117
|
+
]
|
118
|
+
}
|
119
|
+
end
|
120
|
+
|
121
|
+
before do
|
122
|
+
expect(KnapsackPro::Crypto::Decryptor).to receive(:call).with(fast_and_slow_test_files_to_run, response['test_files']).and_call_original
|
123
|
+
end
|
124
|
+
|
125
|
+
it { should eq ['a_spec.rb', 'b_spec.rb'] }
|
126
|
+
end
|
127
|
+
|
128
|
+
context 'when the response has the API code=TEST_SUITE_SPLIT_CACHE_MISS' do
|
129
|
+
let(:response) do
|
130
|
+
{ 'code' => 'TEST_SUITE_SPLIT_CACHE_MISS' }
|
131
|
+
end
|
132
|
+
let(:api_code) { 'TEST_SUITE_SPLIT_CACHE_MISS' }
|
133
|
+
|
134
|
+
before do
|
135
|
+
encrypted_branch = double
|
136
|
+
expect(KnapsackPro::Crypto::BranchEncryptor).to receive(:call).with(repository_adapter.branch).and_return(encrypted_branch)
|
137
|
+
|
138
|
+
encrypted_test_files = double
|
139
|
+
expect(KnapsackPro::Crypto::Encryptor).to receive(:call).with(fast_and_slow_test_files_to_run).and_return(encrypted_test_files)
|
140
|
+
|
141
|
+
# 2nd request is not an attempt to read from the cache.
|
142
|
+
# Try to initalize a new test suite split by sending a list of test files from the disk.
|
143
|
+
action = double
|
144
|
+
expect(KnapsackPro::Client::API::V1::BuildDistributions).to receive(:subset).with({
|
145
|
+
cache_read_attempt: false,
|
146
|
+
commit_hash: repository_adapter.commit_hash,
|
147
|
+
branch: encrypted_branch,
|
148
|
+
node_total: ci_node_total,
|
149
|
+
node_index: ci_node_index,
|
150
|
+
test_files: encrypted_test_files,
|
151
|
+
}).and_return(action)
|
152
|
+
|
153
|
+
connection = instance_double(KnapsackPro::Client::Connection,
|
154
|
+
call: response2,
|
155
|
+
success?: response2_success?,
|
156
|
+
errors?: response2_errors?,
|
157
|
+
api_code: nil)
|
158
|
+
expect(KnapsackPro::Client::Connection).to receive(:new).with(action).and_return(connection)
|
159
|
+
end
|
160
|
+
|
161
|
+
context 'when successful 2nd request to API' do
|
162
|
+
let(:response2_success?) { true }
|
163
|
+
|
164
|
+
context 'when 2nd response has errors' do
|
165
|
+
let(:response2_errors?) { true }
|
166
|
+
let(:response2) { nil }
|
167
|
+
|
168
|
+
it do
|
169
|
+
expect { subject }.to raise_error(ArgumentError)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
context 'when 2nd response has no errors' do
|
174
|
+
let(:response2_errors?) { false }
|
175
|
+
|
176
|
+
context 'when 2nd response returns test files' do
|
177
|
+
let(:response2) do
|
178
|
+
{
|
179
|
+
'test_files' => [
|
180
|
+
{ 'path' => 'a_spec.rb' },
|
181
|
+
{ 'path' => 'b_spec.rb' },
|
182
|
+
]
|
183
|
+
}
|
184
|
+
end
|
185
|
+
|
186
|
+
before do
|
187
|
+
expect(KnapsackPro::Crypto::Decryptor).to receive(:call).with(fast_and_slow_test_files_to_run, response2['test_files']).and_call_original
|
188
|
+
end
|
189
|
+
|
190
|
+
it { should eq ['a_spec.rb', 'b_spec.rb'] }
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
context 'when not successful 2nd request to API' do
|
196
|
+
let(:response2_success?) { false }
|
197
|
+
let(:response2_errors?) { false }
|
198
|
+
let(:response2) { nil }
|
199
|
+
|
200
|
+
it_behaves_like 'when connection to API failed (fallback mode)'
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
context 'when not successful request to API' do
|
207
|
+
let(:success?) { false }
|
208
|
+
let(:errors?) { false }
|
209
|
+
|
210
|
+
it_behaves_like 'when connection to API failed (fallback mode)'
|
211
|
+
end
|
129
212
|
end
|
130
213
|
end
|
@@ -5,10 +5,12 @@ describe KnapsackPro::Client::API::V1::BuildDistributions do
|
|
5
5
|
let(:branch) { double }
|
6
6
|
let(:node_total) { double }
|
7
7
|
let(:node_index) { double }
|
8
|
+
let(:ci_build_id) { double }
|
8
9
|
let(:test_files) { double }
|
9
10
|
|
10
11
|
subject do
|
11
12
|
described_class.subset(
|
13
|
+
cache_read_attempt: cache_read_attempt,
|
12
14
|
commit_hash: commit_hash,
|
13
15
|
branch: branch,
|
14
16
|
node_total: node_total,
|
@@ -19,23 +21,52 @@ describe KnapsackPro::Client::API::V1::BuildDistributions do
|
|
19
21
|
|
20
22
|
before do
|
21
23
|
expect(KnapsackPro::Config::Env).to receive(:fixed_test_suite_split).and_return(fixed_test_suite_split)
|
24
|
+
expect(KnapsackPro::Config::Env).to receive(:ci_node_build_id).and_return(ci_build_id)
|
22
25
|
end
|
23
26
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
27
|
+
context 'when cache_read_attempt=true' do
|
28
|
+
let(:cache_read_attempt) { true }
|
29
|
+
|
30
|
+
it 'does not send test_files among other params' do
|
31
|
+
action = double
|
32
|
+
expect(KnapsackPro::Client::API::Action).to receive(:new).with({
|
33
|
+
endpoint_path: '/v1/build_distributions/subset',
|
34
|
+
http_method: :post,
|
35
|
+
request_hash: {
|
36
|
+
fixed_test_suite_split: fixed_test_suite_split,
|
37
|
+
cache_read_attempt: cache_read_attempt,
|
38
|
+
commit_hash: commit_hash,
|
39
|
+
branch: branch,
|
40
|
+
node_total: node_total,
|
41
|
+
node_index: node_index,
|
42
|
+
ci_build_id: ci_build_id,
|
43
|
+
}
|
44
|
+
}).and_return(action)
|
45
|
+
expect(subject).to eq action
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'when cache_read_attempt=false' do
|
50
|
+
let(:cache_read_attempt) { false }
|
51
|
+
|
52
|
+
it 'sends test_files among other params' do
|
53
|
+
action = double
|
54
|
+
expect(KnapsackPro::Client::API::Action).to receive(:new).with({
|
55
|
+
endpoint_path: '/v1/build_distributions/subset',
|
56
|
+
http_method: :post,
|
57
|
+
request_hash: {
|
58
|
+
fixed_test_suite_split: fixed_test_suite_split,
|
59
|
+
cache_read_attempt: cache_read_attempt,
|
60
|
+
commit_hash: commit_hash,
|
61
|
+
branch: branch,
|
62
|
+
node_total: node_total,
|
63
|
+
node_index: node_index,
|
64
|
+
ci_build_id: ci_build_id,
|
65
|
+
test_files: test_files
|
66
|
+
}
|
67
|
+
}).and_return(action)
|
68
|
+
expect(subject).to eq action
|
69
|
+
end
|
39
70
|
end
|
40
71
|
end
|
41
72
|
|
@@ -147,10 +147,7 @@ describe KnapsackPro::QueueAllocator do
|
|
147
147
|
it { should eq ['a_spec.rb', 'b_spec.rb'] }
|
148
148
|
end
|
149
149
|
|
150
|
-
context 'when response has code=ATTEMPT_CONNECT_TO_QUEUE_FAILED' do
|
151
|
-
let(:response) do
|
152
|
-
{ 'code' => 'ATTEMPT_CONNECT_TO_QUEUE_FAILED' }
|
153
|
-
end
|
150
|
+
context 'when the response has the API code=ATTEMPT_CONNECT_TO_QUEUE_FAILED' do
|
154
151
|
let(:api_code) { 'ATTEMPT_CONNECT_TO_QUEUE_FAILED' }
|
155
152
|
|
156
153
|
before do
|
@@ -197,7 +194,7 @@ describe KnapsackPro::QueueAllocator do
|
|
197
194
|
context 'when 2nd response has no errors' do
|
198
195
|
let(:response2_errors?) { false }
|
199
196
|
|
200
|
-
context 'when 2nd response returns test files (
|
197
|
+
context 'when 2nd response returns test files (successfully initialized a new queue or connected to an existing queue on the API side)' do
|
201
198
|
let(:response2) do
|
202
199
|
{
|
203
200
|
'test_files' => [
|
@@ -19,9 +19,7 @@ describe KnapsackPro::Tracker do
|
|
19
19
|
subject { tracker.current_test_path }
|
20
20
|
|
21
21
|
context 'when current_test_path not set' do
|
22
|
-
it
|
23
|
-
expect { subject }.to raise_error("current_test_path needs to be set by Knapsack Pro Adapter's bind method")
|
24
|
-
end
|
22
|
+
it { should eql nil }
|
25
23
|
end
|
26
24
|
|
27
25
|
context 'when current_test_path set' do
|
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: 3.
|
4
|
+
version: 3.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ArturT
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-12-
|
11
|
+
date: 2022-12-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -390,7 +390,7 @@ metadata:
|
|
390
390
|
documentation_uri: https://docs.knapsackpro.com/integration/
|
391
391
|
homepage_uri: https://knapsackpro.com
|
392
392
|
source_code_uri: https://github.com/KnapsackPro/knapsack_pro-ruby
|
393
|
-
post_install_message:
|
393
|
+
post_install_message:
|
394
394
|
rdoc_options: []
|
395
395
|
require_paths:
|
396
396
|
- lib
|
@@ -405,8 +405,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
405
405
|
- !ruby/object:Gem::Version
|
406
406
|
version: '0'
|
407
407
|
requirements: []
|
408
|
-
rubygems_version: 3.
|
409
|
-
signing_key:
|
408
|
+
rubygems_version: 3.1.6
|
409
|
+
signing_key:
|
410
410
|
specification_version: 4
|
411
411
|
summary: Knapsack Pro splits tests across parallel CI nodes and ensures each parallel
|
412
412
|
job finish work at a similar time.
|