knapsack_pro 3.4.2 → 3.6.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2b7ff9f0b6a3c331eb6c09ea0e04678152db2bae4248e47181bcffe6c88ee194
4
- data.tar.gz: 4ae766dc15f410d4c82baf223c5ca9abfce4a84c031a37693649e1b58e98b13a
3
+ metadata.gz: ba65a6353675fce4c06920c5dca6b7dcc90aee4a978db714f28bf9305f5208e3
4
+ data.tar.gz: 345aa8cf66464faeeb05cc3adcd2fcf904862aa02ea3f6a0109ca83f37c7c332
5
5
  SHA512:
6
- metadata.gz: 63ee85c13851d6d87b8d73c189eae9b477ccfb231b9119e1efbc1921142a31b7c82b85a425223cf8f60927b2de8a0b58e72ae77395844f78b6bc2711b0cfe13d
7
- data.tar.gz: 1b782f2383e2b583cb718e67b2a65feb0ee568378d09411aae80ac55a51e3fe243017ce179c6f3c6199e9fe7bf683dec0dd72465fa41a1f1b250bf50d231371d
6
+ metadata.gz: c12d293d3ac2ca00f33e5802f4c6cf0c8f9ef08dd76d5217892efcb14a8bc090b6f5a118514c79a7066baf8449c3b2406e7b6d4a867b4b479a9bda841d057dbf
7
+ data.tar.gz: 757a63fd917a7fc685659fe6d64d01b19800fa3cc81b4f66d7e9fd08ed9631b28c727544577bae13faae3e54c3b1b3fb3624b2d69e6b74287887c3cb1fb95c44
data/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Change Log
2
2
 
3
+ ### 3.6.0
4
+
5
+ * Add an attempt to read from the cache for Regular Mode API
6
+
7
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/182
8
+
9
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v3.5.0...v3.6.0
10
+
11
+ ### 3.5.0
12
+
13
+ * Add the `KnapsackPro::Hooks::Queue.before_subset_queue` hook in Queue Mode
14
+
15
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/183
16
+
17
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v3.4.2...v3.5.0
18
+
3
19
  ### 3.4.2
4
20
 
5
21
  * Fix: Load `rspec/core` in Regular Mode when using RSpec split by test examples feature
@@ -9,8 +9,18 @@ module KnapsackPro
9
9
  end
10
10
 
11
11
  def test_file_paths
12
- connection = KnapsackPro::Client::Connection.new(build_action)
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: encrypted_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
 
@@ -3,6 +3,7 @@ module KnapsackPro
3
3
  class Queue
4
4
  class << self
5
5
  attr_reader :before_queue_store,
6
+ :before_subset_queue_store,
6
7
  :after_subset_queue_store,
7
8
  :after_queue_store
8
9
 
@@ -10,6 +11,10 @@ module KnapsackPro
10
11
  @before_queue_store = nil
11
12
  end
12
13
 
14
+ def reset_before_subset_queue
15
+ @before_subset_queue_store = nil
16
+ end
17
+
13
18
  def reset_after_subset_queue
14
19
  @after_subset_queue_store = nil
15
20
  end
@@ -23,6 +28,11 @@ module KnapsackPro
23
28
  @before_queue_store << block
24
29
  end
25
30
 
31
+ def before_subset_queue(&block)
32
+ @before_subset_queue_store ||= []
33
+ @before_subset_queue_store << block
34
+ end
35
+
26
36
  def after_subset_queue(&block)
27
37
  @after_subset_queue_store ||= []
28
38
  @after_subset_queue_store << block
@@ -42,6 +52,16 @@ module KnapsackPro
42
52
  end
43
53
  end
44
54
 
55
+ def call_before_subset_queue
56
+ return unless before_subset_queue_store
57
+ before_subset_queue_store.each do |block|
58
+ block.call(
59
+ KnapsackPro::Config::Env.queue_id,
60
+ KnapsackPro::Config::Env.subset_queue_id
61
+ )
62
+ end
63
+ end
64
+
45
65
  def call_after_subset_queue
46
66
  return unless after_subset_queue_store
47
67
  after_subset_queue_store.each do |block|
