knapsack_pro 5.3.2 → 5.3.4
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/repository_adapters/git_adapter.rb +14 -2
- data/lib/knapsack_pro/runners/queue/base_runner.rb +22 -0
- data/lib/knapsack_pro/runners/queue/cucumber_runner.rb +1 -0
- data/lib/knapsack_pro/runners/queue/minitest_runner.rb +1 -0
- data/lib/knapsack_pro/runners/queue/rspec_runner.rb +10 -0
- data/lib/knapsack_pro/version.rb +1 -1
- data/lib/knapsack_pro.rb +1 -0
- data/lib/tasks/queue/cucumber.rake +7 -1
- data/lib/tasks/queue/minitest.rake +7 -1
- data/lib/tasks/queue/rspec.rake +7 -1
- data/spec/knapsack_pro/runners/queue/cucumber_runner_spec.rb +2 -0
- data/spec/knapsack_pro/runners/queue/minitest_runner_spec.rb +2 -0
- data/spec/knapsack_pro/runners/queue/rspec_runner_spec.rb +66 -4
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6952ceb372cbcc2dc8c2c5514f0fe68bc4be51572199168e3d7f7992eabdfe43
|
4
|
+
data.tar.gz: '077863b80cab5c090ad84c62cbb0c2d680757ea19da59e94c92cb9ee2770ba90'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3ba6a868b796019d571c077131e1cd33016bee27e7a8cbd1b1d35cfe31532c2049734d1cf24686ac5ef63a881a82ed0c3d811d4e04ccf17ba0444a856121e363
|
7
|
+
data.tar.gz: a717af5c831cfd8984ac2c2d691b557dd7cd919e1e7a223d9347eac8d28345700bdcefdf50d0fc5ab10a23c2c9dd4811e95198c443530d83006e7baeee898dbb
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,21 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
### 5.3.4
|
4
|
+
|
5
|
+
* fix(Queue Mode): handle OS signals and RSpec internal `wants_to_quit` and `rspec_is_quitting` states to stop consuming tests from the Queue API when the CI node is terminated
|
6
|
+
|
7
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/pull/207
|
8
|
+
|
9
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v5.3.3...v5.3.4
|
10
|
+
|
11
|
+
### 5.3.3
|
12
|
+
|
13
|
+
* Fix hanging CI when `git fetch --shallow-since` takes too long
|
14
|
+
|
15
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/pull/213
|
16
|
+
|
17
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v5.3.2...v5.3.3
|
18
|
+
|
3
19
|
### 5.3.2
|
4
20
|
|
5
21
|
* On top of 5.3.1, avoid noise to stderr when git is not available when collecting the build author
|
@@ -41,8 +41,15 @@ module KnapsackPro
|
|
41
41
|
private
|
42
42
|
|
43
43
|
def git_commit_authors
|
44
|
-
if KnapsackPro::Config::Env.ci?
|
45
|
-
|
44
|
+
if KnapsackPro::Config::Env.ci? && shallow_repository?
|
45
|
+
command = 'git fetch --shallow-since "one month ago" --quiet 2>/dev/null'
|
46
|
+
begin
|
47
|
+
Timeout.timeout(5) do
|
48
|
+
`#{command}`
|
49
|
+
end
|
50
|
+
rescue Timeout::Error
|
51
|
+
KnapsackPro.logger.debug("Skip the `#{command}` command because it took too long.")
|
52
|
+
end
|
46
53
|
end
|
47
54
|
|
48
55
|
`git log --since "one month ago" 2>/dev/null | git shortlog --summary --email 2>/dev/null`
|
@@ -52,6 +59,11 @@ module KnapsackPro
|
|
52
59
|
`git log --format="%aN <%aE>" -1 2>/dev/null`
|
53
60
|
end
|
54
61
|
|
62
|
+
def shallow_repository?
|
63
|
+
result = `git rev-parse --is-shallow-repository 2>/dev/null`
|
64
|
+
result.strip == 'true'
|
65
|
+
end
|
66
|
+
|
55
67
|
def working_dir
|
56
68
|
dir = KnapsackPro::Config::Env.project_dir
|
57
69
|
File.expand_path(dir)
|
@@ -2,6 +2,10 @@ module KnapsackPro
|
|
2
2
|
module Runners
|
3
3
|
module Queue
|
4
4
|
class BaseRunner
|
5
|
+
TERMINATION_SIGNALS = %w(HUP INT TERM ABRT QUIT USR1 USR2)
|
6
|
+
|
7
|
+
@@terminate_process = false
|
8
|
+
|
5
9
|
def self.run(args)
|
6
10
|
raise NotImplementedError
|
7
11
|
end
|
@@ -13,6 +17,7 @@ module KnapsackPro
|
|
13
17
|
def initialize(adapter_class)
|
14
18
|
@allocator_builder = KnapsackPro::QueueAllocatorBuilder.new(adapter_class)
|
15
19
|
@allocator = allocator_builder.allocator
|
20
|
+
trap_signals
|
16
21
|
end
|
17
22
|
|
18
23
|
def test_file_paths(args)
|
@@ -33,6 +38,23 @@ module KnapsackPro
|
|
33
38
|
def self.child_status
|
34
39
|
$?
|
35
40
|
end
|
41
|
+
|
42
|
+
def self.handle_signal!
|
43
|
+
raise 'Knapsack Pro process was terminated!' if @@terminate_process
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.set_terminate_process
|
47
|
+
@@terminate_process = true
|
48
|
+
end
|
49
|
+
|
50
|
+
def trap_signals
|
51
|
+
TERMINATION_SIGNALS.each do |signal|
|
52
|
+
Signal.trap(signal) {
|
53
|
+
puts "#{signal} signal has been received. Terminating Knapsack Pro..."
|
54
|
+
@@terminate_process = true
|
55
|
+
}
|
56
|
+
end
|
57
|
+
end
|
36
58
|
end
|
37
59
|
end
|
38
60
|
end
|
@@ -37,6 +37,7 @@ module KnapsackPro
|
|
37
37
|
all_test_file_paths: [],
|
38
38
|
}
|
39
39
|
while accumulator[:status] == :next
|
40
|
+
handle_signal!
|
40
41
|
accumulator = run_tests(accumulator)
|
41
42
|
end
|
42
43
|
|
@@ -94,6 +95,15 @@ module KnapsackPro
|
|
94
95
|
exit_code = rspec_runner.run($stderr, $stdout)
|
95
96
|
exitstatus = exit_code if exit_code != 0
|
96
97
|
|
98
|
+
if rspec_runner.world.wants_to_quit
|
99
|
+
KnapsackPro.logger.warn('RSpec wants to quit.')
|
100
|
+
set_terminate_process
|
101
|
+
end
|
102
|
+
if rspec_runner.world.rspec_is_quitting
|
103
|
+
KnapsackPro.logger.warn('RSpec is quitting.')
|
104
|
+
set_terminate_process
|
105
|
+
end
|
106
|
+
|
97
107
|
printable_args = args_with_seed_option_added_when_viable(args, rspec_runner)
|
98
108
|
log_rspec_command(printable_args, test_file_paths, :subset_queue)
|
99
109
|
|
data/lib/knapsack_pro/version.rb
CHANGED
data/lib/knapsack_pro.rb
CHANGED
@@ -4,7 +4,13 @@ namespace :knapsack_pro do
|
|
4
4
|
namespace :queue do
|
5
5
|
task :cucumber, [:cucumber_args] do |_, args|
|
6
6
|
Kernel.system("RAILS_ENV=test RACK_ENV=test #{$PROGRAM_NAME} 'knapsack_pro:queue:cucumber_go[#{args[:cucumber_args]}]'")
|
7
|
-
|
7
|
+
exitstatus = $?.exitstatus
|
8
|
+
if exitstatus.nil?
|
9
|
+
puts 'Something went wrong. Most likely, the process has been killed. Knapsack Pro has been terminated.'
|
10
|
+
Kernel.exit(1)
|
11
|
+
else
|
12
|
+
Kernel.exit(exitstatus)
|
13
|
+
end
|
8
14
|
end
|
9
15
|
|
10
16
|
task :cucumber_go, [:cucumber_args] do |_, args|
|
@@ -4,7 +4,13 @@ namespace :knapsack_pro do
|
|
4
4
|
namespace :queue do
|
5
5
|
task :minitest, [:minitest_args] do |_, args|
|
6
6
|
Kernel.system("RAILS_ENV=test RACK_ENV=test #{$PROGRAM_NAME} 'knapsack_pro:queue:minitest_go[#{args[:minitest_args]}]'")
|
7
|
-
|
7
|
+
exitstatus = $?.exitstatus
|
8
|
+
if exitstatus.nil?
|
9
|
+
puts 'Something went wrong. Most likely, the process has been killed. Knapsack Pro has been terminated.'
|
10
|
+
Kernel.exit(1)
|
11
|
+
else
|
12
|
+
Kernel.exit(exitstatus)
|
13
|
+
end
|
8
14
|
end
|
9
15
|
|
10
16
|
task :minitest_go, [:minitest_args] do |_, args|
|
data/lib/tasks/queue/rspec.rake
CHANGED
@@ -4,7 +4,13 @@ namespace :knapsack_pro do
|
|
4
4
|
namespace :queue do
|
5
5
|
task :rspec, [:rspec_args] do |_, args|
|
6
6
|
Kernel.system("RAILS_ENV=test RACK_ENV=test #{$PROGRAM_NAME} 'knapsack_pro:queue:rspec_go[#{args[:rspec_args]}]'")
|
7
|
-
|
7
|
+
exitstatus = $?.exitstatus
|
8
|
+
if exitstatus.nil?
|
9
|
+
puts 'Something went wrong. Most likely, the process has been killed. Knapsack Pro has been terminated.'
|
10
|
+
Kernel.exit(1)
|
11
|
+
else
|
12
|
+
Kernel.exit(exitstatus)
|
13
|
+
end
|
8
14
|
end
|
9
15
|
|
10
16
|
task :rspec_go, [:rspec_args] do |_, args|
|
@@ -41,6 +41,7 @@ describe KnapsackPro::Runners::Queue::CucumberRunner do
|
|
41
41
|
exitstatus: 0,
|
42
42
|
all_test_file_paths: [],
|
43
43
|
}
|
44
|
+
expect(described_class).to receive(:handle_signal!)
|
44
45
|
expect(described_class).to receive(:run_tests).with(accumulator).and_return(expected_accumulator)
|
45
46
|
|
46
47
|
expect(Kernel).to receive(:exit).with(expected_exitstatus)
|
@@ -66,6 +67,7 @@ describe KnapsackPro::Runners::Queue::CucumberRunner do
|
|
66
67
|
exitstatus: 0,
|
67
68
|
all_test_file_paths: [],
|
68
69
|
}
|
70
|
+
expect(described_class).to receive(:handle_signal!)
|
69
71
|
expect(described_class).to receive(:run_tests).with(accumulator).and_return(expected_accumulator)
|
70
72
|
|
71
73
|
expect(Kernel).to receive(:exit).with(expected_exitstatus)
|
@@ -43,6 +43,7 @@ describe KnapsackPro::Runners::Queue::MinitestRunner do
|
|
43
43
|
exitstatus: 0,
|
44
44
|
all_test_file_paths: [],
|
45
45
|
}
|
46
|
+
expect(described_class).to receive(:handle_signal!)
|
46
47
|
expect(described_class).to receive(:run_tests).with(accumulator).and_return(expected_accumulator)
|
47
48
|
|
48
49
|
expect(Kernel).to receive(:exit).with(expected_exitstatus)
|
@@ -68,6 +69,7 @@ describe KnapsackPro::Runners::Queue::MinitestRunner do
|
|
68
69
|
exitstatus: 0,
|
69
70
|
all_test_file_paths: [],
|
70
71
|
}
|
72
|
+
expect(described_class).to receive(:handle_signal!)
|
71
73
|
expect(described_class).to receive(:run_tests).with(accumulator).and_return(expected_accumulator)
|
72
74
|
|
73
75
|
expect(Kernel).to receive(:exit).with(expected_exitstatus)
|
@@ -49,6 +49,7 @@ describe KnapsackPro::Runners::Queue::RSpecRunner do
|
|
49
49
|
exitstatus: 0,
|
50
50
|
all_test_file_paths: [],
|
51
51
|
}
|
52
|
+
expect(described_class).to receive(:handle_signal!)
|
52
53
|
expect(described_class).to receive(:run_tests).with(accumulator).and_return(expected_accumulator)
|
53
54
|
|
54
55
|
expect(Kernel).to receive(:exit).with(expected_exitstatus)
|
@@ -74,6 +75,7 @@ describe KnapsackPro::Runners::Queue::RSpecRunner do
|
|
74
75
|
exitstatus: 0,
|
75
76
|
all_test_file_paths: [],
|
76
77
|
}
|
78
|
+
expect(described_class).to receive(:handle_signal!)
|
77
79
|
expect(described_class).to receive(:run_tests).with(accumulator).and_return(expected_accumulator)
|
78
80
|
|
79
81
|
expect(Kernel).to receive(:exit).with(expected_exitstatus)
|
@@ -99,6 +101,7 @@ describe KnapsackPro::Runners::Queue::RSpecRunner do
|
|
99
101
|
exitstatus: 0,
|
100
102
|
all_test_file_paths: [],
|
101
103
|
}
|
104
|
+
expect(described_class).to receive(:handle_signal!)
|
102
105
|
expect(described_class).to receive(:run_tests).with(accumulator).and_return(expected_accumulator)
|
103
106
|
|
104
107
|
expect(Kernel).to receive(:exit).with(expected_exitstatus)
|
@@ -124,6 +127,7 @@ describe KnapsackPro::Runners::Queue::RSpecRunner do
|
|
124
127
|
exitstatus: 0,
|
125
128
|
all_test_file_paths: [],
|
126
129
|
}
|
130
|
+
expect(described_class).to receive(:handle_signal!)
|
127
131
|
expect(described_class).to receive(:run_tests).with(accumulator).and_return(expected_accumulator)
|
128
132
|
|
129
133
|
expect(Kernel).to receive(:exit).with(expected_exitstatus)
|
@@ -165,6 +169,7 @@ describe KnapsackPro::Runners::Queue::RSpecRunner do
|
|
165
169
|
exitstatus: 0,
|
166
170
|
all_test_file_paths: [],
|
167
171
|
}
|
172
|
+
expect(described_class).to receive(:handle_signal!)
|
168
173
|
expect(described_class).to receive(:run_tests).with(accumulator).and_return(expected_accumulator)
|
169
174
|
|
170
175
|
expect(Kernel).to receive(:exit).with(expected_exitstatus)
|
@@ -200,6 +205,12 @@ describe KnapsackPro::Runners::Queue::RSpecRunner do
|
|
200
205
|
let(:test_file_paths) { ['a_spec.rb', 'b_spec.rb'] }
|
201
206
|
let(:logger) { double }
|
202
207
|
let(:rspec_seed) { 7771 }
|
208
|
+
let(:exit_code) { [0, 1].sample }
|
209
|
+
let(:rspec_wants_to_quit) { false }
|
210
|
+
let(:rspec_is_quitting) { false }
|
211
|
+
let(:rspec_core_runner) do
|
212
|
+
double(world: double(wants_to_quit: rspec_wants_to_quit, rspec_is_quitting: rspec_is_quitting))
|
213
|
+
end
|
203
214
|
|
204
215
|
before do
|
205
216
|
subset_queue_id = 'fake-subset-queue-id'
|
@@ -220,7 +231,6 @@ describe KnapsackPro::Runners::Queue::RSpecRunner do
|
|
220
231
|
'a_spec.rb', 'b_spec.rb',
|
221
232
|
]).and_return(options)
|
222
233
|
|
223
|
-
rspec_core_runner = double
|
224
234
|
expect(RSpec::Core::Runner).to receive(:new).with(options).and_return(rspec_core_runner)
|
225
235
|
expect(rspec_core_runner).to receive(:run).with($stderr, $stdout).and_return(exit_code)
|
226
236
|
|
@@ -237,13 +247,13 @@ describe KnapsackPro::Runners::Queue::RSpecRunner do
|
|
237
247
|
expect(configuration).to receive(:seed_used?).and_return(true)
|
238
248
|
expect(configuration).to receive(:seed).and_return(rspec_seed)
|
239
249
|
|
240
|
-
expect(KnapsackPro).to receive(:logger).
|
250
|
+
expect(KnapsackPro).to receive(:logger).at_least(2).and_return(logger)
|
241
251
|
expect(logger).to receive(:info)
|
242
252
|
.with("To retry the last batch of tests fetched from the API Queue, please run the following command on your machine:")
|
243
253
|
expect(logger).to receive(:info).with(/#{args.join(' ')} --seed #{rspec_seed}/)
|
244
254
|
end
|
245
255
|
|
246
|
-
context 'when exit code is zero' do
|
256
|
+
context 'when the exit code is zero' do
|
247
257
|
let(:exit_code) { 0 }
|
248
258
|
|
249
259
|
it do
|
@@ -258,7 +268,7 @@ describe KnapsackPro::Runners::Queue::RSpecRunner do
|
|
258
268
|
end
|
259
269
|
end
|
260
270
|
|
261
|
-
context 'when exit code is not zero' do
|
271
|
+
context 'when the exit code is not zero' do
|
262
272
|
let(:exit_code) { double }
|
263
273
|
|
264
274
|
it do
|
@@ -272,6 +282,58 @@ describe KnapsackPro::Runners::Queue::RSpecRunner do
|
|
272
282
|
})
|
273
283
|
end
|
274
284
|
end
|
285
|
+
|
286
|
+
context 'when RSpec wants to quit' do
|
287
|
+
let(:exit_code) { 0 }
|
288
|
+
let(:rspec_wants_to_quit) { true }
|
289
|
+
|
290
|
+
after do
|
291
|
+
described_class.class_variable_set(:@@terminate_process, false)
|
292
|
+
end
|
293
|
+
|
294
|
+
it 'terminates the process' do
|
295
|
+
expect(logger).to receive(:warn).with('RSpec wants to quit.')
|
296
|
+
|
297
|
+
expect(described_class.class_variable_get(:@@terminate_process)).to be false
|
298
|
+
|
299
|
+
expect(subject).to eq({
|
300
|
+
status: :next,
|
301
|
+
runner: runner,
|
302
|
+
can_initialize_queue: false,
|
303
|
+
args: args,
|
304
|
+
exitstatus: exitstatus,
|
305
|
+
all_test_file_paths: test_file_paths,
|
306
|
+
})
|
307
|
+
|
308
|
+
expect(described_class.class_variable_get(:@@terminate_process)).to be true
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
context 'when RSpec is quitting' do
|
313
|
+
let(:exit_code) { 0 }
|
314
|
+
let(:rspec_is_quitting) { true }
|
315
|
+
|
316
|
+
after do
|
317
|
+
described_class.class_variable_set(:@@terminate_process, false)
|
318
|
+
end
|
319
|
+
|
320
|
+
it 'terminates the process' do
|
321
|
+
expect(logger).to receive(:warn).with('RSpec is quitting.')
|
322
|
+
|
323
|
+
expect(described_class.class_variable_get(:@@terminate_process)).to be false
|
324
|
+
|
325
|
+
expect(subject).to eq({
|
326
|
+
status: :next,
|
327
|
+
runner: runner,
|
328
|
+
can_initialize_queue: false,
|
329
|
+
args: args,
|
330
|
+
exitstatus: exitstatus,
|
331
|
+
all_test_file_paths: test_file_paths,
|
332
|
+
})
|
333
|
+
|
334
|
+
expect(described_class.class_variable_get(:@@terminate_process)).to be true
|
335
|
+
end
|
336
|
+
end
|
275
337
|
end
|
276
338
|
|
277
339
|
context "when test files don't exist" 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: 5.3.
|
4
|
+
version: 5.3.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ArturT
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-07-
|
11
|
+
date: 2023-07-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|