forked from openSUSE/openSUSE-release-tools
-
Notifications
You must be signed in to change notification settings - Fork 0
/
status.py
executable file
·138 lines (115 loc) · 4.9 KB
/
status.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#!/usr/bin/python
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))