@@ -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
@@ -60,6 +60,8 @@ module KnapsackPro
60
60
  KnapsackPro.tracker.reset!
61
61
  KnapsackPro.tracker.set_prerun_tests(test_file_paths)
62
62
 
63
+ KnapsackPro::Hooks::Queue.call_before_subset_queue
64
+
63
65
  all_test_file_paths += test_file_paths
64
66
 
65
67
  result_exitstatus = cucumber_run(runner, test_file_paths, args)
@@ -67,6 +67,8 @@ module KnapsackPro
67
67
  KnapsackPro.tracker.reset!
68
68
  KnapsackPro.tracker.set_prerun_tests(test_file_paths)
69
69
 
70
+ KnapsackPro::Hooks::Queue.call_before_subset_queue
71
+
70
72
  all_test_file_paths += test_file_paths
71
73
 
72
74
  result = minitest_run(runner, test_file_paths, args)
@@ -82,6 +82,8 @@ module KnapsackPro
82
82
  KnapsackPro.tracker.reset!
83
83
  KnapsackPro.tracker.set_prerun_tests(test_file_paths)
84
84
 
85
+ KnapsackPro::Hooks::Queue.call_before_subset_queue
86
+
85
87
  all_test_file_paths += test_file_paths
86
88
  cli_args = args + test_file_paths
87
89
 
@@ -1,3 +1,3 @@
1
1
  module KnapsackPro
2
- VERSION = '3.4.2'
2
+ VERSION = '3.6.0'
3
3
  end
@@ -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","test_files":[{"path":"a_spec.rb"},{"path":"b_spec.rb"}],"test_suite_token":"fake"}'
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: 'Forbidden '
27
+ message: Forbidden
22
28
  headers:
23
29
  X-Frame-Options:
24
30
  - SAMEORIGIN
25
31
  X-Xss-Protection:
26
- - 1; mode=block
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
- - 6d40fe71-7fad-449a-812f-9773429777ce
46
+ - a5ffe97f-4558-426b-9475-166eb89ab7cb
35
47
  X-Runtime:
36
- - '0.054890'
37
- Server:
38
- - WEBrick/1.3.1 (Ruby/2.2.2/2015-04-13)
39
- Date:
40
- - Fri, 31 Jul 2015 16:09:00 GMT
41
- Content-Length:
42
- - '39'
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
- http_version:
49
- recorded_at: Fri, 31 Jul 2015 16:09:00 GMT
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","test_files":[{"path":"a_spec.rb"},{"path":"b_spec.rb"}],"test_suite_token":"3fa64859337f6e56409d49f865d13fd7"}'
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: 'OK '
27
+ message: OK
22
28
  headers:
23
29
  X-Frame-Options:
24
30
  - SAMEORIGIN
25
31
  X-Xss-Protection:
26
- - 1; mode=block
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/"bba747f5e635a765e120718b7876d174"
44
+ - W/"1f643e3528e8ff45d9d2d67ab7e32be1"
33
45
  Cache-Control:
34
46
  - max-age=0, private, must-revalidate
35
47
  X-Request-Id:
36
- - 190e26fb-676b-4b85-9737-8a90d0cce310
48
+ - 9b378323-c960-4868-894e-5ae0cdab8840
37
49
  X-Runtime:
38
- - '0.639590'
39
- Server:
40
- - WEBrick/1.3.1 (Ruby/2.2.3/2015-08-18)
41
- Date:
42
- - Tue, 28 Jun 2016 20:40:35 GMT
43
- Content-Length:
44
- - '137'
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: '{"build_distribution_id":"1f905f45-c203-40f1-9891-d9a91dd11245","node_index":1,"test_files":[{"path":"b_spec.rb","time_execution":null}]}'
50
- http_version:
51
- recorded_at: Tue, 28 Jun 2016 20:40:35 GMT
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
@@ -6,6 +6,7 @@ describe 'Request API /v1/build_distributions/subset' do
6
6
 
7
7
  let(:action) do
