Skip to content

Commit 631daf4

Browse files
authored
sync_labels_add_on_review_comment initial (#6)
1 parent d084f7c commit 631daf4

File tree

1 file changed

+100
-29
lines changed

1 file changed

+100
-29
lines changed

.github/sync_labels.py

+100-29
Original file line numberDiff line numberDiff line change
@@ -235,9 +235,9 @@ def get_review_decision(self):
235235

236236
def get_reviews(self, complete=False):
237237
r"""
238-
Return the list of reviews of the PR. Per default only those reviews
239-
are returned which have been submitted after the youngest commit.
240-
Use keyword ``complete`` to get them all.
238+
Return the list of reviews of the PR. Per default only those proper reviews
239+
are returned which have been submitted after the most recent commit. Use
240+
keyword ``complete`` to get them all.
241241
"""
242242
if not self.is_pull_request():
243243
return None
@@ -253,9 +253,11 @@ def get_reviews(self, complete=False):
253253
self.get_commits()
254254

255255
date = self._commit_date
256+
no_rev = ReviewDecision.unclear.value
256257
new_revs = [rev for rev in self._reviews if rev['submittedAt'] > date]
257-
info('Reviews for %s: %s after %s' % (self._issue, self._reviews, date))
258-
return new_revs
258+
proper_new_revs = [rev for rev in new_revs if rev['state'] != no_rev]
259+
info('Proper reviews after %s for %s: %s' % (date, self._issue, proper_new_revs))
260+
return proper_new_revs
259261

260262
def active_partners(self, item):
261263
r"""
@@ -270,12 +272,34 @@ def active_partners(self, item):
270272
# -------------------------------------------------------------------------
271273
# methods to validate the issue state
272274
# -------------------------------------------------------------------------
275+
def review_comment_to_state(self):
276+
r"""
277+
Return a State label if the most recent review comment
278+
starts with its value.
279+
"""
280+
revs = self.get_reviews(complete=True)
281+
date = max(rev['submittedAt'] for rev in revs)
282+
283+
for rev in revs:
284+
if rev['submittedAt'] == date:
285+
for stat in State:
286+
body = rev['body']
287+
if body.startswith(stat.value):
288+
return stat
289+
return None
290+
273291
def needs_work_valid(self):
274292
r"""
275293
Return ``True`` if the PR needs work. This is the case if
276-
the review decision requests changes or if there is any
277-
review reqesting changes.
294+
there are reviews more recent than any commit and the review
295+
decision requests changes or if there is any review reqesting
296+
changes.
278297
"""
298+
revs = self.get_reviews()
299+
if not revs:
300+
# no proper review since most recent commit.
301+
return False
302+
279303
ch_req = ReviewDecision.changes_requested
280304
rev_dec = self.get_review_decision()
281305
if rev_dec:
@@ -286,8 +310,6 @@ def needs_work_valid(self):
286310
info('PR %s doesn\'t need work (by decision)' % self._issue)
287311
return False
288312

289-
revs = self.get_reviews()
290-
revs = [rev for rev in revs if rev['author']['login'] == self._actor]
291313
if any(rev['state'] == ch_req.value for rev in revs):
292314
info('PR %s needs work' % self._issue)
293315
return True
@@ -297,9 +319,15 @@ def needs_work_valid(self):
297319
def positive_review_valid(self):
298320
r"""
299321
Return ``True`` if the PR has positive review. This is the
300-
case if the review decision is approved or if there is any
301-
approved review but no changes requesting one.
322+
case if there are reviews more recent than any commit and the
323+
review decision is approved or if there is any approved review
324+
but no changes requesting one.
302325
"""
326+
revs = self.get_reviews()
327+
if not revs:
328+
# no proper review since most recent commit.
329+
return False
330+
303331
appr = ReviewDecision.approved
304332
rev_dec = self.get_review_decision()
305333
if rev_dec:
@@ -310,13 +338,7 @@ def positive_review_valid(self):
310338
info('PR %s doesn\'t have positve review (by decision)' % self._issue)
311339
return False
312340

313-
if self.needs_work_valid():
314-
info('PR %s doesn\'t have positve review (needs work)' % self._issue)
315-
return False
316-
317-
revs = self.get_reviews()
318-
revs = [rev for rev in revs if rev['author']['login'] == self._actor]
319-
if any(rev['state'] == appr.value for rev in revs):
341+
if all(rev['state'] == appr.value for rev in revs):
320342
info('PR %s has positve review' % self._issue)
321343
return True
322344
info('PR %s doesn\'t have positve review' % self._issue)
@@ -407,6 +429,12 @@ def edit(self, arg, option):
407429
"""
408430
self.gh_cmd('edit', arg, option)
409431

432+
def mark_as_ready(self):
433+
r"""
434+
Perform a system call to ``gh`` to mark a PR as ready for review.
435+
"""
436+
self.gh_cmd('ready', '', '')
437+
410438
def review(self, arg, text):
411439
r"""
412440
Perform a system call to ``gh`` to review a PR.
@@ -427,6 +455,13 @@ def request_changes(self):
427455
self.review('--request-changes', '%s requested changes for this PR' % self._actor)
428456
info('Changes requested for PR %s by %s' % (self._issue, self._actor))
429457

458+
def review_comment(self, text):
459+
r"""
460+
Add a review comment.
461+
"""
462+
self.review('--comment', text)
463+
info('Add review comment for PR %s: %s' % (self._issue, text))
464+
430465
def add_comment(self, text):
431466
r"""
432467
Perform a system call to ``gh`` to add a comment to an issue or PR.
@@ -526,20 +561,34 @@ def on_label_add(self, label):
526561
return
527562

528563
if item == State.needs_review:
529-
if not self.needs_review_valid():
564+
if self.needs_review_valid():
565+
# here we come for example after a sequence:
566+
# needs review -> needs info -> needs review
567+
pass
568+
elif self.is_draft():
569+
self.mark_as_ready()
570+
else:
530571
self.reject_label_addition(item)
531572
return
532573

533-
if item == State.positive_review:
534-
if self.approve_allowed():
535-
self.approve()
574+
if item == State.needs_work:
575+
if self.needs_work_valid():
576+
# here we come for example after a sequence:
577+
# needs work -> needs info -> needs work
578+
pass
579+
elif not self.is_draft():
580+
self.request_changes()
536581
else:
537582
self.reject_label_addition(item)
538583
return
539584

540-
if item == State.needs_work:
541-
if self.needs_review_valid():
542-
self.request_changes()
585+
if item == State.positive_review:
586+
if self.positive_review_valid():
587+
# here we come for example after a sequence:
588+
# positive review -> needs info -> positive review
589+
pass
590+
elif self.approve_allowed():
591+
self.approve()
543592
else:
544593
self.reject_label_addition(item)
545594
return
@@ -570,6 +619,19 @@ def on_label_removal(self, label):
570619
elif sel_list is Priority:
571620
self.reject_label_removal(item)
572621
return
622+
623+
def on_review_comment(self):
624+
r"""
625+
Check if the text of the most recent review begins with a
626+
specific label name. In this case, simulate the corresponding
627+
label addition. This feature is needed for people who don't
628+
have permission to add labels (i.e. aren't a member of the
629+
Triage team).
630+
"""
631+
rev_state = self.review_comment_to_state()
632+
if rev_state in (State.needs_info, State.needs_review):
633+
self.select_label(rev_state)
634+
self.run(Action.labeled, label=rev_state.value)
573635

574636
def remove_all_labels_of_sel_list(self, sel_list):
575637
r"""
@@ -605,6 +667,7 @@ def run(self, action, label=None, rev_state=None):
605667
self.select_label(State.needs_review)
606668

607669
if action is Action.submitted:
670+
rev_state = RevState(rev_state)
608671
if rev_state is RevState.approved:
609672
if self.positive_review_valid():
610673
self.select_label(State.positive_review)
@@ -613,6 +676,9 @@ def run(self, action, label=None, rev_state=None):
613676
if self.needs_work_valid():
614677
self.select_label(State.needs_work)
615678

679+
if rev_state is RevState.commented:
680+
self.on_review_comment()
681+
616682
def run_tests(self):
617683
r"""
618684
Simulative run over all posibble events.
@@ -644,12 +710,17 @@ def run_tests(self):
644710
self.add_label(res.value)
645711
self.run(action, label=prio.value)
646712
elif action == Action.submitted and self.is_pull_request():
647-
for stat in RevState:
648-
if stat is RevState.approved:
713+
for rev_stat in RevState:
714+
if rev_stat is RevState.approved:
649715
self.approve()
650-
elif stat is RevState.changes_requested:
716+
self.run(action, rev_state=rev_stat.value)
717+
elif rev_stat is RevState.changes_requested:
651718
self.request_changes()
652-
self.run(action, rev_state=stat.value)
719+
self.run(action, rev_state=rev_stat.value)
720+
elif rev_stat is RevState.commented:
721+
for stat in State:
722+
self.review_comment(stat.value)
723+
self.run(action, rev_state=rev_stat.value)
653724
elif self.is_pull_request():
654725
self.run(action)
655726

0 commit comments

Comments
 (0)