diff --git a/ruby/lib/minitest/queue.rb b/ruby/lib/minitest/queue.rb index c25259bb..aa88646a 100644 --- a/ruby/lib/minitest/queue.rb +++ b/ruby/lib/minitest/queue.rb @@ -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 @@ -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 @@ -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 @@ -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