8
8
  KnapsackPro::Client::API::V1::BuildDistributions.subset(
9
+ cache_read_attempt: true,
9
10
  commit_hash: 'abcdefg',
10
11
  branch: 'master',
11
12
  node_total: '2',
@@ -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
- before do
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
- it do
25
- action = double
26
- expect(KnapsackPro::Client::API::Action).to receive(:new).with({
27
- endpoint_path: '/v1/build_distributions/subset',
28
- http_method: :post,
29
- request_hash: {
30
- fixed_test_suite_split: fixed_test_suite_split,
31
- commit_hash: commit_hash,
32
- branch: branch,
33
- node_total: node_total,
34
- node_index: node_index,
35
- test_files: test_files
36
- }
37
- }).and_return(action)
38
- expect(subject).to eq action
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
 
@@ -37,6 +37,46 @@ describe KnapsackPro::Hooks::Queue do
37
37
  end
38
38
  end
39
39
 
40
+ describe '.call_before_subset_queue' do
41
+ subject { described_class.call_before_subset_queue }
42
+
43
+ context 'when callback is not set' do
44
+ before do
45
+ described_class.reset_before_subset_queue
46
+ end
47
+
48
+ it { should be_nil }
49
+ end
50
+
51
+ context 'when callback is set multiple times' do
52
+ let(:queue_id) { double }
53
+ let(:subset_queue_id) { double }
54
+
55
+ before do
56
+ expect(KnapsackPro::Config::Env).to receive(:queue_id).twice.and_return(queue_id)
57
+ expect(KnapsackPro::Config::Env).to receive(:subset_queue_id).twice.and_return(subset_queue_id)
58
+
59
+ $expected_called_blocks = []
60
+
61
+ described_class.before_subset_queue do |q_id, subset_q_id|
62
+ $expected_called_blocks << [:block_1_called, q_id, subset_q_id]
63
+ end
64
+ described_class.before_subset_queue do |q_id, subset_q_id|
65
+ $expected_called_blocks << [:block_2_called, q_id, subset_q_id]
66
+ end
67
+ end
68
+
69
+ it 'each block is called' do
70
+ subject
71
+
72
+ expect($expected_called_blocks).to eq([
73
+ [:block_1_called, queue_id, subset_queue_id],
74
+ [:block_2_called, queue_id, subset_queue_id],
75
+ ])
76
+ end
77
+ end
78
+ end
79
+
40
80
  describe '.call_after_subset_queue' do
41
81
  subject { described_class.call_after_subset_queue }
42
82
 
@@ -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 (successful attempt to connect to queue already existing on the API side)' do
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' => [
@@ -115,6 +115,8 @@ describe KnapsackPro::Runners::Queue::CucumberRunner do
115
115
  expect(tracker).to receive(:reset!)
116
116
  expect(tracker).to receive(:set_prerun_tests).with(test_file_paths)
117
117
 
118
+ expect(KnapsackPro::Hooks::Queue).to receive(:call_before_subset_queue)
119
+
118
120
  # .cucumber_run
119
121
  expect(Kernel).to receive(:system).with('bundle exec cucumber --retry 5 --no-strict-flaky --require fake-features-dir -- "features/a.feature" "features/b.feature"')
120
122
 
@@ -125,6 +125,7 @@ describe KnapsackPro::Runners::Queue::MinitestRunner do
125
125
 
126
126
  expect(Minitest::Runnable).to receive(:reset)
127
127
 
128
+ expect(KnapsackPro::Hooks::Queue).to receive(:call_before_subset_queue)
128
129
 
129
130
  expect(KnapsackPro::Hooks::Queue).to receive(:call_after_subset_queue)
130
131
 
@@ -225,6 +225,8 @@ describe KnapsackPro::Runners::Queue::RSpecRunner do
225
225
 
226
226
  expect(described_class).to receive(:rspec_clear_examples)
227
227
 
228
+ expect(KnapsackPro::Hooks::Queue).to receive(:call_before_subset_queue)
229
+
228
230
  expect(KnapsackPro::Hooks::Queue).to receive(:call_after_subset_queue)
229
231
 
230
232
  expect(KnapsackPro::Report).to receive(:save_subset_queue_to_file)
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.2
4
+ version: 3.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ArturT
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-11-21 00:00:00.000000000 Z
11
+ date: 2022-12-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake