Skip to content

Commit 4f0b3a9

Browse files
authored
Merge pull request #23 from kennytm/treeclosed-retry-log
Display which comment issued `treeclosed`, and log which comments performed a `retry`
2 parents ae42677 + 4ad0157 commit 4f0b3a9

File tree

5 files changed

+146
-11
lines changed

5 files changed

+146
-11
lines changed

cfg.sample.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
# Priority values above max_priority will be refused.
22
max_priority = 9001
33

4+
# How long to keep the retry log
5+
# Should be a negative interval of time recognized by SQLite3.
6+
retry_log_expire = '-42 days'
7+
48
[github]
59

610
# Information for securely interacting with GitHub. These are found/generated

homu/html/queue.html

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
</style>
3333
</head>
3434
<body>
35-
<h1>Homu queue - {% if repo_url %}<a href="{{repo_url}}" target="_blank">{{repo_label}}</a>{% else %}{{repo_label}}{% endif %} {% if treeclosed %} [TREE CLOSED below priority {{treeclosed}}] {% endif %}</h2>
35+
<h1>Homu queue - {% if repo_url %}<a href="{{repo_url}}" target="_blank">{{repo_label}}</a>{% else %}{{repo_label}}{% endif %} {% if treeclosed %} [<a href="{{treeclosed_src}}">TREE CLOSED</a> below priority {{treeclosed}}] {% endif %}</h2>
3636

3737
<p>
3838
<button type="button" id="expand-rollup">Create a rollup</button>
@@ -118,6 +118,8 @@ <h1>Homu queue - {% if repo_url %}<a href="{{repo_url}}" target="_blank">{{repo_
118118
</tbody>
119119
</table>
120120

121+
<p><a href="../retry_log/{{repo_label}}">Open retry log</a></p>
122+
121123
<script src="../assets/jquery.min.js"></script>
122124
<script src="../assets/jquery.dataTables.min.js"></script>
123125

homu/html/retry_log.html

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<!doctype html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<title>Homu retry log {{repo_label}}</title>
6+
<style>
7+
* { font-family: sans-serif; }
8+
h1 { font-size: 20px; }
9+
h2 { font-size: 16px; }
10+
p { font-size: 15px; }
11+
pre { margin: 0; }
12+
13+
table { border-collapse: collapse; }
14+
td, th { border: 2px solid white; padding: 5px; font-size: 13px; vertical-align: top; }
15+
tr:nth-child(even) { background: #ddd; }
16+
</style>
17+
</head>
18+
<body>
19+
<h1>Homu retry log - <a href="{{repo_url}}" target="_blank">{{repo_label}}</a></h1>
20+
21+
<table id="results">
22+
<thead>
23+
<tr>
24+
<th>Time (UTC)</th>
25+
<th>PR</th>
26+
<th>Message</th>
27+
</tr>
28+
</thead>
29+
30+
<tbody>
31+
{% for log in logs %}
32+
<tr>
33+
<td>{{log.time}}</td>
34+
<td><a href="{{log.src}}">{{log.num}}</a></td>
35+
<td><pre>{{log.msg}}</pre></td>
36+
</tr>
37+
{% endfor %}
38+
</tbody>
39+
</table>
40+
41+
</body>
42+
</html>

homu/main.py

Lines changed: 56 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ def db_query(db, *args):
7777

7878
class Repository:
7979
treeclosed = -1
80+
treecloesd_src = None
8081
gh = None
8182
label = None
8283
db = None
@@ -87,17 +88,20 @@ def __init__(self, gh, repo_label, db):
8788
self.db = db
8889
db_query(
8990
db,
90-
'SELECT treeclosed FROM repos WHERE repo = ?',
91+
'SELECT treeclosed, treeclosed_src FROM repos WHERE repo = ?',
9192
[repo_label]
9293
)
9394
row = db.fetchone()
9495
if row:
9596
self.treeclosed = row[0]
97+
self.treecloesd_src = row[1]
9698
else:
9799
self.treeclosed = -1
100+
self.treeclosed_src = None
98101

99-
def update_treeclosed(self, value):
102+
def update_treeclosed(self, value, src):
100103
self.treeclosed = value
104+
self.treeclosed_src = src
101105
db_query(
102106
self.db,
103107
'DELETE FROM repos where repo = ?',
@@ -106,8 +110,11 @@ def update_treeclosed(self, value):
106110
if value > 0:
107111
db_query(
108112
self.db,
109-
'INSERT INTO repos (repo, treeclosed) VALUES (?, ?)',
110-
[self.repo_label, value]
113+
'''
114+
INSERT INTO repos (repo, treeclosed, treeclosed_src)
115+
VALUES (?, ?, ?)
116+
''',
117+
[self.repo_label, value, src]
111118
)
112119

113120
def __lt__(self, other):
@@ -348,8 +355,8 @@ def fake_merge(self, repo_cfg):
348355
title = merged_prefix + title
349356
issue.edit(title=title)
350357

351-
def change_treeclosed(self, value):
352-
self.repos[self.repo_label].update_treeclosed(value)
358+
def change_treeclosed(self, value, src):
359+
self.repos[self.repo_label].update_treeclosed(value, src)
353360

354361
def blocked_by_closed_tree(self):
355362
treeclosed = self.repos[self.repo_label].treeclosed
@@ -386,6 +393,19 @@ def timed_out(self):
386393
self.add_comment(comments.TimedOut())
387394
self.change_labels(LabelEvent.TIMED_OUT)
388395

396+
def record_retry_log(self, src, body):
397+
# destroy ancient records
398+
db_query(
399+
self.db,
400+
"DELETE FROM retry_log WHERE repo = ? AND time < date('now', ?)",
401+
[self.repo_label, global_cfg.get('retry_log_expire', '-42 days')],
402+
)
403+
db_query(
404+
self.db,
405+
'INSERT INTO retry_log (repo, num, src, msg) VALUES (?, ?, ?, ?)',
406+
[self.repo_label, self.num, src, body],
407+
)
408+
389409

390410
def sha_cmp(short, full):
391411
return len(short) >= 4 and short == full[:len(short)]
@@ -422,7 +442,7 @@ class LabelEvent(Enum):
422442

423443

424444
def parse_commands(body, username, repo_label, repo_cfg, state, my_username,
425-
db, states, *, realtime=False, sha=''):
445+
db, states, *, realtime=False, sha='', command_src=''):
426446
global global_cfg
427447
state_changed = False
428448

@@ -629,6 +649,7 @@ def parse_commands(body, username, repo_label, repo_cfg, state, my_username,
629649
state.set_status('')
630650
if realtime:
631651
event = LabelEvent.TRY if state.try_ else LabelEvent.APPROVED
652+
state.record_retry_log(command_src, body)
632653
state.change_labels(event)
633654

634655
elif word in ['try', 'try-'] and realtime:
@@ -703,14 +724,14 @@ def parse_commands(body, username, repo_label, repo_cfg, state, my_username,
703724
continue
704725
try:
705726
treeclosed = int(word[len('treeclosed='):])
706-
state.change_treeclosed(treeclosed)
727+
state.change_treeclosed(treeclosed, command_src)
707728
except ValueError:
708729
pass
709730
state.save()
710731
elif word == 'treeclosed-':
711732
if not _reviewer_auth_verified():
712733
continue
713-
state.change_treeclosed(-1)
734+
state.change_treeclosed(-1, None)
714735
state.save()
715736
elif 'hooks' in global_cfg:
716737
hook_found = False
@@ -1500,6 +1521,9 @@ def synchronize(repo_label, repo_cfg, logger, gh, states, repos, db, mergeable_q
15001521
db,
15011522
states,
15021523
sha=comment.original_commit_id,
1524+
command_src=comment.to_json()['html_url'],
1525+
# FIXME switch to `comment.html_url`
1526+
# after updating github3 to 1.3.0+
15031527
)
15041528

15051529
for comment in pull.iter_issue_comments():
@@ -1512,6 +1536,9 @@ def synchronize(repo_label, repo_cfg, logger, gh, states, repos, db, mergeable_q
15121536
my_username,
15131537
db,
15141538
states,
1539+
command_src=comment.to_json()['html_url'],
1540+
# FIXME switch to `comment.html_url`
1541+
# after updating github3 to 1.3.0+
15151542
)
15161543

15171544
saved_state = saved_states.get(pull.number)
@@ -1637,8 +1664,28 @@ def main():
16371664
db_query(db, '''CREATE TABLE IF NOT EXISTS repos (
16381665
repo TEXT NOT NULL,
16391666
treeclosed INTEGER NOT NULL,
1667+
treeclosed_src TEXT,
16401668
UNIQUE (repo)
16411669
)''')
1670+
1671+
db_query(db, '''CREATE TABLE IF NOT EXISTS retry_log (
1672+
repo TEXT NOT NULL,
1673+
num INTEGER NOT NULL,
1674+
time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
1675+
src TEXT NOT NULL,
1676+
msg TEXT NOT NULL
1677+
)''')
1678+
db_query(db, '''
1679+
CREATE INDEX IF NOT EXISTS retry_log_time_index ON retry_log
1680+
(repo, time DESC)
1681+
''')
1682+
1683+
# manual DB migration :/
1684+
try:
1685+
db_query(db, 'SELECT treeclosed_src FROM repos LIMIT 0')
1686+
except sqlite3.OperationalError:
1687+
db_query(db, 'ALTER TABLE repos ADD COLUMN treeclosed_src TEXT')
1688+
16421689
for repo_label, repo_cfg in cfg['repo'].items():
16431690
repo_cfgs[repo_label] = repo_cfg
16441691
repo_labels[repo_cfg['owner'], repo_cfg['name']] = repo_label

homu/server.py

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ def queue(repo_label):
115115
lazy_debug(logger, lambda: 'repo_label: {}'.format(repo_label))
116116

117117
single_repo_closed = None
118+
treeclosed_src = None
118119
if repo_label == 'all':
119120
labels = g.repos.keys()
120121
multiple = True
@@ -124,6 +125,7 @@ def queue(repo_label):
124125
multiple = len(labels) > 1
125126
if repo_label in g.repos and g.repos[repo_label].treeclosed >= 0:
126127
single_repo_closed = g.repos[repo_label].treeclosed
128+
treeclosed_src = g.repos[repo_label].treeclosed_src
127129
repo_url = 'https://github.com/{}/{}'.format(
128130
g.cfg['repo'][repo_label]['owner'],
129131
g.cfg['repo'][repo_label]['name'])
@@ -138,7 +140,7 @@ def queue(repo_label):
138140
pull_states = sorted(states)
139141
rows = []
140142
for state in pull_states:
141-
treeclosed = (single_repo_closed or
143+
treeclosed = (single_repo_closed and
142144
state.priority < g.repos[state.repo_label].treeclosed)
143145
status_ext = ''
144146

@@ -173,6 +175,7 @@ def queue(repo_label):
173175
repo_url=repo_url,
174176
repo_label=repo_label,
175177
treeclosed=single_repo_closed,
178+
treeclosed_src=treeclosed_src,
176179
states=rows,
177180
oauth_client_id=g.cfg['github']['app_client_id'],
178181
total=len(pull_states),
@@ -184,6 +187,37 @@ def queue(repo_label):
184187
)
185188

186189

190+
@get('/retry_log/<repo_label:path>')
191+
def retry_log(repo_label):
192+
logger = g.logger.getChild('retry_log')
193+
194+
lazy_debug(logger, lambda: 'repo_label: {}'.format(repo_label))
195+
196+
repo_url = 'https://github.com/{}/{}'.format(
197+
g.cfg['repo'][repo_label]['owner'],
198+
g.cfg['repo'][repo_label]['name'],
199+
)
200+
201+
db_query(
202+
g.db,
203+
'''
204+
SELECT num, time, src, msg FROM retry_log
205+
WHERE repo = ? ORDER BY time DESC
206+
''',
207+
[repo_label],
208+
)
209+
logs = [
210+
{'num': num, 'time': time, 'src': src, 'msg': msg}
211+
for num, time, src, msg in g.db.fetchall()
212+
]
213+
214+
return g.tpls['retry_log'].render(
215+
repo_url=repo_url,
216+
repo_label=repo_label,
217+
logs=logs,
218+
)
219+
220+
187221
@get('/callback')
188222
def callback():
189223
logger = g.logger.getChild('callback')
@@ -361,6 +395,7 @@ def github():
361395
g.states,
362396
realtime=True,
363397
sha=original_commit_id,
398+
command_src=info['comment']['html_url'],
364399
):
365400
state.save()
366401

@@ -406,6 +441,9 @@ def github():
406441
g.my_username,
407442
g.db,
408443
g.states,
444+
command_src=c.to_json()['html_url'],
445+
# FIXME switch to `c.html_url`
446+
# after updating github3 to 1.3.0+
409447
) or found
410448

411449
status = ''
@@ -526,6 +564,7 @@ def fail(err):
526564
g.db,
527565
g.states,
528566
realtime=True,
567+
command_src=info['comment']['html_url'],
529568
):
530569
state.save()
531570

@@ -903,6 +942,7 @@ def start(cfg, states, queue_handler, repo_cfgs, repos, logger,
903942
tpls['index'] = env.get_template('index.html')
904943
tpls['queue'] = env.get_template('queue.html')
905944
tpls['build_res'] = env.get_template('build_res.html')
945+
tpls['retry_log'] = env.get_template('retry_log.html')
906946

907947
g.cfg = cfg
908948
g.states = states

0 commit comments

Comments
 (0)