Remove abandon_stale.py
Remove the file which was added the gerrit-release-tools project with change Ifaa5d12ce. Change-Id: Ie2fafa3e476fe74c9c3bdaccd1be329f78f4b2c2
This commit is contained in:
@@ -1,225 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# The MIT License
|
||||
#
|
||||
# Copyright 2014 Sony Mobile Communications. All rights reserved.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
|
||||
""" Script to abandon stale changes from the review server.
|
||||
|
||||
Fetches a list of open changes that have not been updated since a given age in
|
||||
days, months or years (default 6 months), and then abandons them.
|
||||
|
||||
Requires the user's credentials for the Gerrit server to be declared in the
|
||||
.netrc file. Supports either basic or digest authentication.
|
||||
|
||||
Example to abandon changes that have not been updated for 3 months:
|
||||
|
||||
./abandon_stale --gerrit-url http://review.example.com/ --age 3months
|
||||
|
||||
Supports dry-run mode to only list the stale changes, but not actually
|
||||
abandon them.
|
||||
|
||||
See the --help output for more information about options.
|
||||
|
||||
Requires pygerrit2 (https://github.com/dpursehouse/pygerrit2) to be installed
|
||||
and available for import.
|
||||
|
||||
"""
|
||||
|
||||
import logging
|
||||
import optparse
|
||||
import re
|
||||
import sys
|
||||
|
||||
from pygerrit2.rest import GerritRestAPI
|
||||
from pygerrit2.rest.auth import HTTPBasicAuthFromNetrc, HTTPDigestAuthFromNetrc
|
||||
|
||||
|
||||
def _main():
|
||||
parser = optparse.OptionParser()
|
||||
parser.add_option('-g', '--gerrit-url', dest='gerrit_url',
|
||||
metavar='URL',
|
||||
default=None,
|
||||
help='gerrit server URL')
|
||||
parser.add_option('-b', '--basic-auth', dest='basic_auth',
|
||||
action='store_true',
|
||||
help='(deprecated) use HTTP basic authentication instead'
|
||||
' of digest')
|
||||
parser.add_option('-d', '--digest-auth', dest='digest_auth',
|
||||
action='store_true',
|
||||
help='use HTTP digest authentication instead of basic')
|
||||
parser.add_option('-n', '--dry-run', dest='dry_run',
|
||||
action='store_true',
|
||||
help='enable dry-run mode: show stale changes but do '
|
||||
'not abandon them')
|
||||
parser.add_option('-t', '--test', dest='testmode', action='store_true',
|
||||
help='test mode: query changes with the `test-abandon` '
|
||||
'topic and ignore age option')
|
||||
parser.add_option('-a', '--age', dest='age',
|
||||
metavar='AGE',
|
||||
default="6months",
|
||||
help='age of change since last update in days, months'
|
||||
' or years (default: %default)')
|
||||
parser.add_option('-m', '--message', dest='message',
|
||||
metavar='STRING', default=None,
|
||||
help='custom message to append to abandon message')
|
||||
parser.add_option('--branch', dest='branches', metavar='BRANCH_NAME',
|
||||
default=[], action='append',
|
||||
help='abandon changes only on the given branch')
|
||||
parser.add_option('--exclude-branch', dest='exclude_branches',
|
||||
metavar='BRANCH_NAME',
|
||||
default=[],
|
||||
action='append',
|
||||
help='do not abandon changes on given branch')
|
||||
parser.add_option('--project', dest='projects', metavar='PROJECT_NAME',
|
||||
default=[], action='append',
|
||||
help='abandon changes only on the given project')
|
||||
parser.add_option('--exclude-project', dest='exclude_projects',
|
||||
metavar='PROJECT_NAME',
|
||||
default=[],
|
||||
action='append',
|
||||
help='do not abandon changes on given project')
|
||||
parser.add_option('--owner', dest='owner',
|
||||
metavar='USERNAME',
|
||||
default=None,
|
||||
action='store',
|
||||
help='only abandon changes owned by the given user')
|
||||
parser.add_option('--exclude-wip', dest='exclude_wip',
|
||||
action='store_true',
|
||||
help='Exclude changes that are Work-in-Progress')
|
||||
parser.add_option('-v', '--verbose', dest='verbose',
|
||||
action='store_true',
|
||||
help='enable verbose (debug) logging')
|
||||
|
||||
(options, _args) = parser.parse_args()
|
||||
|
||||
level = logging.DEBUG if options.verbose else logging.INFO
|
||||
logging.basicConfig(format='%(asctime)s %(levelname)s %(message)s',
|
||||
level=level)
|
||||
|
||||
if not options.gerrit_url:
|
||||
logging.error("Gerrit URL is required")
|
||||
return 1
|
||||
|
||||
if options.testmode:
|
||||
message = "Abandoning in test mode"
|
||||
else:
|
||||
pattern = re.compile(r"^([\d]+)(month[s]?|year[s]?|week[s]?)")
|
||||
match = pattern.match(options.age)
|
||||
if not match:
|
||||
logging.error("Invalid age: %s", options.age)
|
||||
return 1
|
||||
message = "Abandoning after %s %s or more of inactivity." % \
|
||||
(match.group(1), match.group(2))
|
||||
|
||||
if options.digest_auth:
|
||||
auth_type = HTTPDigestAuthFromNetrc
|
||||
else:
|
||||
auth_type = HTTPBasicAuthFromNetrc
|
||||
|
||||
try:
|
||||
auth = auth_type(url=options.gerrit_url)
|
||||
gerrit = GerritRestAPI(url=options.gerrit_url, auth=auth)
|
||||
except Exception as e:
|
||||
logging.error(e)
|
||||
return 1
|
||||
|
||||
logging.info(message)
|
||||
try:
|
||||
stale_changes = []
|
||||
offset = 0
|
||||
step = 500
|
||||
if options.testmode:
|
||||
query_terms = ["status:new", "owner:self", "topic:test-abandon"]
|
||||
else:
|
||||
query_terms = ["status:new", "age:%s" % options.age]
|
||||
if options.exclude_wip:
|
||||
query_terms += ["-is:wip"]
|
||||
if options.branches:
|
||||
query_terms += ["branch:%s" % b for b in options.branches]
|
||||
elif options.exclude_branches:
|
||||
query_terms += ["-branch:%s" % b for b in options.exclude_branches]
|
||||
if options.projects:
|
||||
query_terms += ["project:%s" % p for p in options.projects]
|
||||
elif options.exclude_projects:
|
||||
query_terms = ["-project:%s" % p for p in options.exclude_projects]
|
||||
if options.owner and not options.testmode:
|
||||
query_terms += ["owner:%s" % options.owner]
|
||||
query = "%20".join(query_terms)
|
||||
while True:
|
||||
q = query + "&o=DETAILED_ACCOUNTS&n=%d&S=%d" % (step, offset)
|
||||
logging.debug("Query: %s", q)
|
||||
url = "/changes/?q=" + q
|
||||
result = gerrit.get(url)
|
||||
logging.debug("%d changes", len(result))
|
||||
if not result:
|
||||
break
|
||||
stale_changes += result
|
||||
last = result[-1]
|
||||
if "_more_changes" in last:
|
||||
logging.debug("More...")
|
||||
offset += step
|
||||
else:
|
||||
break
|
||||
except Exception as e:
|
||||
logging.error(e)
|
||||
return 1
|
||||
|
||||
abandoned = 0
|
||||
errors = 0
|
||||
abandon_message = message
|
||||
if options.message:
|
||||
abandon_message += "\n\n" + options.message
|
||||
for change in stale_changes:
|
||||
number = change["_number"]
|
||||
project = ""
|
||||
if len(options.projects) != 1:
|
||||
project = "%s: " % change["project"]
|
||||
owner = ""
|
||||
if options.verbose:
|
||||
try:
|
||||
o = change["owner"]["name"]
|
||||
except KeyError:
|
||||
o = "Unknown"
|
||||
owner = " (%s)" % o
|
||||
subject = change["subject"]
|
||||
if len(subject) > 70:
|
||||
subject = subject[:65] + " [...]"
|
||||
change_id = change["id"]
|
||||
logging.info("%s%s: %s%s", number, owner, project, subject)
|
||||
if options.dry_run:
|
||||
continue
|
||||
|
||||
try:
|
||||
gerrit.post("/changes/" + change_id + "/abandon",
|
||||
json={"message": "%s" % abandon_message})
|
||||
abandoned += 1
|
||||
except Exception as e:
|
||||
errors += 1
|
||||
logging.error(e)
|
||||
logging.info("Total %d stale open changes", len(stale_changes))
|
||||
if not options.dry_run:
|
||||
logging.info("Abandoned %d changes. %d errors.", abandoned, errors)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(_main())
|
Reference in New Issue
Block a user