knapsack_pro 2.9.0 → 2.10.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7985606018ab50713321190176606a281cdfbec98e7c4883569ddcc73fd1acad
4
- data.tar.gz: e1564d27e3a6ab282657d131e0ccd134de831260cf240114cca213b32c804e27
3
+ metadata.gz: ab52ffbbe5618da1d1c70e11493e6dcd474542a8fe19dc11b57c673f3fc5b939
4
+ data.tar.gz: e53495530e21c903b56921a47a6cd27de056f3cc2cbb3f2804df99f0bc6d4542
5
5
  SHA512:
6
- metadata.gz: 658af58fa87cff47e1c61cd48bc37a54574339a5450fe0cc77c8dac0001cdd0fad36ed0537fdb597ab23678c99446fcbf6793f574ee7ad99c12d05ee7be7a25f
7
- data.tar.gz: 6ef3927c8ea007073102969878dea4c00cc3340912d49448803e4b62207e73fd289e6dcfb7a22b22eab4d21f9c72828933bfdccf0d509a2e904fda425e73cdcb
6
+ metadata.gz: 732b7ce526fa01c176e5a958bd6cf71eab989fce6bcf160334157dd1e7b65b37c6b31ecc0ad603b4780df0a925059eaf5f212174d1bff37f89ab86c807d4ac30
7
+ data.tar.gz: baa2ef028990a02e332f0f5e1d985db760f44ae3c1b090128c696dea5f77e2a89659381e7a081a2c67eb1d870cec09b9a16d9b11e0dbe4315622fd7a458889b1
@@ -1,5 +1,13 @@
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
+
3
11
  ### 2.9.0
4
12
 
5
13
  * Use `Process.clock_gettime` to measure track execution time
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.0.0`
53
+ `>= Ruby 2.1.0`
54
54
 
55
55
  # Table of Contents
56
56
 
@@ -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
@@ -1,8 +1,8 @@
1
1
  module KnapsackPro
2
2
  class QueueAllocator
3
3
  def initialize(args)
4
- @fast_and_slow_test_files_to_run = args.fetch(:fast_and_slow_test_files_to_run)
5
- @fallback_mode_test_files = args.fetch(:fallback_mode_test_files)
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 :fast_and_slow_test_files_to_run,
41
- :fallback_mode_test_files,
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(fast_and_slow_test_files_to_run)
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: encrypted_test_files,
85
+ test_files: test_files,
64
86
  )
65
87
  end
66
88
 
67
89
  def prepare_test_files(response)
68
- decrypted_test_files = KnapsackPro::Crypto::Decryptor.call(fast_and_slow_test_files_to_run, response['test_files'])
69
- KnapsackPro::TestFilePresenter.paths(decrypted_test_files)
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(fallback_mode_test_files, ci_node_total)
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
- fast_and_slow_test_files_to_run: fast_and_slow_test_files_to_run,
6
- fallback_mode_test_files: fallback_mode_test_files,
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,
@@ -1,3 +1,3 @@
1
1
  module KnapsackPro
2
- VERSION = '2.9.0'
2
+ VERSION = '2.10.0'
3
3
  end
@@ -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,
@@ -8,11 +8,11 @@ describe KnapsackPro::QueueAllocatorBuilder do
8
8
  subject { allocator_builder.allocator }
9
9
 
10
10
  before do
11
- fast_and_slow_test_files_to_run = double
12
- expect(allocator_builder).to receive(:fast_and_slow_test_files_to_run).and_return(fast_and_slow_test_files_to_run)
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
- fallback_mode_test_files = double
15
- expect(allocator_builder).to receive(:fallback_mode_test_files).and_return(fallback_mode_test_files)
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
- fast_and_slow_test_files_to_run: fast_and_slow_test_files_to_run,
29
- fallback_mode_test_files: fallback_mode_test_files,
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(:fast_and_slow_test_files_to_run) { double }
3
- let(:fallback_mode_test_files) { double }
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
- fast_and_slow_test_files_to_run: fast_and_slow_test_files_to_run,
12
- fallback_mode_test_files: fallback_mode_test_files,
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
- before do
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(fallback_mode_test_files, ci_node_total).and_return(test_flat_distributor)
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
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.9.0
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-21 00:00:00.000000000 Z
11
+ date: 2020-11-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake