require 'cgi'
require 'erb'
require 'erubi'
require 'forwardable'
require 'json'
require 'pathname'
require 'debci'
require 'debci/feed'
require 'debci/job'
require 'debci/package'
require 'debci/package_status'
require 'debci/graph'
require 'debci/html_helpers'
require 'fileutils'
module Debci
class HTML
class << self
def update
html = Debci::HTML.new
Debci.config.suite_list.each do |suite|
Debci.config.arch_list.each do |arch|
json = Debci::HTML::JSON.new(suite, arch)
json.status
json.history
json.packages
end
end
html.index('index.html')
end
def update_package(package)
feed = Debci::HTML::Feed.new
feed.package(package)
end
end
class Rooted
attr_reader :root, :datadir
def initialize
data_basedir = Debci.config.data_basedir
@root = Pathname(data_basedir) / datadir
end
end
class JSON < Rooted
attr_accessor :suite, :arch
def initialize(suite, arch)
@datadir = 'status'
super()
self.suite = suite
self.arch = arch
end
def status_packages_data
@status_packages_data ||=
Debci::PackageStatus.where(suite: suite, arch: arch).includes(:job)
end
def status
data = {
pass: 0,
fail: 0,
neutral: 0,
tmpfail: 0,
total: 0,
}
status_packages_data.each do |package_status|
status = package_status.job.status
data[status.to_sym] += 1
data[:total] += 1
end
data[:date] = Time.now.strftime('%Y-%m-%dT%H:%M:%S')
output = ::JSON.pretty_generate(data)
today = root / suite / arch / Time.now.strftime('%Y/%m/%d.json')
today.parent.mkpath
today.write(output)
current = root / suite / arch / 'status.json'
current.write(output)
end
def history
status_history = (root / suite / arch).glob('[0-9]*/[0-9]*/[0-9]*.json')
status_history_data = status_history.sort.map { |f| ::JSON.parse(f.read) }
h = root / suite / arch / 'history.json'
h.write(::JSON.pretty_generate(status_history_data))
end
def packages
p = root / suite / arch / 'packages.json'
p.write(::JSON.pretty_generate(status_packages_data.map(&:job).as_json))
end
end
class Feed < Rooted
def initialize
@datadir = 'feeds'
super
end
def package(pkg)
news = pkg.news
write_feed(news, root / pkg.prefix / "#{pkg.name}.xml") do |feed|
feed.channel.title = "#{pkg.name} CI news feed"
feed.channel.about = Debci.config.url_base + "/packages/#{pkg.prefix}/#{pkg.name}/"
feed.channel.description = [
"News for #{pkg.name}.",
'Includes only state transitions (pass-fail, and fail-pass).',
'Full history is available in the package page and in the published data files.',
].join(' ')
end
end
private
def write_feed(news, feedfile, &block)
feed = Debci::Feed.new(news, &block)
feedfile.parent.mkpath
feed.write(feedfile)
end
end
include Debci::HTMLHelpers
attr_reader :root_directory
def initialize(root_directory=Debci.config.html_dir)
@root_directory = root_directory
@package_prefixes = Debci::Package.prefixes
@head = read_config_file('head.html')
@footer = read_config_file('footer.html')
end
def index(filename)
expand_template(:index, filename)
end
private
def templates
@templates ||= {}
end
def load_template(template)
binding.eval(read_template(template).src) end
def read_template(name)
templates[name] ||= begin
filename = File.join(File.dirname(__FILE__), 'html/templates', "#{name}.erb")
Erubi::Engine.new(
File.read(filename),
escape: true,
filename: filename,
)
end
end
def expand_template(template, filename)
directory = File.dirname(filename)
abs_filename = File.join(root_directory, filename)
FileUtils.mkdir_p(File.dirname(abs_filename))
@root = directory.split('/').map { |_| '..' }.join('/')
html = load_template(:layout) do
load_template(template)
end
File.open(abs_filename, 'w') do |f|
f.write(html)
end
end
def read_config_file(filename)
file_path = File.join(Debci.config.config_dir, filename)
if File.exist?(file_path)
File.read(file_path)
end
end
end
end