knapsack_pro 2.6.0 → 2.10.1

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: b4167b51e7f0af27a7d1482efb7a6c019f9aa99dd849f9488e47c4a33b5bd943
4
- data.tar.gz: fff1d5e557813cd2829298c422d4ffae857e047d27aa001cf746a516270d9259
3
+ metadata.gz: 9b0ef524a80bd3e88c8c12c631880e644734fc8be8253bd4aa8d9c58fcc2dc48
4
+ data.tar.gz: 7fa53878c1cbf1fb421f2637c98db03133654df1abf07d058179b2516a01da49
5
5
  SHA512:
6
- metadata.gz: fd9b442c01b5b58b295e6fc36d3879ddbf97b8770d4f96243f594f225ef3f73e23e75555cfba7adb6439dd5afa39a38ea756e5758628eed54c9305a12bd8b716
7
- data.tar.gz: 7401c76f35ce8485a7dc8dc5742514803c8a045d7f431899b32aaa4795433b723b68e554386b7670abb367b1f9dfde2be9e4bc8b661ead354dbab366b56c1705
6
+ metadata.gz: 6faf1e8b52b3d93c424945e560dba8caeda53a208b002c370b2e050f31aafbffd66856e06e7475043891923ef5315f40a3f6ee9e58fad243eb91fc12bde47ad7
7
+ data.tar.gz: c4767bf21996e966db844779e177b10086626b6a8bfd7ffd67333842aa2376814234b54a00a945b70a676d481c70bea07ae74480c3f2359e5ab7588490194eca
@@ -1,5 +1,45 @@
1
1
  # Change Log
2
2
 
3
+ ### 2.10.1
4
+
5
+ * Fix RSpec split by test examples feature broken by lazy generating of JSON report with test example ids
6
+
7
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/135
8
+
9
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v2.10.0...v2.10.1
10
+
11
+ ### 2.10.0
12
+
13
+ * Add support for an attempt to connect to existing Queue on API side to reduce slow requests number
14
+
15
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/133
16
+
17
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v2.9.0...v2.10.0
18
+
19
+ ### 2.9.0
20
+
21
+ * Use `Process.clock_gettime` to measure track execution time
22
+
23
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/132
24
+
25
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v2.8.0...v2.9.0
26
+
27
+ ### 2.8.0
28
+
29
+ * More actionable error message when RSpec split by examples is not working due to RSpec dry-run failure
30
+
31
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/130
32
+
33
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v2.7.0...v2.8.0
34
+
35
+ ### 2.7.0
36
+
37
+ * Add support for env var `KNAPSACK_PRO_TEST_FILE_LIST_SOURCE_FILE` to allow accepting file containing test files to run
38
+
39
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/129
40
+
41
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v2.6.0...v2.7.0
42
+
3
43
  ### 2.6.0
4
44
 
5
45
  * Improve logger to show failed requests URL and when retry will happen
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
 
@@ -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
- Note when you set `KNAPSACK_PRO_TEST_FILE_LIST` then below environment variables are ignored:
3095
+ **Option 2:**
3096
+
3097
+ Similarly, you can also provide a source file containing the test files that you would like to run. For example:
3098
+ `KNAPSACK_PRO_TEST_FILE_LIST_SOURCE_FILE=spec/fixtures/test_file_list_source_file.txt`
3099
+ And the content of the source file can be any of the format below:
3100
+
3101
+ ```
3102
+ ./spec/test1_spec.rb
3103
+ spec/test2_spec.rb[1]
3104
+ ./spec/test3_spec.rb[1:2:3:4]
3105
+ ./spec/test4_spec.rb:4
3106
+ ./spec/test4_spec.rb:5
3107
+ ```
3108
+
3109
+ > Note that each of the line must be ending with `\n` the new line.
3110
+
3111
+ Note when you set `KNAPSACK_PRO_TEST_FILE_LIST` or `KNAPSACK_PRO_TEST_FILE_LIST_SOURCE_FILE` then below environment variables are ignored:
3112
+
3094
3113
  * `KNAPSACK_PRO_TEST_FILE_PATTERN`
