From 7e80d47eb6a76dd81cc41ae06780320ca3a54e19 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Lallement Date: Tue, 29 Apr 2014 23:38:45 +0200 Subject: [PATCH] autopkgtest.py: - A test for a package/version can be triggered by several distincts causes with different results. Modify the data structure to store this instead of only storing the last cause and result, leading to missing test results in excuses. - Check if failures are regressions (there is at least one pass and migration is blocked) or if test has always been failing. In the latter case, migration is not blocked. - Add colours to excuses.html to distinguishes the test results - Point jenkins URL to lastBuild --- autopkgtest.py | 78 +++++++++++++++++++++++++++++--------------------- britney.py | 13 +++++---- 2 files changed, 54 insertions(+), 37 deletions(-) diff --git a/autopkgtest.py b/autopkgtest.py index 5dd2445..75371e0 100644 --- a/autopkgtest.py +++ b/autopkgtest.py @@ -19,18 +19,24 @@ from __future__ import print_function from collections import defaultdict from contextlib import closing -import logging import os import subprocess import tempfile from textwrap import dedent import time - import apt_pkg adt_britney = os.path.expanduser("~/auto-package-testing/jenkins/adt-britney") +ADT_PASS = ["PASS", "ALWAYSFAIL"] +ADT_EXCUSES_LABELS = { + "PASS": 'Pass', + "ALWAYSFAIL": 'Always failed', + "REGRESSION": 'Regression', + "RUNNING": 'Test in progress', +} + class AutoPackageTest(object): """autopkgtest integration @@ -62,7 +68,7 @@ class AutoPackageTest(object): components: main restricted universe multiverse rsync_host: rsync://tachash.ubuntu-ci/adt/ datadir: ~/proposed-migration/autopkgtest/data""" % - (self.series, self.series, home)), file=rc_file) + (self.series, self.series, home)), file=rc_file) @property def _request_path(self): @@ -85,8 +91,7 @@ class AutoPackageTest(object): continue linebits = line.split() if len(linebits) < 2: - logging.warning( - "Invalid line format: '%s', skipped" % line) + print("W: Invalid line format: '%s', skipped" % line) continue yield linebits @@ -94,29 +99,21 @@ class AutoPackageTest(object): self.pkglist = defaultdict(dict) self.pkgcauses = defaultdict(lambda: defaultdict(list)) for linebits in self._parse(self._result_path): - src = linebits.pop(0) - ver = linebits.pop(0) - self.pkglist[src][ver] = { - "status": "NEW", - "causes": {}, + (src, ver, status) = linebits[:3] + + if not (src in self.pkglist and ver in self.pkglist[src]): + self.pkglist[src][ver] = { + "status": status, + "causes": {} } - try: - status = linebits.pop(0).upper() - self.pkglist[src][ver]["status"] = status - while True: - trigsrc = linebits.pop(0) - trigver = linebits.pop(0) - self.pkglist[src][ver]["causes"][trigsrc] = trigver - except IndexError: - # End of the list - pass - for src in self.pkglist: - all_vers = sorted(self.pkglist[src], cmp=apt_pkg.version_compare) - for ver in self.pkglist[src]: - status = self.pkglist[src][ver]["status"] - for trigsrc, trigver in \ - self.pkglist[src][ver]["causes"].items(): - self.pkgcauses[trigsrc][trigver].append((status, src, ver)) + + i = iter(linebits[3:]) + for trigsrc, trigver in zip(i, i): + if not trigsrc in self.pkglist[src][ver]['causes']: + self.pkglist[src][ver]['causes'][trigsrc] = [] + self.pkglist[src][ver]['causes'][trigsrc].append((trigver, + status)) + self.pkgcauses[trigsrc][trigver].append((status, src, ver)) def _adt_britney(self, *args): command = [ @@ -197,12 +194,29 @@ class AutoPackageTest(object): self.read() if self.britney.options.verbose: for src in sorted(self.pkglist): - for ver in self.pkglist[src]: - print("I: [%s] - Collected autopkgtest status for %s_%s: " - "%s" % - (time.asctime(), src, ver, - self.pkglist[src][ver]["status"])) + for ver in sorted(self.pkglist[src], + cmp=apt_pkg.version_compare): + for trigsrc in sorted(self.pkglist[src][ver]['causes']): + for trigver, status \ + in self.pkglist[src][ver]['causes'][trigsrc]: + print("I: [%s] - Collected autopkgtest status " + "for %s_%s/%s_%s: " "%s" % ( + time.asctime(), src, ver, trigsrc, + trigver, status)) def results(self, trigsrc, trigver): for status, src, ver in self.pkgcauses[trigsrc][trigver]: + # Check for regresssion + if status == 'FAIL': + passed_once = False + for ver in self.pkglist[src]: + for trigsrc in self.pkglist[src][ver]['causes']: + for trigver, status \ + in self.pkglist[src][ver]['causes'][trigsrc]: + if status == 'PASS': + passed_once = True + if not passed_once: + status = 'ALWAYSFAIL' + else: + status = 'REGRESSION' yield status, src, ver diff --git a/britney.py b/britney.py index 683822e..648eb57 100755 --- a/britney.py +++ b/britney.py @@ -222,7 +222,7 @@ from britney_util import (old_libraries_format, same_source, undo_changes, from consts import (VERSION, SECTION, BINARIES, MAINTAINER, FAKESRC, SOURCE, SOURCEVER, ARCHITECTURE, DEPENDS, CONFLICTS, PROVIDES, RDEPENDS, RCONFLICTS, MULTIARCH) -from autopkgtest import AutoPackageTest +from autopkgtest import AutoPackageTest, ADT_PASS, ADT_EXCUSES_LABELS __author__ = 'Fabio Tranchitella and the Debian Release Team' __version__ = '2.0' @@ -1756,18 +1756,21 @@ class Britney(object): adtpass = True for status, adtsrc, adtver in autopkgtest.results( e.name, e.ver[1]): - public_url = "%s/%s-adt-%s/" % ( + public_url = "%s/%s-adt-%s/lastBuild" % ( jenkins_public, self.options.adt_series, adtsrc.replace("+", "-")) - private_url = "%s/%s-adt-%s/" % ( + private_url = "%s/%s-adt-%s/lastBuild" % ( jenkins_private, self.options.adt_series, adtsrc.replace("+", "-")) + adt_label = status + if status in ADT_EXCUSES_LABELS: + adt_label = ADT_EXCUSES_LABELS[status] e.addhtml( "autopkgtest for %s %s: %s (Jenkins: " "public, " "private)" % - (adtsrc, adtver, status, public_url, private_url)) - if status != "PASS": + (adtsrc, adtver, adt_label, public_url, private_url)) + if status not in ADT_PASS: hints = self.hints.search( 'force-badtest', package=adtsrc) hints.extend(