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
127
128
129
130
|
#!/usr/bin/python3
# Generate a list of autopkgtest request.cgi URLs to
# re-run all autopkgtests which regressed
# 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 = 'bionic'
args = None
def parse_args():
parser = argparse.ArgumentParser(
'Generate %s URLs to re-run regressions' % request_url,
formatter_class=argparse.RawDescriptionHelpFormatter,
description='''Typical workflow:
- export autopkgtest.ubuntu.com session cookie into ~/.cache/autopkgtest.cookie
Use a browser plugin or get the value from the settings and create it with
printf "autopkgtest.ubuntu.com\\tTRUE\\t/\\tTRUE\\t0\\tsession\\tVALUE\\n" > ~/.cache/autopkgtest.cookie
(The cookie is valid for one month)
- retry-autopkgtest-regressions [opts...] | vipe | xargs -rn1 -P10 wget --load-cookies ~/.cache/autopkgtest.cookie -O-
edit URL list to pick/remove requests as desired, then close editor to let it run
''')
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 → pkg → arch → [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('policy_info', {}).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(
pkg, {}).setdefault(arch, []).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 + '/v2/ticket/%s' % args.bileto
excuses_url = None
with urllib.request.urlopen(ticket_url) as f:
ticket = json.loads(f.read().decode('utf-8'))['tickets'][0]
ppa_name = ticket.get('ppa', '')
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, pkgmap in regressions.items():
for pkg, archmap in pkgmap.items():
for arch, triggers in archmap.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)
|