Allow to unset assignee/milestone for bug with no activity
Change-Id: I4ae13aa647ad43463c241ca8b82bba50aa3581f1
This commit is contained in:
parent
913bd18114
commit
9015a1e2c9
25
README.rst
25
README.rst
|
@ -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
|
||||
---------------
|
||||
|
|
|
@ -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)
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue