require 'json'
require 'time'
module Debci
class Status
attr_accessor :suite, :architecture, :run_id, :package, :version, :date, :trigger, :status, :previous_status, :duration_seconds, :duration_human, :message, :last_pass_version, :last_pass_date
def newsworthy?
[
[:fail, :pass],
[:pass, :fail],
].include?([status, previous_status])
end
def title
{
:pass => "Pass",
:fail => "Fail",
:tmpfail => "Temporary failure",
:no_test_data => "No test data",
}.fetch(status, "Unknown")
end
def extended_status
case status
when :pass
:pass
when :fail
case last_pass_version
when "never"
:fail_passed_never
when version
:fail_passed_current
when "unknown"
:fail
else
:fail_passed_old
end
when :tmpfail
case previous_status
when :pass
:tmpfail_pass
when :fail
:tmpfail_fail
else
:tmpfail
end
else
status
end
end
def failmsg
{
:fail_passed_never => "never passed",
:fail_passed_current => "previously passed",
:fail_passed_old => "#{last_pass_version} passed"
}[extended_status]
end
def headline
msg = "#{package} #{version} #{status.upcase}ED on #{suite}/#{architecture}"
if status == :fail && failmsg
msg += " (#{failmsg})"
end
msg
end
def description
msg = "The tests for #{package}, version #{version}, #{status.upcase}ED on #{suite}/#{architecture} but have previously #{previous_status.upcase}ED"
msg += case extended_status
when :fail_passed_current
" for the current version."
when :fail_passed_old
" for version #{last_pass_version}."
else
"."
end
end
def time
days = (Time.now - date)/86400
if days >= 1 || days <= -1
"#{days.floor} day(s) ago"
else
"#{Time.at(Time.now - date).gmtime.strftime('%H')} hour(s) ago"
end
end
def self.from_file(file, suite, architecture)
status = new
status.suite = suite
status.architecture = architecture
unless File.exists?(file)
status.status = :no_test_data
return status
end
data = nil
begin
File.open(file, 'r') do |f|
data = JSON.load(f)
end
rescue JSON::ParserError
true end
return status unless data
from_data(data, suite, architecture)
end
def self.from_data(data, suite, architecture)
status = Debci::Status.new
status.suite = suite
status.architecture = architecture
status.run_id = data['run_id'] || data['date']
status.package = data['package']
status.version = data['version']
status.date =
begin
Time.parse(data.fetch('date', 'unknown') + ' UTC')
rescue ArgumentError
nil
end
status.trigger = data['trigger']
status.status = data.fetch('status', :unknown).to_sym
status.previous_status = data.fetch('previous_status', :unknown).to_sym
status.duration_seconds =
begin
Integer(data.fetch('duration_seconds', 0))
rescue ArgumentError
nil
end
status.duration_human = data['duration_human']
status.message = data['message']
status.last_pass_version = data.fetch('last_pass_version', 'unknown')
status.last_pass_date =
begin
Time.parse(data.fetch('last_pass_date', 'unknown') + ' UTC')
rescue ArgumentError
nil
end
status
end
def expired?
days = Debci.config.data_retention_days.to_i
if days > 0
retention_window = days * (24*60*60)
Time.now > self.date + retention_window
else
false
end
end
def inspect
"<#{suite}/#{architecture} #{status}>"
end
end
end