Allow to unset assignee/milestone for bug with no activity

Change-Id: I4ae13aa647ad43463c241ca8b82bba50aa3581f1
This commit is contained in:
cedric.brandily 2015-10-02 16:05:33 +00:00 committed by Cedric Brandily
parent 913bd18114
commit 9015a1e2c9
3 changed files with 138 additions and 0 deletions

View File

@ -341,6 +341,31 @@ Example:
Check content differences between nova-stable-kilo.tar.gz and
nova-2015.1.0rc1.tar.gz, as found on http://tarballs.openstack.org.
pre_expire.by
-------------
This script fetches opened bugs for a project in order to prepare bugs with no
activity in the last D days for expiration by:
- unsetting bug assignee
- unsetting bug milestone
- setting bug status to Incomplete
- adding a comment explaining why we updated the bug
Examples:
./pre_expire_bugs.py neutron --days 180
Prepare for expiration neutron bugs with no activity not updated in the last
180 days.
./pre_expire_bugs.py glance --days 365 --test
Test prepare for expiration on Launchpad Staging servers.
./pre_expire_bugs.py glance --days 365 --dry-run
Prepare for expiration dry-run: print actions without executing them.
process_bugs.py
---------------

111
pre_expire_bugs.py Executable file
View File

@ -0,0 +1,111 @@
#!/usr/bin/env python
#
# Script to prepare bugs with no activity for expiration
#
# Copyright (c) 2015 Thales Services SAS
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from __future__ import print_function
from argparse import ArgumentParser
import datetime
from launchpadlib.launchpad import Launchpad
from lazr.restfulclient.errors import ServerError
import pytz
# Parameters
parser = ArgumentParser(
description="Unset assignee/milestone for bugs with no activity in bulk")
parser.add_argument('projectname', help='The project to act on')
parser.add_argument("--test", action='store_const', const='staging',
default='production', help='Use LP staging server to test')
parser.add_argument("--dry-run", action='store_true',
help="Don't actually perform any action")
parser.add_argument("--days", type=int, default=365,
help='days without activity (default: %(default)s days)')
parser.add_argument('exceptions', type=int, nargs='*', help='Bugs to ignore')
args = parser.parse_args()
# Connect to Launchpad
print("Connecting to Launchpad...")
launchpad = Launchpad.login_with('openstack-prepare-expire', args.test)
# Retrieve bugs
print("Retrieving project...")
proj = launchpad.projects[args.projectname]
failed = set()
modified_before = (
datetime.datetime.now(pytz.UTC) - datetime.timedelta(days=args.days))
# Get bugtasks, older first
open_statuses = ['New', 'Incomplete', 'Confirmed', 'Triaged', 'In Progress']
bugtasks = proj.searchTasks(
order_by='date_last_updated', status=open_statuses)
# Process bugs
content = (
"This bug is > %s days without activity. We are unsetting assignee "
"and milestone and setting status to Incomplete in order to allow "
"its expiry in 60 days.\n\n"
"If the bug is still valid, then update the bug status.") % args.days
for bugtask in bugtasks:
bug = bugtask.bug
# Process bugs with no activity after modified_before
if bug.date_last_updated > modified_before:
break
# Skip bugs which triggered timeouts in previous runs
if bug.id in failed:
continue
print(bug.id, end='')
if bug.id in args.exceptions:
print(" - excepted")
continue
if bugtask.assignee:
bugtask.assignee = None
print(" - unset assignee", end='')
if bugtask.milestone:
bugtask.milestone = None
print(" - unset milestone", end='')
if bugtask.status != 'Incomplete':
bugtask.status = 'Incomplete'
print(" - set status Incomplete", end='')
if not args.dry_run:
try:
bugtask.lp_save()
bug.lp_save()
bug.newMessage(content=content)
print(" - DONE!", end='')
except ServerError:
print(" - TIMEOUT!", end='')
failed.add(bug.id)
except Exception as e:
print(" - ERROR! (%s)" % e, end='')
failed.add(bug.id)
print()
if failed:
print()
print("Some bugs could not be automatically updated due to LP timeouts:")
for bugid in failed:
print("http://bugs.launchpad.net/bugs/%d" % bugid)

View File

@ -5,6 +5,8 @@ requests>=1.1
Jinja2>=2.6 # BSD License (3 clause)
oslo.concurrency>=1.4.1 # Apache-2.0
parawrap
# 2013.6 is the first version of pytz that is PEP 440 compatible.
pytz>=2013.6
PyYAML>=3.1.0
zuul
simplejson>=2.2.0