def gen_history_page(package, arch=None): keys = [ 'build date', 'version', 'suite', 'architecture', 'result', 'build duration', 'node1', 'node2', 'job' ] context = {} try: head = package.history[0] except IndexError: context['arch'] = arch else: context['keys'] = [{'key': key} for key in keys] rows = [] for r in package.history: # make a copy, since we modify in place record = dict(r) # skip records for other archs if we care about arch if arch and record['architecture'] != arch: continue # remove trailing .debian.net from hostnames record['node1'] = shorten_if_debiannet(record['node1']) record['node2'] = shorten_if_debiannet(record['node2']) # add icon to result status, icon, spokenstatus = get_status_icon(record['result']) result_html = spokenstatus + ' <img src="/static/{icon}" alt="{spokenstatus}" title="{spokenstatus}"/>' record['result'] = result_html.format(icon=icon, spokenstatus=spokenstatus) # human formatting of build duration record['build duration'] = convert_into_hms_string( int(record['build duration'])) row_items = [{'item': record[key]} for key in keys] rows.append({'row_items': row_items}) context['rows'] = rows html = renderer.render(package_history_template, context) if arch: destfile = os.path.join(HISTORY_PATH, arch, package.name + '.html') else: destfile = os.path.join(HISTORY_PATH, package.name + '.html') title = 'build history of {}'.format(package.name) if arch: title += ' on {}'.format(arch) write_html_page(title=title, body=html, destfile=destfile, noendpage=True)
def gen_html_issue(issue, suite): """ Given a issue as input (as a dict: {"issue_identifier": {"description": "blablabla", "url": "blabla"}} ) it returns the html body """ # links to the issue in other suites suite_links = '' for i in SUITES: if suite_links != '': suite_links += ' / ' if i != suite: suite_links += '<a href="' + REPRODUCIBLE_URL + ISSUES_URI + '/' + i + '/' + issue + '_issue.html">' + i + '</a>' else: suite_links += '<em>' + i + '</em>' # check for url: if 'url' in issues[issue]: url = issue_html_url.substitute(url=issues[issue]['url']) else: url = '' # add affected packages: affected = '' results = db_table('results') sources = db_table('sources') sql = select( [sources.c.name] ).select_from( results.join(sources) ).where( and_( sources.c.suite == bindparam('suite'), sources.c.architecture == bindparam('arch'), results.c.status == bindparam('status'), ) ).order_by( sources.c.name ) try: arch = 'amd64' for status in ['unreproducible', 'FTBFS', 'not for us', 'blacklisted', 'reproducible', 'depwait']: pkgs = query_db(sql.where(sources.c.name.in_(issues_count[issue]))\ .params({'suite': suite, 'arch': arch, 'status': status})) pkgs = [p[0] for p in pkgs] if not pkgs: continue affected += tab*4 + '<p>\n' affected += tab*5 + '<img src="/static/' + get_status_icon(status)[1] + '"' affected += ' alt="' + status + ' icon" />\n' affected += tab*5 + str(len(pkgs)) + ' ' + status + ' packages in ' + suite + '/' + arch +':\n' affected += tab*5 + '<code>\n' pkgs_popcon = issues_popcon_annotate(pkgs) try: for pkg, popcon, is_popular in sorted(pkgs_popcon, key=lambda x: x[0] in bugs): affected += tab*6 + Package(pkg).html_link(suite, arch, bugs, popcon, is_popular) except ValueError: pass affected += tab*5 + '</code>\n' affected += tab*4 + '</p>\n' except KeyError: # The note is not listed in any package, that is affected = '<i>None</i>' # check for description: try: desc = issues[issue]['description'] except KeyError: log.warning('You should really include a description in the ' + issue + ' issue') desc = 'N/A' desc = url2html.sub(r'<a href="\1">\1</a>', desc) desc = desc.replace('\n', '<br />') return issue_html.substitute(issue=issue, urls=url, description=desc, affected_pkgs=affected, suite=suite, suite_links=suite_links, notesgit_description=NOTESGIT_DESCRIPTION)
def build_leading_text_section(section, rows, suite, arch): html = '<p>\n' + tab total = len(rows) count_total = int( query_db(queries['count_total'].params({ 'suite': suite, 'arch': arch }))[0][0]) try: percent = round(((total / count_total) * 100), 1) except ZeroDivisionError: log.error('Looks like there are either no tested package or no ' + 'packages available at all. Maybe it\'s a new database?') percent = 0.0 try: html += '<a href="' + section['icon_link'] + '" target="_parent">' no_icon_link = False except KeyError: no_icon_link = True # to avoid closing the </a> tag below if section.get('icon_status'): html += '<img src="/static/' html += get_status_icon(section['icon_status'])[1] html += '" alt="reproducible icon" />' if not no_icon_link: html += '</a>' html += '\n' + tab if section.get('text') and section.get('timespan'): count = len( query_db(queries[section['query2']].params({ 'suite': suite, 'arch': arch }))) percent = round(((count / count_total) * 100), 1) timespan = section['timespan'] timespan_date = timespan_date_map[timespan] timespan_count = int( query_db(queries['count_timespan'].params({ 'suite': suite, 'arch': arch, 'timespan_date': timespan_date }))[0][0]) try: timespan_percent = round(((total / timespan_count) * 100), 1) except ZeroDivisionError: log.error('Looks like there are either no tested package or no ' + 'packages available at all. Maybe it\'s a new database?') timespan_percent = 0 html += section['text'].substitute(tot=total, percent=percent, timespan_percent=timespan_percent, timespan_count=timespan_count, count_total=count_total, count=count, suite=suite, arch=arch) elif section.get('text'): html += section['text'].substitute(tot=total, percent=percent, suite=suite, arch=arch) else: log.warning('There is no text for this section') html += '\n</p>\n' return html
def create_pkgset_page_and_graphs(suite, arch, stats, pkgset_name): html_body = "" html_body += create_pkgset_navigation(suite, arch, pkgset_name) pkgset_context = ({ 'pkgset_name': pkgset_name, 'suite': suite, 'arch': arch, 'pkg_symbol_legend_html': renderer.render(pkg_legend_template, {}), }) png_file, png_href = stats_png_file_href(suite, arch, pkgset_name) thumb_file, thumb_href = stats_thumb_file_href(suite, arch, pkgset_name) yesterday_timestamp = (datetime.now() - timedelta(days=1)).timestamp() if (not os.access(png_file, os.R_OK) or os.stat(png_file).st_mtime < yesterday_timestamp): create_pkgset_graph(png_file, suite, arch, pkgset_name) check_call( ['convert', png_file, '-adaptive-resize', '160x80', thumb_file]) pkgset_context['png'] = png_href other_archs = [a for a in ARCHS if a != arch] pkgset_context['other_archs']= \ gen_other_arch_context(other_archs, suite, pkgset_name) pkgset_context['status_details'] = [] status_cutename_descriptions = [ ('unreproducible', 'bad', 'failed to build reproducibly'), ('FTBFS', 'ugly', 'failed to build from source'), ('rest', 'rest', 'are either in depwait state, blacklisted, not for us, or cannot be downloaded' ), ('reproducible', 'good', 'successfully build reproducibly'), ] for (status, cutename, description) in status_cutename_descriptions: icon_html = '' if status == 'rest': for s in ['depwait', 'blacklisted', 'not_for_us', '404']: s, icon, spokenstatus = get_status_icon(s) icon_html += gen_status_link_icon(s, None, icon, suite, arch) else: status, icon, spokenstatus = get_status_icon(status) icon_html = gen_status_link_icon(status, None, icon, suite, arch) details_context = { 'icon_html': icon_html, 'description': description, 'package_list_html': ''.join( [Package(x).html_link(suite, arch) for x in stats[cutename]]), 'status_count': stats["count_" + cutename], 'status_percent': stats["percent_" + cutename], } if (status in ('reproducible', 'unreproducible') or stats["count_" + cutename] != 0): pkgset_context['status_details'].append(details_context) html_body += renderer.render(pkgset_details_template, pkgset_context) title = '%s package set for %s/%s' % \ (pkgset_name, suite, arch) page = "pkg_set_" + pkgset_name + ".html" destfile = os.path.join(DISTRO_BASE, suite, arch, page) suite_arch_nav_template = DISTRO_URI + '/{{suite}}/{{arch}}/' + page left_nav_html = create_main_navigation( suite=suite, arch=arch, displayed_page='pkg_set', suite_arch_nav_template=suite_arch_nav_template, ignore_experimental=True, ) log.info("Creating meta pkgset page for %s in %s/%s.", pkgset_name, suite, arch) write_html_page(title=title, body=html_body, destfile=destfile, left_nav_html=left_nav_html)
def gen_suitearch_section(package, current_suite, current_arch): # keep track of whether the package is entirely reproducible final_version = '' final_status = '' default_view = '' context = {} context['architectures'] = [] for a in ARCHS: suites = [] for s in SUITES: status = package.builds[s][a].status if not status: # The package is not available in that suite/arch continue version = package.builds[s][a].version if not final_version or not final_status: final_version = version final_status = status else: final_status, final_version = determine_reproducibility( final_status, final_version, status, version) build_date = package.builds[s][a].build_date status, icon, spokenstatus = get_status_icon(status) if not (build_date and status != 'blacklisted'): build_date = '' li_classes = ['suite'] if s == current_suite and a == current_arch: li_classes.append('active') 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) dbd_links = get_dbd_links(package.name, strip_epoch(version), s, a) dbd_page_uri = dbd_links.get('dbd_page_uri', '') suites.append({ 'package': package.name, '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, 'dbd_page_uri': dbd_page_uri }) if len(suites): context['architectures'].append({ 'arch': a, 'suites': suites, }) html = renderer.render(suitearch_section_template, context) reproducible = True if final_status == 'reproducible' else False return html, default_view, reproducible
def convert_into_status_html(status): if status != 'None': status, icon, spokenstatus = get_status_icon(status) return status + ' <img src="/static/' + icon + '" alt="' + status + '" title="' + status + '"/>' else: return ''