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)
|