From 0c3fcd537bd06556cda1d290ee926e8365969a04 Mon Sep 17 00:00:00 2001 From: Valerie R Young Date: Thu, 16 Jun 2016 09:45:56 -0400 Subject: reproducible debian: improve package page navigation Changes made: - suite and arch specific details moved from the top of side bar to the suite and arch section - "notes" and "test history" (suite and arch agnostic) move to the top of side bar - hover text added to most links, starting with either "Go to:" (if the link takes you away from package page) or "Show:" (if the link opens a file in the iframe) - enabled notifications flag still on top left, by "Test Details" header reproducible debian: address mattia's code review comments Signed-off-by: Holger Levsen --- bin/reproducible_common.py | 1 + bin/reproducible_html_packages.py | 289 ++++++++++++----------- bin/templates/package_page.mustache | 44 ++++ bin/templates/package_suitearch_details.mustache | 36 +++ bin/templates/package_suitearch_section.mustache | 30 +++ bin/templates/status_icon_link.mustache | 14 ++ update_jdn.sh | 1 + 7 files changed, 272 insertions(+), 143 deletions(-) create mode 100644 bin/templates/package_page.mustache create mode 100644 bin/templates/package_suitearch_details.mustache create mode 100644 bin/templates/package_suitearch_section.mustache create mode 100644 bin/templates/status_icon_link.mustache diff --git a/bin/reproducible_common.py b/bin/reproducible_common.py index 3c3f31b9..d0224b1b 100755 --- a/bin/reproducible_common.py +++ b/bin/reproducible_common.py @@ -44,6 +44,7 @@ defaultarch = 'amd64' BIN_PATH = '/srv/jenkins/bin' BASE = '/var/lib/jenkins/userContent/reproducible' DEBIAN_BASE = '/var/lib/jenkins/userContent/reproducible/debian' +TEMPLATE_PATH = BIN_PATH + '/templates' REPRODUCIBLE_JSON = BASE + '/reproducible.json' REPRODUCIBLE_TRACKER_JSON = BASE + '/reproducible-tracker.json' diff --git a/bin/reproducible_html_packages.py b/bin/reproducible_html_packages.py index 840bc17a..f9d26198 100755 --- a/bin/reproducible_html_packages.py +++ b/bin/reproducible_html_packages.py @@ -10,48 +10,18 @@ # Build rb-pkg pages (the pages that describe the package status) from reproducible_common import * +import pystache -html_package_page = Template((tab*2).join((""" -
-

$package

