@@ -408,6 +408,13 @@ def record_retry_log(self, src, body):
408
408
[self .repo_label , self .num , src , body ],
409
409
)
410
410
411
+ @property
412
+ def author (self ):
413
+ """
414
+ Get the GitHub login name of the author of the pull request
415
+ """
416
+ return self .get_issue ().user .login
417
+
411
418
412
419
def sha_cmp (short , full ):
413
420
return len (short ) >= 4 and short == full [:len (short )]
@@ -489,13 +496,10 @@ def parse_commands(body, username, repo_label, repo_cfg, state, my_username,
489
496
for wip_kw in ['WIP' , 'TODO' , '[WIP]' , '[TODO]' , '[DO NOT MERGE]' ]:
490
497
if state .title .upper ().startswith (wip_kw ):
491
498
if realtime :
492
- state .add_comment ((
493
- ':clipboard:'
494
- ' Looks like this PR is still in progress,'
495
- ' ignoring approval.\n \n '
496
- 'Hint: Remove **{}** from this PR\' s title when'
497
- ' it is ready for review.'
498
- ).format (wip_kw ))
499
+ state .add_comment (comments .ApprovalIgnoredWip (
500
+ sha = state .head_sha ,
501
+ wip_keyword = wip_kw ,
502
+ ))
499
503
is_wip = True
500
504
break
501
505
if is_wip :
@@ -557,14 +561,10 @@ def parse_commands(body, username, repo_label, repo_cfg, state, my_username,
557
561
.format (msg , state .head_sha )
558
562
)
559
563
else :
560
- state .add_comment (
561
- ':pushpin: Commit {} has been approved by `{}`\n \n <!-- @{} r={} {} -->' # noqa
562
- .format (
563
- state .head_sha ,
564
- approver ,
565
- my_username ,
566
- approver ,
567
- state .head_sha ,
564
+ state .add_comment (comments .Approved (
565
+ sha = state .head_sha ,
566
+ approver = approver ,
567
+ bot = my_username ,
568
568
))
569
569
treeclosed = state .blocked_by_closed_tree ()
570
570
if treeclosed :
@@ -575,9 +575,18 @@ def parse_commands(body, username, repo_label, repo_cfg, state, my_username,
575
575
state .change_labels (LabelEvent .APPROVED )
576
576
577
577
elif command .action == 'unapprove' :
578
- if not verify_auth (username , repo_label , repo_cfg , state ,
579
- AuthState .REVIEWER , realtime , my_username ):
580
- continue
578
+ # Allow the author of a pull request to unapprove their own PR. The
579
+ # author can already perform other actions that effectively
580
+ # unapprove the PR (change the target branch, push more commits,
581
+ # etc.) so allowing them to directly unapprove it is also allowed.
582
+
583
+ # Because verify_auth has side-effects (especially, it may leave a
584
+ # comment on the pull request if the user is not authorized), we
585
+ # need to do the author check BEFORE the verify_auth check.
586
+ if state .author != username :
587
+ if not verify_auth (username , repo_label , repo_cfg , state ,
588
+ AuthState .REVIEWER , realtime , my_username ):
589
+ continue
581
590
582
591
state .approved_by = ''
583
592
state .save ()
@@ -610,10 +619,10 @@ def parse_commands(body, username, repo_label, repo_cfg, state, my_username,
610
619
state .save ()
611
620
612
621
if realtime :
613
- state .add_comment (
614
- ':v: @{} can now approve this pull request'
615
- . format ( state .delegate )
616
- )
622
+ state .add_comment (comments . Delegated (
623
+ delegator = username ,
624
+ delegate = state .delegate
625
+ ))
617
626
618
627
elif command .action == 'undelegate' :
619
628
# TODO: why is this a TRY?
@@ -630,10 +639,10 @@ def parse_commands(body, username, repo_label, repo_cfg, state, my_username,
630
639
state .save ()
631
640
632
641
if realtime :
633
- state .add_comment (
634
- ':v: @{} can now approve this pull request'
635
- . format ( state .delegate )
636
- )
642
+ state .add_comment (comments . Delegated (
643
+ delegator = username ,
644
+ delegate = state .delegate
645
+ ))
637
646
638
647
elif command .action == 'retry' and realtime :
639
648
if not _try_auth_verified ():
@@ -662,6 +671,10 @@ def parse_commands(body, username, repo_label, repo_cfg, state, my_username,
662
671
663
672
state .save ()
664
673
if realtime and state .try_ :
674
+ # If we've tried before, the status will be 'success', and this
675
+ # new try will not be picked up. Set the status back to ''
676
+ # so the try will be run again.
677
+ state .set_status ('' )
665
678
# `try-` just resets the `try` bit and doesn't correspond to
666
679
# any meaningful labeling events.
667
680
state .change_labels (LabelEvent .TRY )
@@ -1224,7 +1237,11 @@ def start_build(state, repo_cfgs, buildbot_slots, logger, db, git_cfg):
1224
1237
if found_travis_context and len (builders ) == 1 :
1225
1238
can_try_travis_exemption = True
1226
1239
if 'checks' in repo_cfg :
1227
- builders += ['checks-' + key for key , value in repo_cfg ['checks' ].items () if 'name' in value ] # noqa
1240
+ builders += [
1241
+ 'checks-' + key
1242
+ for key , value in repo_cfg ['checks' ].items ()
1243
+ if 'name' in value or (state .try_ and 'try_name' in value )
1244
+ ]
1228
1245
only_status_builders = False
1229
1246
1230
1247
if len (builders ) == 0 :
0 commit comments