~xnox/ubuntu-archive-tools/built-using

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#!/usr/bin/python3
# Generate a list of autopkgtest request.cgi URLs to
# re-run all autopkgtests which regressed
# Typical usage:
# - retry-autopkgtest-regressions [opts...] | vipe | xargs -n1 xdg-open
# - edit URL list to pick/remove requests as desired
# - click on the first link, log into SSO if necessary; delete it
# - close the editor to let the remaining links get opened in the default browser

# Copyright (C) 2015-2016 Canonical Ltd.
# Author: Martin Pitt <martin.pitt@ubuntu.com>

# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.

# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.

# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
# USA

import urllib.request
import urllib.parse
import argparse
import yaml
import json

request_url = 'https://autopkgtest.ubuntu.com/request.cgi'
default_series = 'yakkety'
args = None


def parse_args():
    parser = argparse.ArgumentParser(
        'Generate %s URLs to re-run regressions' % request_url)
    parser.add_argument('-s', '--series', default=default_series,
                        help='Ubuntu series (default: %(default)s)')
    parser.add_argument('--bileto', metavar='TICKETNUMBER',
                        help='Run for bileto ticket')
    parser.add_argument('--all-proposed', action='store_true',
                        help='run tests against all of proposed, i. e. with disabling apt pinning')
    parser.add_argument('--state', default='REGRESSION',
                        help='generate commands for given test state (default: %(default)s)')
    parser.add_argument('--max-age', type=float, metavar='DAYS',
                        help='only consider candiates which are at most '
                        'this number of days old (float allowed)')
    parser.add_argument('--min-age', type=float, metavar='DAYS',
                        help='only consider candiates which are at least '
                        'this number of days old (float allowed)')
    args = parser.parse_args()

    return args


def get_regressions(excuses_url, release, retry_state, min_age, max_age):
    '''Return dictionary with regressions

    Return dict: release → arch → pkg → [trigger, ...]
    '''
    # load YAML excuses
    with urllib.request.urlopen(excuses_url) as f:
        excuses = yaml.load(f)
    regressions = {}
    for excuse in excuses['sources']:
        try:
            age = excuse['policy_info']['age']['current-age']
        except KeyError:
            age = None

        # excuses are sorted by ascending age
        if min_age is not None and age is not None and age < min_age:
            continue
        if max_age is not None and age is not None and age > max_age:
            break
        for pkg, archinfo in excuse.get('tests', {}).get('autopkgtest', {}).items():
            pkg = pkg.split('/')[0].split()[0]  # strip off version (either / or space separated)
            trigger = excuse['source'] + '/' + excuse['new-version']
            for arch, state in archinfo.items():
                if state[0] == retry_state:
                    regressions.setdefault(release, {}).setdefault(
                        arch, {}).setdefault(pkg, []).append(trigger)

    return regressions


args = parse_args()

extra_params = []
if args.all_proposed:
    extra_params.append(('all-proposed', '1'))

if args.bileto:
    url_root = 'https://bileto.ubuntu.com'
    ticket_url = url_root + '/v1/ticket/%s' % args.bileto
    excuses_url = None
    with urllib.request.urlopen(ticket_url) as f:
        ticket = json.loads(f.read().decode('utf-8'))['requests'][0]
    ppa_name = ticket.get('siloname', '').split('/')[-1]
    for line in ticket.get('autopkgtest', '').splitlines():
        if args.series in line:
            excuses_url = line
            break
    if excuses_url.startswith('/'):
        excuses_url = url_root + excuses_url
    excuses_url = excuses_url.replace('.html', '.yaml')
    extra_params += [('ppa', 'ci-train-ppa-service/stable-phone-overlay'),
                     ('ppa', 'ci-train-ppa-service/%s ' % ppa_name)]
else:
    excuses_url = 'http://people.canonical.com/~ubuntu-archive/proposed-migration/%s/update_excuses.yaml' % args.series
regressions = get_regressions(excuses_url, args.series, args.state,
                              args.min_age, args.max_age)

for release, archmap in regressions.items():
    for arch, pkgmap in archmap.items():
        for pkg, triggers in pkgmap.items():
            params = [('release', release), ('arch', arch), ('package', pkg)]
            params += [('trigger', t) for t in triggers]
            params += extra_params
            url = request_url + '?' + urllib.parse.urlencode(params)
            print(url)