ci-queue 0.82.0 → 0.84.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/Gemfile.lock +59 -47
- data/README.md +87 -0
- data/ci-queue.gemspec +3 -1
- data/lib/ci/queue/build_record.rb +5 -5
- data/lib/ci/queue/class_resolver.rb +38 -0
- data/lib/ci/queue/configuration.rb +62 -1
- data/lib/ci/queue/file_loader.rb +101 -0
- data/lib/ci/queue/queue_entry.rb +48 -0
- data/lib/ci/queue/redis/acknowledge.lua +7 -5
- data/lib/ci/queue/redis/base.rb +29 -6
- data/lib/ci/queue/redis/build_record.rb +29 -17
- data/lib/ci/queue/redis/heartbeat.lua +4 -4
- data/lib/ci/queue/redis/monitor.rb +14 -2
- data/lib/ci/queue/redis/requeue.lua +17 -10
- data/lib/ci/queue/redis/reserve.lua +47 -8
- data/lib/ci/queue/redis/supervisor.rb +3 -3
- data/lib/ci/queue/redis/worker.rb +210 -27
- data/lib/ci/queue/static.rb +5 -5
- data/lib/ci/queue/version.rb +1 -1
- data/lib/ci/queue.rb +27 -0
- data/lib/minitest/queue/build_status_recorder.rb +4 -4
- data/lib/minitest/queue/junit_reporter.rb +2 -2
- data/lib/minitest/queue/lazy_entry_resolver.rb +55 -0
- data/lib/minitest/queue/lazy_test_discovery.rb +169 -0
- data/lib/minitest/queue/local_requeue_reporter.rb +11 -0
- data/lib/minitest/queue/order_reporter.rb +9 -2
- data/lib/minitest/queue/queue_population_strategy.rb +176 -0
- data/lib/minitest/queue/runner.rb +97 -22
- data/lib/minitest/queue/test_data.rb +15 -2
- data/lib/minitest/queue/worker_profile_reporter.rb +77 -0
- data/lib/minitest/queue.rb +278 -10
- data/lib/rspec/queue/build_status_recorder.rb +4 -2
- data/lib/rspec/queue.rb +6 -2
- metadata +38 -3
data/lib/minitest/queue.rb
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
require 'shellwords'
|
|
3
3
|
require 'minitest'
|
|
4
4
|
require 'minitest/reporters'
|
|
5
|
+
require 'concurrent/map'
|
|
5
6
|
|
|
6
7
|
require 'minitest/queue/failure_formatter'
|
|
7
8
|
require 'minitest/queue/error_report'
|
|
@@ -106,6 +107,10 @@ module Minitest
|
|
|
106
107
|
attr_accessor :start_timestamp, :finish_timestamp
|
|
107
108
|
end
|
|
108
109
|
|
|
110
|
+
module ResultMetadata
|
|
111
|
+
attr_accessor :queue_id, :queue_entry
|
|
112
|
+
end
|
|
113
|
+
|
|
109
114
|
module Queue
|
|
110
115
|
extend ::CI::Queue::OutputHelpers
|
|
111
116
|
attr_writer :run_command_formatter, :project_root
|
|
@@ -156,19 +161,29 @@ module Minitest
|
|
|
156
161
|
|
|
157
162
|
def run(reporter, *)
|
|
158
163
|
rescue_run_errors do
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
example.
|
|
164
|
+
begin
|
|
165
|
+
queue.poll do |example|
|
|
166
|
+
result = queue.with_heartbeat(example.queue_entry) do
|
|
167
|
+
example.run
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
handle_test_result(reporter, example, result)
|
|
162
171
|
end
|
|
163
172
|
|
|
164
|
-
|
|
173
|
+
report_load_stats(queue)
|
|
174
|
+
ensure
|
|
175
|
+
store_worker_profile(queue)
|
|
176
|
+
queue.stop_heartbeat!
|
|
165
177
|
end
|
|
166
|
-
|
|
167
|
-
queue.stop_heartbeat!
|
|
168
178
|
end
|
|
169
179
|
end
|
|
170
180
|
|
|
171
181
|
def handle_test_result(reporter, example, result)
|
|
182
|
+
if result.respond_to?(:queue_id=)
|
|
183
|
+
result.queue_id = example.id
|
|
184
|
+
result.queue_entry = example.queue_entry if result.respond_to?(:queue_entry=)
|
|
185
|
+
end
|
|
186
|
+
|
|
172
187
|
failed = !(result.passed? || result.skipped?)
|
|
173
188
|
|
|
174
189
|
if example.flaky?
|
|
@@ -180,20 +195,102 @@ module Minitest
|
|
|
180
195
|
# When we do a bisect, we don't care about the result other than the test we're running the bisect on
|
|
181
196
|
result.mark_as_flaked!
|
|
182
197
|
failed = false
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
if failed && CI::Queue.requeueable?(result) && queue.requeue(example.queue_entry)
|
|
201
|
+
result.requeue!
|
|
202
|
+
if CI::Queue.debug?
|
|
203
|
+
$stderr.puts "[ci-queue][requeue] test_id=#{example.id} error_class=#{result.failures.first&.class} error=#{result.failures.first&.message&.lines&.first&.chomp}"
|
|
204
|
+
end
|
|
183
205
|
elsif failed
|
|
184
206
|
queue.report_failure!
|
|
185
207
|
else
|
|
186
208
|
queue.report_success!
|
|
187
209
|
end
|
|
188
|
-
|
|
189
|
-
if failed && CI::Queue.requeueable?(result) && queue.requeue(example)
|
|
190
|
-
result.requeue!
|
|
191
|
-
end
|
|
192
210
|
reporter.record(result)
|
|
193
211
|
end
|
|
194
212
|
|
|
195
213
|
private
|
|
196
214
|
|
|
215
|
+
def report_load_stats(queue)
|
|
216
|
+
return unless CI::Queue.debug?
|
|
217
|
+
return unless queue.respond_to?(:file_loader)
|
|
218
|
+
return unless queue.respond_to?(:config) && queue.config.lazy_load
|
|
219
|
+
|
|
220
|
+
loader = queue.file_loader
|
|
221
|
+
return if loader.load_stats.empty?
|
|
222
|
+
|
|
223
|
+
total_time = loader.total_load_time
|
|
224
|
+
file_count = loader.load_stats.size
|
|
225
|
+
average = file_count.zero? ? 0 : (total_time / file_count)
|
|
226
|
+
|
|
227
|
+
puts
|
|
228
|
+
puts "File loading stats:"
|
|
229
|
+
puts " Total time: #{total_time.round(2)}s"
|
|
230
|
+
puts " Files loaded: #{file_count}"
|
|
231
|
+
puts " Average: #{average.round(3)}s per file"
|
|
232
|
+
|
|
233
|
+
slowest = loader.slowest_files(5)
|
|
234
|
+
return if slowest.empty?
|
|
235
|
+
|
|
236
|
+
puts " Slowest files:"
|
|
237
|
+
slowest.each do |file_path, duration|
|
|
238
|
+
puts " #{duration.round(3)}s - #{Minitest::Queue.relative_path(file_path)}"
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
def store_worker_profile(queue)
|
|
243
|
+
debug = CI::Queue.debug?
|
|
244
|
+
return unless queue.respond_to?(:config)
|
|
245
|
+
config = queue.config
|
|
246
|
+
|
|
247
|
+
run_start = Minitest::Queue::Runner.run_start
|
|
248
|
+
return unless run_start
|
|
249
|
+
|
|
250
|
+
run_end = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
251
|
+
profile = {
|
|
252
|
+
'worker_id' => config.worker_id,
|
|
253
|
+
'mode' => config.lazy_load ? 'lazy' : 'eager',
|
|
254
|
+
'role' => queue.master? ? 'leader' : 'non-leader',
|
|
255
|
+
'total_wall_clock' => (run_end - run_start).round(2),
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
first_test = queue.respond_to?(:first_reserve_at) ? queue.first_reserve_at : nil
|
|
259
|
+
profile['time_to_first_test'] = (first_test - run_start).round(2) if first_test
|
|
260
|
+
|
|
261
|
+
tests_run = queue.rescue_connection_errors { queue.worker_queue_length } if queue.respond_to?(:worker_queue_length)
|
|
262
|
+
profile['tests_run'] = tests_run.to_i if tests_run
|
|
263
|
+
|
|
264
|
+
load_tests_duration = Minitest::Queue::Runner.load_tests_duration
|
|
265
|
+
profile['load_tests_duration'] = load_tests_duration.round(2) if load_tests_duration
|
|
266
|
+
|
|
267
|
+
if queue.respond_to?(:file_loader) && queue.file_loader.load_stats.any?
|
|
268
|
+
loader = queue.file_loader
|
|
269
|
+
profile['files_loaded'] = loader.load_stats.size
|
|
270
|
+
profile['file_load_time'] = loader.total_load_time.round(2)
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
profile['total_files'] = Minitest::Queue::Runner.total_files if Minitest::Queue::Runner.total_files
|
|
274
|
+
|
|
275
|
+
rss_kb = begin
|
|
276
|
+
if File.exist?("/proc/#{Process.pid}/statm")
|
|
277
|
+
pages = Integer(File.read("/proc/#{Process.pid}/statm").split[1])
|
|
278
|
+
pages * 4
|
|
279
|
+
else
|
|
280
|
+
Integer(`ps -o rss= -p #{Process.pid}`.strip)
|
|
281
|
+
end
|
|
282
|
+
rescue
|
|
283
|
+
nil
|
|
284
|
+
end
|
|
285
|
+
profile['memory_rss_kb'] = rss_kb if rss_kb
|
|
286
|
+
|
|
287
|
+
queue.rescue_connection_errors do
|
|
288
|
+
queue.build.record_worker_profile(profile)
|
|
289
|
+
end
|
|
290
|
+
rescue => e
|
|
291
|
+
puts "WARNING: Failed to store worker profile: #{e.message}" if debug
|
|
292
|
+
end
|
|
293
|
+
|
|
197
294
|
def rescue_run_errors(&block)
|
|
198
295
|
block.call
|
|
199
296
|
rescue Errno::EPIPE
|
|
@@ -232,6 +329,10 @@ module Minitest
|
|
|
232
329
|
@id ||= "#{@runnable}##{@method_name}".freeze
|
|
233
330
|
end
|
|
234
331
|
|
|
332
|
+
def queue_entry
|
|
333
|
+
@queue_entry ||= CI::Queue::QueueEntry.format(id, nil)
|
|
334
|
+
end
|
|
335
|
+
|
|
235
336
|
def <=>(other)
|
|
236
337
|
id <=> other.id
|
|
237
338
|
end
|
|
@@ -270,6 +371,171 @@ module Minitest
|
|
|
270
371
|
end
|
|
271
372
|
end
|
|
272
373
|
|
|
374
|
+
class LazySingleExample
|
|
375
|
+
attr_reader :class_name, :method_name, :file_path
|
|
376
|
+
|
|
377
|
+
def initialize(class_name, method_name, file_path, loader:, resolver:, load_error: nil, queue_entry: nil)
|
|
378
|
+
@class_name = class_name
|
|
379
|
+
@method_name = method_name
|
|
380
|
+
@file_path = file_path
|
|
381
|
+
@loader = loader
|
|
382
|
+
@resolver = resolver
|
|
383
|
+
@load_error = load_error
|
|
384
|
+
@queue_entry_override = queue_entry
|
|
385
|
+
@runnable = nil
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
def id
|
|
389
|
+
@id ||= "#{@class_name}##{@method_name}".freeze
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
def queue_entry
|
|
393
|
+
@queue_entry ||= @queue_entry_override || CI::Queue::QueueEntry.format(id, file_path)
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
def <=>(other)
|
|
397
|
+
id <=> other.id
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
RUNNABLE_METHODS_TRIGGERED = Concurrent::Map.new # :nodoc:
|
|
401
|
+
|
|
402
|
+
def runnable
|
|
403
|
+
@runnable ||= begin
|
|
404
|
+
klass = @resolver.resolve(@class_name, file_path: @file_path, loader: @loader)
|
|
405
|
+
unless RUNNABLE_METHODS_TRIGGERED[klass]
|
|
406
|
+
klass.runnable_methods
|
|
407
|
+
RUNNABLE_METHODS_TRIGGERED[klass] = true
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
# If the method doesn't exist, the class may have been autoloaded by
|
|
411
|
+
# Zeitwerk without executing test-specific code (includes, helpers).
|
|
412
|
+
# Force load the file so all class-definition-time code executes.
|
|
413
|
+
unless klass.method_defined?(@method_name) || klass.private_method_defined?(@method_name)
|
|
414
|
+
if @file_path && @loader
|
|
415
|
+
@loader.load_file(@file_path)
|
|
416
|
+
RUNNABLE_METHODS_TRIGGERED.delete(klass)
|
|
417
|
+
klass.runnable_methods
|
|
418
|
+
RUNNABLE_METHODS_TRIGGERED[klass] = true
|
|
419
|
+
end
|
|
420
|
+
end
|
|
421
|
+
|
|
422
|
+
klass
|
|
423
|
+
end
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
def with_timestamps
|
|
427
|
+
start_timestamp = current_timestamp
|
|
428
|
+
result = yield
|
|
429
|
+
result
|
|
430
|
+
ensure
|
|
431
|
+
if result
|
|
432
|
+
result.start_timestamp = start_timestamp
|
|
433
|
+
result.finish_timestamp = current_timestamp
|
|
434
|
+
end
|
|
435
|
+
end
|
|
436
|
+
|
|
437
|
+
def run
|
|
438
|
+
with_timestamps do
|
|
439
|
+
if @load_error
|
|
440
|
+
build_error_result(@load_error)
|
|
441
|
+
elsif skip_stale_tests? && !(runnable.method_defined?(@method_name) || runnable.private_method_defined?(@method_name))
|
|
442
|
+
build_stale_skip_result
|
|
443
|
+
else
|
|
444
|
+
Minitest.run_one_method(runnable, @method_name)
|
|
445
|
+
end
|
|
446
|
+
rescue StandardError, ScriptError => error
|
|
447
|
+
build_error_result(error)
|
|
448
|
+
end
|
|
449
|
+
end
|
|
450
|
+
|
|
451
|
+
def flaky?
|
|
452
|
+
Minitest.queue.flaky?(self)
|
|
453
|
+
end
|
|
454
|
+
|
|
455
|
+
def source_location
|
|
456
|
+
return nil if @load_error
|
|
457
|
+
|
|
458
|
+
runnable.instance_method(@method_name).source_location
|
|
459
|
+
rescue NameError, NoMethodError, CI::Queue::FileLoadError, CI::Queue::ClassNotFoundError
|
|
460
|
+
nil
|
|
461
|
+
end
|
|
462
|
+
|
|
463
|
+
def marshal_dump
|
|
464
|
+
{
|
|
465
|
+
'class_name' => @class_name,
|
|
466
|
+
'method_name' => @method_name,
|
|
467
|
+
'file_path' => @file_path,
|
|
468
|
+
'load_error' => serialize_error(@load_error),
|
|
469
|
+
'queue_entry' => @queue_entry_override,
|
|
470
|
+
}
|
|
471
|
+
end
|
|
472
|
+
|
|
473
|
+
def marshal_load(payload)
|
|
474
|
+
@class_name = payload['class_name']
|
|
475
|
+
@method_name = payload['method_name']
|
|
476
|
+
@file_path = payload['file_path']
|
|
477
|
+
@load_error = deserialize_error(payload['load_error'])
|
|
478
|
+
@queue_entry_override = payload['queue_entry']
|
|
479
|
+
@loader = CI::Queue::FileLoader.new
|
|
480
|
+
@resolver = CI::Queue::ClassResolver
|
|
481
|
+
@runnable = nil
|
|
482
|
+
@id = nil
|
|
483
|
+
@queue_entry = nil
|
|
484
|
+
end
|
|
485
|
+
|
|
486
|
+
private
|
|
487
|
+
|
|
488
|
+
def serialize_error(error)
|
|
489
|
+
return nil unless error
|
|
490
|
+
|
|
491
|
+
{
|
|
492
|
+
'class' => error.class.name,
|
|
493
|
+
'message' => error.message,
|
|
494
|
+
'backtrace' => error.backtrace,
|
|
495
|
+
}
|
|
496
|
+
end
|
|
497
|
+
|
|
498
|
+
def deserialize_error(payload)
|
|
499
|
+
return nil unless payload
|
|
500
|
+
|
|
501
|
+
message = "#{payload['class']}: #{payload['message']}"
|
|
502
|
+
error = StandardError.new(message)
|
|
503
|
+
error.set_backtrace(payload['backtrace']) if payload['backtrace']
|
|
504
|
+
CI::Queue::FileLoadError.new(@file_path, error)
|
|
505
|
+
end
|
|
506
|
+
|
|
507
|
+
def build_error_result(error)
|
|
508
|
+
result_class = defined?(Minitest::Result) ? Minitest::Result : Minitest::Test
|
|
509
|
+
result = result_class.new(@method_name)
|
|
510
|
+
result.klass = @class_name if result.respond_to?(:klass=)
|
|
511
|
+
result.source_location = [@file_path || 'unknown', -1] if result.respond_to?(:source_location=)
|
|
512
|
+
result.failures << Minitest::UnexpectedError.new(error)
|
|
513
|
+
result
|
|
514
|
+
end
|
|
515
|
+
|
|
516
|
+
def skip_stale_tests?
|
|
517
|
+
Minitest.queue&.respond_to?(:config) && Minitest.queue.config.skip_stale_tests
|
|
518
|
+
end
|
|
519
|
+
|
|
520
|
+
def build_stale_skip_result
|
|
521
|
+
$stderr.puts "[ci-queue] Skipping stale preresolved entry: #{@class_name}##{@method_name} " \
|
|
522
|
+
"(method no longer exists in #{@file_path || 'unknown file'})"
|
|
523
|
+
|
|
524
|
+
result_class = defined?(Minitest::Result) ? Minitest::Result : Minitest::Test
|
|
525
|
+
result = result_class.new(@method_name)
|
|
526
|
+
result.klass = @class_name if result.respond_to?(:klass=)
|
|
527
|
+
result.source_location = [@file_path || 'unknown', -1] if result.respond_to?(:source_location=)
|
|
528
|
+
result.failures << Minitest::Skip.new(
|
|
529
|
+
"[ci-queue] Stale preresolved entry: #{@class_name}##{@method_name} no longer exists"
|
|
530
|
+
)
|
|
531
|
+
result
|
|
532
|
+
end
|
|
533
|
+
|
|
534
|
+
def current_timestamp
|
|
535
|
+
CI::Queue.time_now.to_i
|
|
536
|
+
end
|
|
537
|
+
end
|
|
538
|
+
|
|
273
539
|
attr_accessor :queue
|
|
274
540
|
|
|
275
541
|
def queue_reporters=(reporters)
|
|
@@ -310,10 +576,12 @@ if defined? Minitest::Result
|
|
|
310
576
|
Minitest::Result.prepend(Minitest::Requeueing)
|
|
311
577
|
Minitest::Result.prepend(Minitest::Flakiness)
|
|
312
578
|
Minitest::Result.prepend(Minitest::WithTimestamps)
|
|
579
|
+
Minitest::Result.prepend(Minitest::ResultMetadata)
|
|
313
580
|
else
|
|
314
581
|
Minitest::Test.prepend(Minitest::Requeueing)
|
|
315
582
|
Minitest::Test.prepend(Minitest::Flakiness)
|
|
316
583
|
Minitest::Test.prepend(Minitest::WithTimestamps)
|
|
584
|
+
Minitest::Test.prepend(Minitest::ResultMetadata)
|
|
317
585
|
|
|
318
586
|
module MinitestBackwardCompatibility
|
|
319
587
|
def source_location
|
|
@@ -18,12 +18,14 @@ module RSpec
|
|
|
18
18
|
|
|
19
19
|
def example_passed(notification)
|
|
20
20
|
example = notification.example
|
|
21
|
-
|
|
21
|
+
entry = CI::Queue::QueueEntry.format(example.id, nil)
|
|
22
|
+
build.record_success(entry)
|
|
22
23
|
end
|
|
23
24
|
|
|
24
25
|
def example_failed(notification)
|
|
25
26
|
example = notification.example
|
|
26
|
-
|
|
27
|
+
entry = CI::Queue::QueueEntry.format(example.id, nil)
|
|
28
|
+
build.record_error(entry, dump(notification))
|
|
27
29
|
end
|
|
28
30
|
|
|
29
31
|
private
|
data/lib/rspec/queue.rb
CHANGED
|
@@ -253,6 +253,10 @@ module RSpec
|
|
|
253
253
|
example.id
|
|
254
254
|
end
|
|
255
255
|
|
|
256
|
+
def queue_entry
|
|
257
|
+
@queue_entry ||= CI::Queue::QueueEntry.format(id, nil)
|
|
258
|
+
end
|
|
259
|
+
|
|
256
260
|
def <=>(other)
|
|
257
261
|
id <=> other.id
|
|
258
262
|
end
|
|
@@ -411,7 +415,7 @@ module RSpec
|
|
|
411
415
|
end
|
|
412
416
|
|
|
413
417
|
def requeue
|
|
414
|
-
@queue.requeue(@example)
|
|
418
|
+
@queue.requeue(@example.queue_entry)
|
|
415
419
|
end
|
|
416
420
|
|
|
417
421
|
def cancel_run!
|
|
@@ -422,7 +426,7 @@ module RSpec
|
|
|
422
426
|
end
|
|
423
427
|
|
|
424
428
|
def acknowledge
|
|
425
|
-
@queue.acknowledge(@example)
|
|
429
|
+
@queue.acknowledge(@example.queue_entry)
|
|
426
430
|
end
|
|
427
431
|
end
|
|
428
432
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ci-queue
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.84.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jean Boussier
|
|
@@ -149,6 +149,34 @@ dependencies:
|
|
|
149
149
|
- - ">="
|
|
150
150
|
- !ruby/object:Gem::Version
|
|
151
151
|
version: '0'
|
|
152
|
+
- !ruby/object:Gem::Dependency
|
|
153
|
+
name: benchmark
|
|
154
|
+
requirement: !ruby/object:Gem::Requirement
|
|
155
|
+
requirements:
|
|
156
|
+
- - ">="
|
|
157
|
+
- !ruby/object:Gem::Version
|
|
158
|
+
version: '0'
|
|
159
|
+
type: :development
|
|
160
|
+
prerelease: false
|
|
161
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
162
|
+
requirements:
|
|
163
|
+
- - ">="
|
|
164
|
+
- !ruby/object:Gem::Version
|
|
165
|
+
version: '0'
|
|
166
|
+
- !ruby/object:Gem::Dependency
|
|
167
|
+
name: rexml
|
|
168
|
+
requirement: !ruby/object:Gem::Requirement
|
|
169
|
+
requirements:
|
|
170
|
+
- - ">="
|
|
171
|
+
- !ruby/object:Gem::Version
|
|
172
|
+
version: '0'
|
|
173
|
+
type: :development
|
|
174
|
+
prerelease: false
|
|
175
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
176
|
+
requirements:
|
|
177
|
+
- - ">="
|
|
178
|
+
- !ruby/object:Gem::Version
|
|
179
|
+
version: '0'
|
|
152
180
|
- !ruby/object:Gem::Dependency
|
|
153
181
|
name: rubocop
|
|
154
182
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -190,11 +218,14 @@ files:
|
|
|
190
218
|
- lib/ci/queue/bisect.rb
|
|
191
219
|
- lib/ci/queue/build_record.rb
|
|
192
220
|
- lib/ci/queue/circuit_breaker.rb
|
|
221
|
+
- lib/ci/queue/class_resolver.rb
|
|
193
222
|
- lib/ci/queue/common.rb
|
|
194
223
|
- lib/ci/queue/configuration.rb
|
|
195
224
|
- lib/ci/queue/file.rb
|
|
225
|
+
- lib/ci/queue/file_loader.rb
|
|
196
226
|
- lib/ci/queue/grind.rb
|
|
197
227
|
- lib/ci/queue/output_helpers.rb
|
|
228
|
+
- lib/ci/queue/queue_entry.rb
|
|
198
229
|
- lib/ci/queue/redis.rb
|
|
199
230
|
- lib/ci/queue/redis/acknowledge.lua
|
|
200
231
|
- lib/ci/queue/redis/base.rb
|
|
@@ -222,14 +253,18 @@ files:
|
|
|
222
253
|
- lib/minitest/queue/grind_recorder.rb
|
|
223
254
|
- lib/minitest/queue/grind_reporter.rb
|
|
224
255
|
- lib/minitest/queue/junit_reporter.rb
|
|
256
|
+
- lib/minitest/queue/lazy_entry_resolver.rb
|
|
257
|
+
- lib/minitest/queue/lazy_test_discovery.rb
|
|
225
258
|
- lib/minitest/queue/local_requeue_reporter.rb
|
|
226
259
|
- lib/minitest/queue/order_reporter.rb
|
|
260
|
+
- lib/minitest/queue/queue_population_strategy.rb
|
|
227
261
|
- lib/minitest/queue/runner.rb
|
|
228
262
|
- lib/minitest/queue/statsd.rb
|
|
229
263
|
- lib/minitest/queue/test_data.rb
|
|
230
264
|
- lib/minitest/queue/test_data_reporter.rb
|
|
231
265
|
- lib/minitest/queue/test_time_recorder.rb
|
|
232
266
|
- lib/minitest/queue/test_time_reporter.rb
|
|
267
|
+
- lib/minitest/queue/worker_profile_reporter.rb
|
|
233
268
|
- lib/minitest/reporters/bisect_reporter.rb
|
|
234
269
|
- lib/minitest/reporters/statsd_reporter.rb
|
|
235
270
|
- lib/rspec/queue.rb
|
|
@@ -249,14 +284,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
249
284
|
requirements:
|
|
250
285
|
- - ">="
|
|
251
286
|
- !ruby/object:Gem::Version
|
|
252
|
-
version: '
|
|
287
|
+
version: '3.1'
|
|
253
288
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
254
289
|
requirements:
|
|
255
290
|
- - ">="
|
|
256
291
|
- !ruby/object:Gem::Version
|
|
257
292
|
version: '0'
|
|
258
293
|
requirements: []
|
|
259
|
-
rubygems_version: 4.0.
|
|
294
|
+
rubygems_version: 4.0.8
|
|
260
295
|
specification_version: 4
|
|
261
296
|
summary: Distribute tests over many workers using a queue
|
|
262
297
|
test_files: []
|