- - -${project_links} -
- -""" % DEBIAN_URL ).splitlines(True))) - +# Templates used for creating package pages +renderer = pystache.Renderer(); +package_page_template = renderer.load_template( + TEMPLATE_PATH + '/package_page') +suitearch_section_template = renderer.load_template( + TEMPLATE_PATH + '/package_suitearch_section') +suitearch_details_template = renderer.load_template( + TEMPLATE_PATH + '/package_suitearch_details') +status_icon_link_template = renderer.load_template( + TEMPLATE_PATH + '/status_icon_link') def sizeof_fmt(num): for unit in ['B','KB','MB','GB']: @@ -65,37 +35,33 @@ def sizeof_fmt(num): def gen_status_link_icon(status, spokenstatus, icon, suite, arch): - html = """ - - {spokenstatus} - - - {spokenstatus} - """ - - # There are no indices for untested packages - if status == 'untested': - html = '{spokenstatus} {spokenstatus}' - - return html.format(status=status, spokenstatus=spokenstatus, icon=icon, suite=suite, arch=arch) + context = { + 'status': status, + 'spokenstatus': spokenstatus, + 'icon': icon, + 'suite': suite, + 'arch': arch, + 'untested': True if status == 'untested' else False, + } + return renderer.render(status_icon_link_template, context) - -def link_buildlogs(package, eversion, suite, arch): - html = '' +def get_buildlog_links_context(package, eversion, suite, arch): log = suite + '/' + arch + '/' + package + '_' + eversion + '.build2.log.gz' diff = suite + '/' + arch + '/' + package + '_' + eversion + '.diff.gz' + + context = {} if os.access(LOGS_PATH+'/'+log, os.R_OK): - uri = LOGS_URI + '/' + log - size = sizeof_fmt(os.stat(LOGS_PATH+'/'+log).st_size) - html += 'build2 (' + size + ')\n' + context['build2_uri'] = LOGS_URI + '/' + log + context['build2_size'] = sizeof_fmt(os.stat(LOGS_PATH+'/'+log).st_size) + if os.access(DIFFS_PATH+'/'+diff, os.R_OK): - uri = DIFFS_URI + '/' + diff - html += 'diff\n' - return html + context['diff_uri'] = DIFFS_URI + '/' + diff + + return context -def link_diffs(package, eversion, suite, arch, status): - html = '' +def get_dbd_link_context(package, eversion, suite, arch, status): + dbd = DBD_PATH + '/' + suite + '/' + arch + '/' + package + '_' + \ eversion + '.diffoscope.html' dbdtxt = DBDTXT_PATH + '/' + suite + '/' + arch + '/' + package + '_' + \ @@ -104,98 +70,132 @@ def link_diffs(package, eversion, suite, arch, status): eversion + '.diffoscope.html' dbdtxt_url = DBDTXT_URI + '/' + suite + '/' + arch + '/' + package + '_' + \ eversion + '.diffoscope.txt' + + context = {} if os.access(dbd, os.R_OK): - html += '
  • differences\n' + context['dbd_url'] = dbd_url if os.access(dbdtxt, os.R_OK): - html += '(txt)\n' - html += '
  • \n' + context['dbdtxt_url'] = dbdtxt_url else: if status == 'unreproducible' and not args.ignore_missing_files: log.critical(DEBIAN_URL + '/' + suite + '/' + arch + '/' + package + ' is unreproducible, but without diffoscope output.') - return html, dbd_url + return context, dbd_url -def gen_extra_links(package, version, suite, arch, status): +def gen_suitearch_details(package, version, suite, arch, status, spokenstatus, + build_date): eversion = strip_epoch(version) - notes = NOTES_PATH + '/' + package + '_note.html' - buildinfo = BUILDINFO_PATH + '/' + suite + '/' + arch + '/' + package + \ + buildinfo_file = BUILDINFO_PATH + '/' + suite + '/' + arch + '/' + package + \ '_' + eversion + '_' + arch + '.buildinfo' - links = '' + context = {} default_view = '' - if os.access(notes, os.R_OK): - url = NOTES_URI + '/' + package + '_note.html' - links += '
  • notes
  • \n' - default_view = url - dbd = link_diffs(package, eversion, suite, arch, status) - links += dbd[0] if dbd[0] else '' - if dbd[0] and not default_view: - default_view = dbd[1] + + # Make notes the default default view + notes_file = NOTES_PATH + '/' + package + '_note.html' + notes_uri = NOTES_URI + '/' + package + '_note.html' + if os.access(notes_file, os.R_OK): + default_view = notes_uri + + # Get summary context + context['status_html'] = gen_status_link_icon(status, spokenstatus, None, + suite, arch) + context['build_date'] = build_date + + default_view = '' + # Get diffoscope differences context + dbd = get_dbd_link_context(package, eversion, suite, arch, status) + if dbd[0]: + context['dbd'] = dbd[0] + default_view = default_view if default_view else dbd[1] + + # Get buildinfo context if pkg_has_buildinfo(package, version, suite, arch): url = BUILDINFO_URI + '/' + suite + '/' + arch + '/' + package + \ '_' + eversion + '_' + arch + '.buildinfo' - links += '
  • buildinfo
  • \n' - if not default_view: - default_view = url + context['buildinfo_uri'] = url + default_view = default_view if default_view else url elif not args.ignore_missing_files and status not in \ ('untested', 'blacklisted', 'FTBFS', 'not for us', 'depwait', '404'): - log.critical('buildinfo not detected at ' + buildinfo) + log.critical('buildinfo not detected at ' + buildinfo_file) + + # Get rbuild, build2 and build diffs context rbuild = pkg_has_rbuild(package, version, suite, arch) if rbuild: # being a tuple (rbuild path, size), empty if non existant url = RBUILD_URI + '/' + suite + '/' + arch + '/' + package + '_' + \ eversion + '.rbuild.log' # apache ignores the trailing .gz - links +='
  • rbuild (' + \ - sizeof_fmt(rbuild[1]) + ')\n' - if not default_view: - default_view = url - links += link_buildlogs(package, eversion, suite, arch) + '
  • \n' - elif status not in ('untested', 'blacklisted') and not args.ignore_missing_files: + context['rbuild_uri'] = url + context['rbuild_size'] = sizeof_fmt(rbuild[1]) + default_view = default_view if default_view else url + context['buildlogs'] = get_buildlog_links_context(package, eversion, + suite, arch) + elif status not in ('untested', 'blacklisted') and \ + not args.ignore_missing_files: log.critical(DEBIAN_URL + '/' + suite + '/' + arch + '/' + package + ' didn\'t produce a buildlog, even though it has been built.') - default_view = '/untested.html' if not default_view else default_view - return (links, default_view) + context['has_buildloginfo'] = 'buildinfo_uri' in context or \ + 'buildlogs' in context or \ + 'rbuild_uri' in context -def gen_suites_links(package, current_suite, current_arch): - html = '\n' - return tab*5 + (tab*7).join(html.splitlines(True)) + package_uri = ('{}/{}/{}/{}.html').format(RB_PKG_URI, s, a, package.name) + + suitearch_details_html = '' + if (s == current_suite and a == current_arch): + suitearch_details_html, default_view = gen_suitearch_details( + package.name, version, s, a, status, spokenstatus, build_date) + + suites.append({ + 'status': status, + 'version': version, + 'build_date': build_date, + 'icon': icon, + 'spokenstatus': spokenstatus, + 'li_classes': ' '.join(li_classes), + 'arch': a, + 'suite': s, + 'untested': status == 'untested', + 'current_suitearch': s == current_suite and a == current_arch, + 'package_uri': package_uri, + 'suitearch_details_html': suitearch_details_html, + }) + + if len(suites): + context['architectures'].append({ + 'arch': a, + 'suites': suites, + }) + + html = renderer.render(suitearch_section_template, context) + return html, default_view def shorten_if_debiannet(hostname): if hostname[-11:] == '.debian.net': @@ -247,42 +247,45 @@ def gen_packages_html(packages, no_clean=False): assert isinstance(package, Package) gen_history_page(package) pkg = package.name + + notes_uri = '' + notes_file = NOTES_PATH + '/' + pkg + '_note.html' + if os.access(notes_file, os.R_OK): + notes_uri = NOTES_URI + '/' + pkg + '_note.html' + for suite in SUITES: for arch in ARCHS: + status = package.get_status(suite, arch) version = package.get_tested_version(suite, arch) build_date = package.get_build_date(suite, arch) - if build_date and status != 'blacklisted': - build_date = 'at ' + build_date - else: - build_date = '' if status == False: # the package is not in the checked suite continue log.debug('Generating the page of %s/%s/%s @ %s built at %s', pkg, suite, arch, version, build_date) - links, default_view = gen_extra_links( - pkg, version, suite, arch, status) - suites_links = gen_suites_links(package, suite, arch) - status, icon, spokenstatus = get_status_icon(status) - status = gen_status_link_icon(status, spokenstatus, icon, suite, arch) + suitearch_section_html, default_view = gen_suitearch_section( + package, suite, arch) + history = '{}/{}.html'.format(HISTORY_URI, pkg) project_links = html_project_links.substitute() - html = html_package_page.substitute( - package=pkg, - suite=suite, - arch=arch, - status=status, - version=version, - build_time=build_date, - history=history, - links=links, - notify_maintainer=package.notify_maint, - suites_links=suites_links, - project_links=project_links, - default_view=default_view) - destfile = RB_PKG_PATH + '/' + suite + '/' + arch + '/' + pkg + '.html' + html = renderer.render(package_page_template, { + 'package': pkg, + 'suite': suite, + 'arch': arch, + 'version': version, + 'history': history, + 'notes_uri': notes_uri, + 'notify_maintainer': package.notify_maint, + 'suitearch_section_html': suitearch_section_html, + 'project_links_html': project_links, + 'default_view': default_view, + 'dashboard_url': DEBIAN_URL, + }) + + destfile = RB_PKG_PATH + '/' + suite + '/' + arch + '/' + \ + pkg + '.html' desturl = REPRODUCIBLE_URL + RB_PKG_URI + '/' + suite + \ '/' + arch + '/' + pkg + '.html' title = pkg + ' - reproducible build results' diff --git a/bin/templates/package_page.mustache b/bin/templates/package_page.mustache new file mode 100644 index 00000000..059bffb0 --- /dev/null +++ b/bin/templates/package_page.mustache @@ -0,0 +1,44 @@ +
    +

    {{package}}

    + + +{{{project_links_html}}} +
    + diff --git a/bin/templates/package_suitearch_details.mustache b/bin/templates/package_suitearch_details.mustache new file mode 100644 index 00000000..685d6631 --- /dev/null +++ b/bin/templates/package_suitearch_details.mustache @@ -0,0 +1,36 @@ + diff --git a/bin/templates/package_suitearch_section.mustache b/bin/templates/package_suitearch_section.mustache new file mode 100644 index 00000000..ed29ba8f --- /dev/null +++ b/bin/templates/package_suitearch_section.mustache @@ -0,0 +1,30 @@ + diff --git a/bin/templates/status_icon_link.mustache b/bin/templates/status_icon_link.mustache new file mode 100644 index 00000000..2b866f7a --- /dev/null +++ b/bin/templates/status_icon_link.mustache @@ -0,0 +1,14 @@ +{{^untested}} +{{#icon}} + + {{spokenstatus}} + +{{/icon}} + + {{spokenstatus}} + +{{/untested}} + +{{#untested}} +{{#icon}}{{spokenstatus}}{{/icon}} {{spokenstatus}} +{{/untested}} diff --git a/update_jdn.sh b/update_jdn.sh index 2c52ff7f..3fa55599 100755 --- a/update_jdn.sh +++ b/update_jdn.sh @@ -328,6 +328,7 @@ if [ -f /etc/debian_version ] ; then python3-debian python3-xdg python3-yaml + python3-pystache python-arpy python-hachoir-metadata python-imaging -- cgit v1.2.3-70-g09d2