#!/usr/bin/python3 # -*- coding: utf-8 -*- # # Copyright © 2015-2017 Holger Levsen # based on ~jenkins.d.n:~mattia/status.sh by Mattia Rizzolo # Licensed under GPL-2 # # Depends: python3 # from reproducible_common import * from reproducible_html_indexes import build_leading_text_section from sqlalchemy import select, func, cast, Integer, and_, bindparam import glob bugs = get_bugs() # sqlalchemy table definitions needed for queries results = db_table('results') sources = db_table('sources') schedule = db_table('schedule') stats_build = db_table('stats_build') def convert_into_status_html(status): if status != 'None': status, icon, spokenstatus = get_status_icon(status) return status + ' ' + status + '' else: return '' def generate_schedule(arch): """ the schedule pages are very different than others index pages """ log.info('Building the schedule index page for ' + arch + '...') title = 'Packages currently scheduled on ' + arch + ' for testing for build reproducibility' # 'AND h.name=s.name AND h.suite=s.suite AND h.architecture=s.architecture' # in this query and the query below is needed due to not using package_id # in the stats_build table, which should be fixed... averagesql = select([ func.coalesce(func.avg(cast(stats_build.c.build_duration, Integer)), 0) ]).where( and_( stats_build.c.status.in_(('reproducible', 'unreproducible')), stats_build.c.name == sources.c.name, stats_build.c.suite == sources.c.suite, stats_build.c.architecture == sources.c.architecture, ) ).as_scalar() query = select([ schedule.c.date_scheduled, sources.c.suite, sources.c.architecture, sources.c.name, results.c.status, results.c.build_duration, averagesql ]).select_from( sources.join(schedule).join(results, isouter=True) ).where( and_( schedule.c.date_build_started == None, sources.c.architecture == bindparam('arch'), ) ).order_by( schedule.c.date_scheduled ) text = Template('$tot packages are currently scheduled for testing on $arch:') html = '' rows = query_db(query.params({'arch': arch})) html += build_leading_text_section({'text': text}, rows, defaultsuite, arch) html += generate_live_status_table(arch) html += '

\n' + tab html += '' html += '\n' for row in rows: # 0: date_scheduled, 1: suite, 2: arch, 3: pkg name 4: previous status 5: previous build duration 6. avg build duration pkg = row[3] duration = convert_into_hms_string(row[5]) avg_duration = convert_into_hms_string(row[6]) html += tab + '' html += '\n' html += '
#scheduled atsuitearchsource packageprevious build statusprevious build durationaverage build duration
 ' + row[0] + '' + row[1] + '' + row[2] + '' html += link_package(pkg, row[1], row[2], bugs) html += ''+convert_into_status_html(str(row[4]))+''+duration+'' + avg_duration + '

\n' destfile = DEBIAN_BASE + '/index_' + arch + '_scheduled.html' desturl = DEBIAN_URL + '/index_' + arch + '_scheduled.html' suite_arch_nav_template = DEBIAN_URI + '/index_{{arch}}_scheduled.html' left_nav_html = create_main_navigation(arch=arch, no_suite=True, displayed_page='scheduled', suite_arch_nav_template=suite_arch_nav_template) write_html_page(title=title, body=html, destfile=destfile, style_note=True, refresh_every=60, left_nav_html=left_nav_html) log.info("Page generated at " + desturl) def generate_live_status_table(arch): averagesql = select([ func.coalesce(func.avg(cast(stats_build.c.build_duration, Integer)), 0) ]).where( and_( stats_build.c.status.in_(('reproducible', 'unreproducible')), stats_build.c.name == sources.c.name, stats_build.c.suite == sources.c.suite, stats_build.c.architecture == sources.c.architecture, ) ).as_scalar() query = select([ sources.c.id, sources.c.suite, sources.c.architecture, sources.c.name, sources.c.version, schedule.c.date_build_started, results.c.status, results.c.build_duration, averagesql, schedule.c.job, ]).select_from( sources.join(schedule).join(results, isouter=True) ).where( and_( schedule.c.date_build_started != None, sources.c.architecture == bindparam('arch'), ) ).order_by( schedule.c.date_scheduled ) html = '' rows = query_db(query.params({'arch': arch})) html += '

\n' + tab html += '' html += '' html += '' html += '' html += '\n' counter = 0 for row in rows: counter += 1 suite = row[1] arch = row[2] pkg = row[3] duration = convert_into_hms_string(row[7]) avg_duration = convert_into_hms_string(row[8]) html += tab + '' html += '' html += '' html += '' html += '' html += '' html += '\n' html += '
#src pkg idsuitearchsource packageversionbuild startedprevious build statusprevious build durationaverage build durationbuilder job
 ' + str(row[0]) + '' + suite + '' + arch + '' + link_package(pkg, suite, arch) + '' + str(row[4]) + '' + str(row[5]) + '' + convert_into_status_html(str(row[6])) + '' + duration + '' + avg_duration + '' + str(row[9]) + '

\n' return html def generate_oldies(arch): log.info('Building the oldies page for ' + arch + '...') title = 'Oldest results on ' + arch html = '' for suite in SUITES: query = select([ sources.c.suite, sources.c.architecture, sources.c.name, results.c.status, results.c.build_date ]).select_from( results.join(sources) ).where( and_( sources.c.suite == bindparam('suite'), sources.c.architecture == bindparam('arch'), results.c.status != 'blacklisted' ) ).order_by( results.c.build_date ).limit(15) text = Template('Oldest results on $suite/$arch:') rows = query_db(query.params({'arch': arch, 'suite': suite})) html += build_leading_text_section({'text': text}, rows, suite, arch) html += '

\n' + tab html += '' html += '\n' for row in rows: # 0: suite, 1: arch, 2: pkg name 3: status 4: build date pkg = row[2] html += tab + '' html += '\n' html += '
#suitearchsource packagestatusbuild date
 ' + row[0] + '' + row[1] + '' html += link_package(pkg, row[0], row[1], bugs) html += ''+convert_into_status_html(str(row[3]))+'' + row[4] + '

\n' destfile = DEBIAN_BASE + '/index_' + arch + '_oldies.html' desturl = DEBIAN_URL + '/index_' + arch + '_oldies.html' left_nav_html = create_main_navigation(arch=arch) write_html_page(title=title, body=html, destfile=destfile, style_note=True, refresh_every=60, left_nav_html=left_nav_html) log.info("Page generated at " + desturl) if __name__ == '__main__': for arch in ARCHS: generate_schedule(arch) generate_oldies(arch)