You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
179 lines
6.7 KiB
179 lines
6.7 KiB
#!/usr/bin/python2.7
|
|
|
|
# Copyright (C) 2015 Brian Murray <brian.murray@canonical.com>
|
|
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; version 3 of the License.
|
|
#
|
|
# This program 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 General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
'''Remove an SRU fom the -proposed pocket for a release.
|
|
|
|
Remove a package from the -proposed pocket for a release of Ubuntu and comment
|
|
on bug reports regarding the removal of the package giving an explanation that
|
|
it was removed to due a failure for the SRU bug(s) to be verified in a timely
|
|
fashion.
|
|
|
|
USAGE:
|
|
sru-remove -s trusty -p homerun 12345
|
|
'''
|
|
|
|
from __future__ import print_function
|
|
|
|
import optparse
|
|
import re
|
|
import subprocess
|
|
import sys
|
|
|
|
from launchpadlib.launchpad import Launchpad
|
|
|
|
|
|
def parse_options():
|
|
'''Parse command line arguments.
|
|
|
|
Return (options, [bugs]) tuple.
|
|
'''
|
|
|
|
parser = optparse.OptionParser(
|
|
usage='Usage: %prog [options]')
|
|
parser.add_option(
|
|
"-l", "--launchpad", dest="launchpad_instance", default="production")
|
|
parser.add_option(
|
|
"-s", dest="release", default=default_release, metavar="RELEASE",
|
|
help="release (default: %s)" % default_release)
|
|
parser.add_option(
|
|
"-p", "--package", dest="sourcepkg")
|
|
parser.add_option(
|
|
"--reason", dest="reason", default="ancient",
|
|
help="reason for removal: ancient, failed (default: ancient)")
|
|
|
|
opts, args = parser.parse_args()
|
|
|
|
if opts.reason not in ('ancient', 'failed'):
|
|
parser.error('Reason can only be "ancient" or "failed".')
|
|
|
|
return (opts, args)
|
|
|
|
|
|
def process_bug(launchpad, distroseries, sourcepkg, num, reason):
|
|
bug_target_re = re.compile(
|
|
r'/ubuntu/(?:(?P<suite>[^/]+)/)?\+source/(?P<source>[^/]+)$')
|
|
bug = launchpad.bugs[num]
|
|
series_name = distroseries.name
|
|
open_task = False
|
|
|
|
for task in bug.bug_tasks:
|
|
# Ugly; we have to do URL-parsing to figure this out.
|
|
# /ubuntu/+source/foo can be fed to launchpad.load() to get a
|
|
# distribution_source_package, but /ubuntu/hardy/+source/foo can't.
|
|
match = bug_target_re.search(task.target.self_link)
|
|
if (not match or
|
|
(sourcepkg and
|
|
match.group('source') != sourcepkg)):
|
|
print("Ignoring task %s in bug %s" % (task.web_link, num))
|
|
continue
|
|
if (match.group('suite') != series_name and
|
|
match.group('suite') in supported_series and
|
|
task.status == "Fix Committed"):
|
|
open_task = True
|
|
if (match.group('suite') == series_name and
|
|
task.status == "Fix Committed"):
|
|
task.status = "Won't Fix"
|
|
task.lp_save()
|
|
print("Success: task %s in bug %s" % (task.web_link, num))
|
|
btags = bug.tags
|
|
series_v_needed = 'verification-needed-%s' % series_name
|
|
if series_v_needed in btags:
|
|
# this dance is needed due to
|
|
# https://bugs.launchpad.net/launchpadlib/+bug/254901
|
|
tags = btags
|
|
tags.remove(series_v_needed)
|
|
bug.tags = tags
|
|
bug.lp_save()
|
|
|
|
if reason == 'failed':
|
|
text = ('The version of %s in the proposed pocket of %s that was '
|
|
'purported to fix this bug report has been removed '
|
|
'because one or more bugs that were to be fixed by the '
|
|
'upload have failed verification and been in this state '
|
|
'for more than 10 days.' %
|
|
(sourcepkg, series_name.title()))
|
|
else: # 'ancient'
|
|
text = ('The version of %s in the proposed pocket of %s that was '
|
|
'purported to fix this bug report has been removed '
|
|
'because the bugs that were to be fixed by the upload '
|
|
'were not verified in a timely (105 days) fashion.' %
|
|
(sourcepkg, series_name.title()))
|
|
bug.newMessage(content=text,
|
|
subject='Proposed package removed from archive')
|
|
|
|
# remove verification-needed tag if there are no open tasks
|
|
if open_task:
|
|
return
|
|
# only unsubscribe the teams if there are no open tasks left
|
|
bug.unsubscribe(person=launchpad.people['ubuntu-sru'])
|
|
bug.unsubscribe(person=launchpad.people['sru-verification'])
|
|
if 'verification-needed' in btags:
|
|
# this dance is needed due to
|
|
# https://bugs.launchpad.net/launchpadlib/+bug/254901
|
|
tags = btags
|
|
tags.remove('verification-needed')
|
|
bug.tags = tags
|
|
bug.lp_save()
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
default_release = 'focal'
|
|
|
|
(opts, bugs) = parse_options()
|
|
|
|
if opts.reason == 'failed':
|
|
removal_comment = ('The package was removed due to one or more of '
|
|
'its SRU bugs having failed verification.')
|
|
else: # 'ancient'
|
|
removal_comment = ('The package was removed due to its SRU bug(s) '
|
|
'not being verified in a timely fashion.')
|
|
|
|
launchpad = Launchpad.login_with('sru-remove', opts.launchpad_instance,
|
|
version="devel")
|
|
ubuntu = launchpad.distributions['ubuntu']
|
|
# determine series for which we issue SRUs
|
|
supported_series = []
|
|
for serie in ubuntu.series:
|
|
if serie.supported:
|
|
supported_series.append(serie.name)
|
|
|
|
series = ubuntu.getSeries(name_or_version=opts.release)
|
|
archive = ubuntu.main_archive
|
|
|
|
existing = [
|
|
pkg for pkg in archive.getPublishedSources(
|
|
exact_match=True, distro_series=series, pocket='Proposed',
|
|
source_name=opts.sourcepkg, status='Published')]
|
|
|
|
if not existing:
|
|
print("ERROR: %s was not found in -proposed for release %s." %
|
|
(opts.sourcepkg, opts.release), file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
rm_p_cmd = ["remove-package", "-m", removal_comment, "-y",
|
|
"-l", opts.launchpad_instance, "-s",
|
|
"%s-proposed" % opts.release, opts.sourcepkg]
|
|
ret = subprocess.call(rm_p_cmd)
|
|
if ret != 0:
|
|
print("ERROR: There was an error removing %s from %s-proposed.\n"
|
|
"The remove-package command returned %s." %
|
|
(opts.sourcepkg, opts.release, ret), file=sys.stderr)
|
|
sys.exit(1)
|
|
# only comment on the bugs after removing the package
|
|
for bug in bugs:
|
|
process_bug(launchpad, series, opts.sourcepkg, bug, opts.reason)
|