With the python shebang remaining as Python 2, switch the scripts to using Python 3. This also allows us to clean up some imports.
139 lines
4.9 KiB
Python
Executable File
139 lines
4.9 KiB
Python
Executable File
#!/usr/bin/python3
|
|
|
|
import argparse
|
|
from datetime import datetime
|
|
from osc import conf
|
|
from osc.core import ET
|
|
from osc.core import search
|
|
from osc.core import xpath_join
|
|
from osclib.comments import CommentAPI
|
|
from osclib.core import request_age
|
|
from osclib.memoize import memoize
|
|
import sys
|
|
|
|
def print_debug(message):
|
|
if conf.config['debug']:
|
|
print(message)
|
|
|
|
def request_debug(request, age, threshold):
|
|
print_debug('{}: {} {} [{}]'.format(request.get('id'), age, threshold, age <= threshold))
|
|
|
|
@memoize(session=True)
|
|
def check_comment(apiurl, bot, **kwargs):
|
|
if not len(kwargs):
|
|
return False
|
|
|
|
api = CommentAPI(apiurl)
|
|
comments = api.get_comments(**kwargs)
|
|
comment = api.comment_find(comments, bot)[0]
|
|
if comment:
|
|
return (datetime.utcnow() - comment['when']).total_seconds()
|
|
|
|
return False
|
|
|
|
def check(apiurl, entity, entity_type='group', comment=False, bot=None,
|
|
threshold=2 * 3600, threshold_require=True):
|
|
queries = {'request': {'limit': 1000, 'withfullhistory': 1}}
|
|
xpath = 'state[@name="new"] or state[@name="review"]'
|
|
|
|
if entity == 'staging-bot':
|
|
xpath = xpath_join(
|
|
xpath, 'review[starts-with(@by_project, "openSUSE:") and @state="new"]', op='and')
|
|
xpath = xpath_join(
|
|
xpath, 'history/@who="{}"'.format(entity), op='and')
|
|
|
|
requests = search(apiurl, queries, request=xpath)['request']
|
|
for request in requests:
|
|
age = request_age(request).total_seconds()
|
|
request_debug(request, age, threshold)
|
|
|
|
if age <= threshold:
|
|
return True
|
|
|
|
return False
|
|
|
|
xpath = xpath_join(
|
|
xpath, 'review[@by_{}="{}" and @state="new"]'.format(entity_type, entity), op='and')
|
|
requests = search(apiurl, queries, request=xpath)['request']
|
|
|
|
print_debug('{:,} requests'.format(len(requests)))
|
|
if not len(requests):
|
|
# Could check to see that a review has been performed in the last week.
|
|
return True
|
|
|
|
all_comment = True
|
|
for request in requests:
|
|
kwargs = {}
|
|
if comment == 'project':
|
|
# Would be a lot easier with lxml, but short of reparsing or monkey.
|
|
for review in request.findall('review[@by_project]'):
|
|
if review.get('by_project').startswith('openSUSE:'):
|
|
kwargs['project_name'] = review.get('by_project')
|
|
# TODO repo-checker will miss stagings where delete only problem so
|
|
# comment on request, but should be fixed by #1084.
|
|
elif comment:
|
|
kwargs['request_id'] = request.get('id')
|
|
|
|
age = request_age(request).total_seconds()
|
|
request_debug(request, age, threshold)
|
|
comment_age = check_comment(apiurl, bot, **kwargs)
|
|
if comment_age:
|
|
if comment_age <= threshold:
|
|
print_debug('comment found below threshold')
|
|
return True
|
|
elif age > threshold:
|
|
print_debug('no comment found and above threshold')
|
|
all_comment = False
|
|
if threshold_require:
|
|
return False
|
|
else:
|
|
continue
|
|
else:
|
|
print_debug('no comment found, but below threshold')
|
|
|
|
print_debug('all comments: {}'.format(all_comment))
|
|
return all_comment
|
|
|
|
def status(apiurl):
|
|
# TODO If request ordering via api (openSUSE/open-build-service#4108) is
|
|
# provided this can be implemented much more cleanly by looking for positive
|
|
# activity (review changes) in threshold. Without sorting, some sampling of
|
|
# all requests accepted are returned which is not useful.
|
|
# TODO legal-auto, does not make comments so pending the above.
|
|
bots = [
|
|
# No open requests older than 2 hours.
|
|
['factory-auto'],
|
|
# No open requests older than 2 hours or all old requests have comment.
|
|
['leaper', 'user', True, 'Leaper'],
|
|
# As long as some comment made in last 6 hours.
|
|
['repo-checker', 'user', 'project', 'RepoChecker', 6 * 3600, False],
|
|
# Different algorithm, any staging in last 24 hours.
|
|
['staging-bot', 'user', False, None, 24 * 3600],
|
|
]
|
|
|
|
all_alive = True
|
|
for bot in bots:
|
|
result = check(apiurl, *bot)
|
|
if not result:
|
|
all_alive = False
|
|
print('{} = {}'.format(bot[0], result))
|
|
|
|
return all_alive
|
|
|
|
def main(args):
|
|
conf.get_config(override_apiurl=args.apiurl)
|
|
conf.config['debug'] = args.debug
|
|
apiurl = conf.config['apiurl']
|
|
return not status(apiurl)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
description = 'Check the status of the staging workflow bots.'
|
|
parser = argparse.ArgumentParser(description=description)
|
|
parser.add_argument('-A', '--apiurl', help='OBS instance API URL')
|
|
parser.add_argument('-d', '--debug', action='store_true', help='print useful debugging info')
|
|
parser.add_argument('-p', '--project', default='openSUSE:Factory', help='OBS project')
|
|
args = parser.parse_args()
|
|
|
|
sys.exit(main(args))
|