Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 74 additions & 55 deletions ruby/lib/minitest/queue.rb
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ module WithTimestamps
end

module Queue
include ::CI::Queue::OutputHelpers
extend ::CI::Queue::OutputHelpers
attr_writer :run_command_formatter, :project_root

def run_command_formatter
Expand Down Expand Up @@ -149,8 +149,79 @@ def self.relative_path(path, root: project_root)
path
end

class << self
def queue
Minitest.queue
end

def run(reporter, *)
rescue_run_errors do
queue.poll do |example|
result = queue.with_heartbeat(example.id) do
example.run
end

handle_test_result(reporter, example, result)
end

queue.stop_heartbeat!
end
end

def handle_test_result(reporter, example, result)
failed = !(result.passed? || result.skipped?)

if example.flaky?
result.mark_as_flaked!
failed = false
end

if failed && queue.config.failing_test && queue.config.failing_test != example.id
# When we do a bisect, we don't care about the result other than the test we're running the bisect on
result.mark_as_flaked!
failed = false
elsif failed
queue.report_failure!
else
queue.report_success!
end

if failed && CI::Queue.requeueable?(result) && queue.requeue(example)
result.requeue!
end
reporter.record(result)
end

private

def rescue_run_errors(&block)
block.call
rescue Errno::EPIPE
# This happens when the heartbeat process dies
reopen_previous_step
puts red("The heartbeat process died. This worker is exiting early.")
exit!(41)
rescue CI::Queue::Error => error
reopen_previous_step
puts red("#{error.class}: #{error.message}")
error.backtrace.each do |frame|
puts red(frame)
end
exit!(41)
rescue => error
reopen_previous_step
Minitest.queue.report_worker_error(error)
puts red("This worker exited because of an uncaught application error:")
puts red("#{error.class}: #{error.message}")
error.backtrace.each do |frame|
puts red(frame)
end
exit!(42)
end
end

class SingleExample
attr_reader :method_name
attr_reader :runnable, :method_name

def initialize(runnable, method_name)
@runnable = runnable
Expand Down Expand Up @@ -212,7 +283,7 @@ def loaded_tests

def __run(*args)
if queue
run_from_queue(*args)
Queue.run(*args)

if queue.config.circuit_breakers.any?(&:open?)
STDERR.puts queue.config.circuit_breakers.map(&:message).join(' ').strip
Expand All @@ -225,58 +296,6 @@ def __run(*args)
super
end
end

def run_from_queue(reporter, *)
queue.poll do |example|
result = queue.with_heartbeat(example.id) do
example.run
end

failed = !(result.passed? || result.skipped?)

if example.flaky?
result.mark_as_flaked!
failed = false
end

if failed && queue.config.failing_test && queue.config.failing_test != example.id
# When we do a bisect, we don't care about the result other than the test we're running the bisect on
result.mark_as_flaked!
failed = false
elsif failed
queue.report_failure!
else
queue.report_success!
end

if failed && CI::Queue.requeueable?(result) && queue.requeue(example)
result.requeue!
end
reporter.record(result)
end
queue.stop_heartbeat!
rescue Errno::EPIPE
# This happens when the heartbeat process dies
reopen_previous_step
puts red("The heartbeat process died. This worker is exiting early.")
exit!(41)
rescue CI::Queue::Error => error
reopen_previous_step
puts red("#{error.class}: #{error.message}")
error.backtrace.each do |frame|
puts red(frame)
end
exit!(41)
rescue => error
reopen_previous_step
queue.report_worker_error(error)
puts red("This worker exited because of an uncaught application error:")
puts red("#{error.class}: #{error.message}")
error.backtrace.each do |frame|
puts red(frame)
end
exit!(42)
end
end
end

Expand Down
Loading