class RSpec::Buildkite::AnnotationFormatter

Create a Buildkite annotation for RSpec failures

Help folks fix their builds as soon as possible when failures crop up by calling out failures in an annotation, even while the build is still running.

Uses a background Thread so we don't block the build.

Public Class Methods

new(output) click to toggle source
# File lib/rspec/buildkite/annotation_formatter.rb, line 17
def initialize(output)
  # We don't actually use this, but keep a reference anyway
  @output = output

  # Only setup if we're actually running on Buildkite
  if ENV["BUILDKITE"]
    @queue = Queue.new
    @thread = Thread.new(&method(:thread))
    at_exit { @queue.push(:close); @thread.join }
  end
end

Public Instance Methods

example_failed(notification) click to toggle source
# File lib/rspec/buildkite/annotation_formatter.rb, line 29
def example_failed(notification)
  @queue.push(notification) if @queue
end

Private Instance Methods

format_failure(notification) click to toggle source
# File lib/rspec/buildkite/annotation_formatter.rb, line 55
def format_failure(notification)
  build_url = ENV["BUILDKITE_BUILD_URL"].to_s
  job_id = ENV["BUILDKITE_JOB_ID"].to_s
  job_url = "#{build_url}##{job_id}"

  %{<details>\n} <<
  %{<summary>#{notification.description.encode(:xml => :text)}</summary>\n} <<
  %{<pre class="term">#{Recolorizer.recolorize(notification.colorized_message_lines.join("\n").encode(:xml => :text))}</pre>\n} <<
  format_rerun(notification) <<
  %{<p>in <a href=#{job_url.encode(:xml => :attr)}>Job ##{job_id.encode(:xml => :text)}</a></p>\n} <<
  %{</details>} <<
  %{\n\n\n}
end
format_rerun(notification) click to toggle source
# File lib/rspec/buildkite/annotation_formatter.rb, line 69
def format_rerun(notification)
  %{<pre class="term">} <<
  %{<span class="term-fg31">rspec #{notification.example.location_rerun_argument.encode(:xml => :text)}</span>} <<
  %{ <span class="term-fg36"># #{notification.example.full_description.encode(:xml => :text)}</span>} <<
  %{</pre>\n}
end
thread() click to toggle source
# File lib/rspec/buildkite/annotation_formatter.rb, line 35
def thread
  while notification = @queue.pop
    break if notification == :close

    if notification
      system("buildkite-agent", "annotate",
        "--context", "rspec",
        "--style", "error",
        "--append",
        format_failure(notification),
        out: :close # only display errors
      ) or raise "buildkite-agent failed to run: #{$?}#{" (command not found)" if $?.exitstatus == 127}"
    end
  end
rescue
  $stderr.puts "Warning: Couldn't create Buildkite annotations:\n" <<
    "  #{$!.to_s}\n" <<
    "    #{$!.backtrace.join("\n    ")}"
end