コード例 #1
0
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)
コード例 #2
0
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)
コード例 #3
0
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
コード例 #4
0
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)
コード例 #5
0
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
コード例 #6
0
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 ''