diff --git a/ruby/lib/ci/queue/redis/build_record.rb b/ruby/lib/ci/queue/redis/build_record.rb index cb45a755..3c23de95 100644 --- a/ruby/lib/ci/queue/redis/build_record.rb +++ b/ruby/lib/ci/queue/redis/build_record.rb @@ -57,12 +57,13 @@ def record_warning(type, attributes) end def record_error(id, payload, stats: nil) - acknowledged, _ = redis.pipelined do |pipeline| - @queue.acknowledge(id, error: payload, pipeline: pipeline) - record_stats(stats, pipeline: pipeline) - end + acknowledged = @queue.acknowledge(id, error: payload) - @queue.increment_test_failed if acknowledged == 1 + if acknowledged + # if another worker already acknowledged the test, we don't need to update the global stats or increment the test failed count + record_stats(stats) + @queue.increment_test_failed + end nil end diff --git a/ruby/lib/minitest/queue/runner.rb b/ruby/lib/minitest/queue/runner.rb index ef50ada3..8515ca71 100644 --- a/ruby/lib/minitest/queue/runner.rb +++ b/ruby/lib/minitest/queue/runner.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require 'optparse' require 'json' +require 'fileutils' require 'minitest/queue' require 'ci/queue' require 'digest/md5' @@ -242,16 +243,16 @@ def bisect_command puts File.write('log/test_order.log', failing_order.to_a.map(&:id).join("\n")) - + bisect_test_details = failing_order.to_a.map do |test| source_location = test.source_location file_path = source_location&.first || 'unknown' line_number = source_location&.last || -1 "#{test.id} #{file_path}:#{line_number}" end - + File.write('log/bisect_test_details.log', bisect_test_details.join("\n")) - + exit! 0 end end @@ -336,8 +337,22 @@ def display_warnings(build) warnings = build.pop_warnings.map do |type, attributes| attributes.merge(type: type) end.compact - File.open(queue_config.warnings_file, 'w') do |f| - JSON.dump(warnings, f) + + return if warnings.empty? + + begin + # Ensure directory exists + dir = File.dirname(queue_config.warnings_file) + FileUtils.mkdir_p(dir) unless File.directory?(dir) + + # Write each warning as a separate JSON line (JSONL format) + File.open(queue_config.warnings_file, 'a') do |f| + warnings.each do |warning| + f.puts(JSON.dump(warning)) + end + end + rescue => error + STDERR.puts "Failed to write warnings: #{error.message}" end end diff --git a/ruby/test/integration/minitest_redis_test.rb b/ruby/test/integration/minitest_redis_test.rb index dbb74d9f..2a24438a 100644 --- a/ruby/test/integration/minitest_redis_test.rb +++ b/ruby/test/integration/minitest_redis_test.rb @@ -89,7 +89,7 @@ def test_lost_test_with_heartbeat_monitor assert_empty err result = normalize(out.lines[1].strip) assert_equal "Ran 1 tests, 0 assertions, 0 failures, 0 errors, 0 skips, 0 requeues in X.XXs (aggregated)", result - warnings = JSON.parse(warnings_file.read) + warnings = warnings_file.read.lines.map { |line| JSON.parse(line) } assert_equal 1, warnings.size end end @@ -927,7 +927,7 @@ def test_redis_reporter end warnings_file.rewind - content = JSON.parse(warnings_file.read) + content = warnings_file.read.lines.map { |line| JSON.parse(line) } assert_equal 1, content.size assert_equal "RESERVED_LOST_TEST", content[0]["type"] assert_equal "Atest#test_bar", content[0]["test"]