@@ -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 )]
@@ -576,9 +583,18 @@ def parse_commands(body, username, repo_label, repo_cfg, state, my_username,
576
583
state .change_labels (LabelEvent .APPROVED )
577
584
578
585
elif word == 'r-' :
579
- if not verify_auth (username , repo_label , repo_cfg , state ,
580
- AuthState .REVIEWER , realtime , my_username ):
581
- continue
586
+ # Allow the author of a pull request to unapprove their own PR. The
587
+ # author can already perform other actions that effectively
588
+ # unapprove the PR (change the target branch, push more commits,
589
+ # etc.) so allowing them to directly unapprove it is also allowed.
590
+
591
+ # Because verify_auth has side-effects (especially, it may leave a
592
+ # comment on the pull request if the user is not authorized), we
593
+ # need to do the author check BEFORE the verify_auth check.
594
+ if state .author != username :
595
+ if not verify_auth (username , repo_label , repo_cfg , state ,
596
+ AuthState .REVIEWER , realtime , my_username ):
597
+ continue
582
598
583
599
state .approved_by = ''
584
600
state .save ()
0 commit comments