3095
3114
  * `KNAPSACK_PRO_TEST_FILE_EXCLUDE_PATTERN`
3096
3115
 
@@ -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
@@ -74,6 +74,10 @@ module KnapsackPro
74
74
  ENV['KNAPSACK_PRO_TEST_FILE_LIST']
75
75
  end
76
76
 
77
+ def test_file_list_source_file
78
+ ENV['KNAPSACK_PRO_TEST_FILE_LIST_SOURCE_FILE']
79
+ end
80
+
77
81
  def test_dir
78
82
  ENV['KNAPSACK_PRO_TEST_DIR']
79
83
  end
@@ -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)
@@ -52,15 +61,22 @@ module KnapsackPro
52
61
  KnapsackPro::Crypto::BranchEncryptor.call(repository_adapter.branch)
53
62
  end
54
63
 
55
- def build_action(can_initialize_queue)
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
+ test_files =
67
+ if can_initialize_queue && !attempt_connect_to_queue
68
+ encrypted_test_files
69
+ end
70
+
56
71
  KnapsackPro::Client::API::V1::Queues.queue(
57
72
  can_initialize_queue: can_initialize_queue,
73
+ attempt_connect_to_queue: attempt_connect_to_queue,
58
74
  commit_hash: repository_adapter.commit_hash,
59
75
  branch: encrypted_branch,
60
76
  node_total: ci_node_total,
61
77
  node_index: ci_node_index,
62
78
  node_build_id: ci_node_build_id,
63
- test_files: encrypted_test_files,
79
+ test_files: test_files,
64
80
  )
65
81
  end
66
82
 
@@ -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
- raise 'There was problem to generate test examples for test suite'
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 =
@@ -90,11 +90,7 @@ module KnapsackPro
90
90
  end
91
91
 
92
92
  def now_without_mock_time
93
- if defined?(Timecop)
94
- Time.now_without_mock_time
95
- else
96
- Time.raw_now
97
- end
93
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
98
94
  end
99
95
  end
100
96
  end
@@ -1,3 +1,3 @@
1
1
  module KnapsackPro
2
- VERSION = '2.6.0'
2
+ VERSION = '2.10.1'
3
3
  end
@@ -0,0 +1,6 @@
1
+ ./spec/test1_spec.rb
2
+ spec/test2_spec.rb[1]
3
+ ./spec/test3_spec.rb[1:2:3:4]
4
+ ./spec/test4_spec.rb:4
5
+ ./spec/test4_spec.rb:5
6
+
@@ -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,
@@ -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
 
@@ -18,71 +18,13 @@ describe KnapsackPro::QueueAllocator do
18
18
  end
19
19
 
20
20
  describe '#test_file_paths' do
21
- let(:can_initialize_queue) { double }
22
21
  let(:executed_test_files) { [] }
23
22
  let(:response) { double }
23
+ let(:api_code) { nil }
24
24
 
25
25
  subject { queue_allocator.test_file_paths(can_initialize_queue, executed_test_files) }
26
26
 
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
-
27
+ shared_examples_for 'when connection to API failed (fallback mode)' do
86
28
  context 'when fallback mode is disabled' do
87
29
  before do
88
30
  expect(KnapsackPro::Config::Env).to receive(:fallback_mode_enabled?).and_return(false)
@@ -146,5 +88,220 @@ describe KnapsackPro::QueueAllocator do
146
88
  end
147
89
  end
148
90
  end
91
+
92
+ context 'when can_initialize_queue=true' do
93
+ let(:can_initialize_queue) { true }
94
+
95
+ before do
96
+ encrypted_branch = double
97
+ expect(KnapsackPro::Crypto::BranchEncryptor).to receive(:call).with(repository_adapter.branch).and_return(encrypted_branch)
98
+
99
+ action = double
100
+ expect(KnapsackPro::Client::API::V1::Queues).to receive(:queue).with(
101
+ can_initialize_queue: can_initialize_queue,
102
+ attempt_connect_to_queue: true, # when can_initialize_queue=true then expect attempt_connect_to_queue=true
103
+ commit_hash: repository_adapter.commit_hash,
104
+ branch: encrypted_branch,
105
+ node_total: ci_node_total,
106
+ node_index: ci_node_index,
107
+ node_build_id: ci_node_build_id,
108
+ test_files: nil, # when attempt_connect_to_queue=true then expect test_files is nil to make fast request to API
109
+ ).and_return(action)
110
+
111
+ connection = instance_double(KnapsackPro::Client::Connection,
112
+ call: response,
113
+ success?: success?,
114
+ errors?: errors?,
115
+ api_code: api_code)
116
+ expect(KnapsackPro::Client::Connection).to receive(:new).with(action).and_return(connection)
117
+ end
118
+
119
+ context 'when successful request to API' do
120
+ let(:success?) { true }
121
+
122
+ context 'when response has errors' do
123
+ let(:errors?) { true }
124
+
125
+ it do
126
+ expect { subject }.to raise_error(ArgumentError)
127
+ end
128
+ end
129
+
130
+ context 'when response has no errors' do
131
+ let(:errors?) { false }
132
+
133
+ context 'when response returns test files (successful attempt to connect to queue already existing on the API side)' do
134
+ let(:response) do
135
+ {
136
+ 'test_files' => [
137
+ { 'path' => 'a_spec.rb' },
138
+ { 'path' => 'b_spec.rb' },
139
+ ]
140
+ }
141
+ end
142
+
143
+ before do
144
+ expect(KnapsackPro::Crypto::Decryptor).to receive(:call).with(fast_and_slow_test_files_to_run, response['test_files']).and_call_original
145
+ end
146
+
147
+ it { should eq ['a_spec.rb', 'b_spec.rb'] }
148
+ end
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
154
+ let(:api_code) { 'ATTEMPT_CONNECT_TO_QUEUE_FAILED' }
155
+
156
+ before do
157
+ encrypted_branch = double
158
+ expect(KnapsackPro::Crypto::BranchEncryptor).to receive(:call).with(repository_adapter.branch).and_return(encrypted_branch)
159
+
160
+ encrypted_test_files = double
161
+ expect(KnapsackPro::Crypto::Encryptor).to receive(:call).with(fast_and_slow_test_files_to_run).and_return(encrypted_test_files)
162
+
163
+ # 2nd request is no more an attempt to connect to queue.
164
+ # We want to try to initalize a new queue so we will also send list of test files from disk.
165
+ action = double
166
+ expect(KnapsackPro::Client::API::V1::Queues).to receive(:queue).with(
167
+ can_initialize_queue: can_initialize_queue,
168
+ attempt_connect_to_queue: false,
169
+ commit_hash: repository_adapter.commit_hash,
170
+ branch: encrypted_branch,
171
+ node_total: ci_node_total,
172
+ node_index: ci_node_index,
173
+ node_build_id: ci_node_build_id,
174
+ test_files: encrypted_test_files,
175
+ ).and_return(action)
176
+
177
+ connection = instance_double(KnapsackPro::Client::Connection,
178
+ call: response2,
179
+ success?: response2_success?,
180
+ errors?: response2_errors?,
181
+ api_code: nil)
182
+ expect(KnapsackPro::Client::Connection).to receive(:new).with(action).and_return(connection)
183
+ end
184
+
185
+ context 'when successful 2nd request to API' do
186
+ let(:response2_success?) { true }
187
+
188
+ context 'when 2nd response has errors' do
189
+ let(:response2_errors?) { true }
190
+ let(:response2) { nil }
191
+
192
+ it do
193
+ expect { subject }.to raise_error(ArgumentError)
194
+ end
195
+ end
196
+
197
+ context 'when 2nd response has no errors' do
198
+ let(:response2_errors?) { false }
199
+
200
+ context 'when 2nd response returns test files (successful attempt to connect to queue already existing on the API side)' do
201
+ let(:response2) do
202
+ {
203
+ 'test_files' => [
204
+ { 'path' => 'a_spec.rb' },
205
+ { 'path' => 'b_spec.rb' },
206
+ ]
207
+ }
208
+ end
209
+
210
+ before do
211
+ expect(KnapsackPro::Crypto::Decryptor).to receive(:call).with(fast_and_slow_test_files_to_run, response2['test_files']).and_call_original
212
+ end
213
+
214
+ it { should eq ['a_spec.rb', 'b_spec.rb'] }
215
+ end
216
+ end
217
+ end
218
+
219
+ context 'when not successful 2nd request to API' do
220
+ let(:response2_success?) { false }
221
+ let(:response2_errors?) { false }
222
+ let(:response2) { nil }
223
+
224
+ it_behaves_like 'when connection to API failed (fallback mode)'
225
+ end
226
+ end
227
+ end
228
+ end
229
+
230
+ context 'when not successful request to API' do
231
+ let(:success?) { false }
232
+ let(:errors?) { false }
233
+
234
+ it_behaves_like 'when connection to API failed (fallback mode)'
235
+ end
236
+ end
237
+
238
+ context 'when can_initialize_queue=false' do
239
+ let(:can_initialize_queue) { false }
240
+ let(:api_code) { nil }
241
+
242
+ before do
243
+ encrypted_branch = double
244
+ expect(KnapsackPro::Crypto::BranchEncryptor).to receive(:call).with(repository_adapter.branch).and_return(encrypted_branch)
245
+
246
+ action = double
247
+ expect(KnapsackPro::Client::API::V1::Queues).to receive(:queue).with(
248
+ can_initialize_queue: can_initialize_queue,
249
+ attempt_connect_to_queue: false, # when can_initialize_queue=false then expect attempt_connect_to_queue=false
250
+ commit_hash: repository_adapter.commit_hash,
251
+ branch: encrypted_branch,
252
+ node_total: ci_node_total,
253
+ node_index: ci_node_index,
254
+ node_build_id: ci_node_build_id,
255
+ test_files: nil, # when can_initialize_queue=false then expect test_files is nil to make fast request to API
256
+ ).and_return(action)
257
+
258
+ connection = instance_double(KnapsackPro::Client::Connection,
259
+ call: response,
260
+ success?: success?,
261
+ errors?: errors?,
262
+ api_code: api_code)
263
+ expect(KnapsackPro::Client::Connection).to receive(:new).with(action).and_return(connection)
264
+ end
265
+
266
+ context 'when successful request to API' do
267
+ let(:success?) { true }
268
+
269
+ context 'when response has errors' do
270
+ let(:errors?) { true }
271
+
272
+ it do
273
+ expect { subject }.to raise_error(ArgumentError)
274
+ end
275
+ end
276
+
277
+ context 'when response has no errors' do
278
+ let(:errors?) { false }
279
+
280
+ context 'when response returns test files (successful attempt to connect to queue already existing on the API side)' do
281
+ let(:response) do
282
+ {
283
+ 'test_files' => [
284
+ { 'path' => 'a_spec.rb' },
285
+ { 'path' => 'b_spec.rb' },
286
+ ]
287
+ }
288
+ end
289
+
290
+ before do
291
+ expect(KnapsackPro::Crypto::Decryptor).to receive(:call).with(fast_and_slow_test_files_to_run, response['test_files']).and_call_original
292
+ end
293
+
294
+ it { should eq ['a_spec.rb', 'b_spec.rb'] }
295
+ end
296
+ end
297
+ end
298
+
299
+ context 'when not successful request to API' do
300
+ let(:success?) { false }
301
+ let(:errors?) { false }
302
+
303
+ it_behaves_like 'when connection to API failed (fallback mode)'
304
+ end
305
+ end
149
306
  end
150
307
  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 to generate test examples for test suite')
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.6.0
4
+ version: 2.10.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - ArturT
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-09-23 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
@@ -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