@@ -40,6 +40,7 @@ type MergeOptions struct {
4040 BodySet bool
4141 Editor editor
4242
43+ UseAdmin bool
4344 IsDeleteBranchIndicated bool
4445 CanDeleteLocalBranch bool
4546 InteractiveMode bool
@@ -109,6 +110,15 @@ func NewCmdMerge(f *cmdutil.Factory, runF func(*MergeOptions) error) *cobra.Comm
109110 bodyProvided := cmd .Flags ().Changed ("body" )
110111 bodyFileProvided := bodyFile != ""
111112
113+ if err := cmdutil .MutuallyExclusive (
114+ "specify only one of `--auto`, `--disable-auto`, or `--admin`" ,
115+ opts .AutoMergeEnable ,
116+ opts .AutoMergeDisable ,
117+ opts .UseAdmin ,
118+ ); err != nil {
119+ return err
120+ }
121+
112122 if err := cmdutil .MutuallyExclusive (
113123 "specify only one of `--body` or `--body-file`" ,
114124 bodyProvided ,
@@ -140,6 +150,7 @@ func NewCmdMerge(f *cmdutil.Factory, runF func(*MergeOptions) error) *cobra.Comm
140150 },
141151 }
142152
153+ cmd .Flags ().BoolVar (& opts .UseAdmin , "admin" , false , "Use administrator privileges to merge a pull request that does not meet requirements" )
143154 cmd .Flags ().BoolVarP (& opts .DeleteBranch , "delete-branch" , "d" , false , "Delete the local and remote branch after merge" )
144155 cmd .Flags ().StringVarP (& opts .Body , "body" , "b" , "" , "Body `text` for the merge commit" )
145156 cmd .Flags ().StringVarP (& bodyFile , "body-file" , "F" , "" , "Read body text from `file`" )
@@ -192,9 +203,13 @@ func mergeRun(opts *MergeOptions) error {
192203 }
193204
194205 isPRAlreadyMerged := pr .State == "MERGED"
195- if blocked := blockedReason (pr .MergeStateStatus ); ! opts .AutoMergeEnable && ! isPRAlreadyMerged && blocked != "" {
196- fmt .Fprintf (opts .IO .ErrOut , "%s Pull request #%d is not mergeable: %s.\n " , cs .FailureIcon (), pr .Number , blocked )
206+ if reason := blockedReason (pr .MergeStateStatus , opts . UseAdmin ); ! opts .AutoMergeEnable && ! isPRAlreadyMerged && reason != "" {
207+ fmt .Fprintf (opts .IO .ErrOut , "%s Pull request #%d is not mergeable: %s.\n " , cs .FailureIcon (), pr .Number , reason )
197208 fmt .Fprintf (opts .IO .ErrOut , "To have the pull request merged after all the requirements have been met, add the `--auto` flag.\n " )
209+ if ! opts .UseAdmin && allowsAdminOverride (pr .MergeStateStatus ) {
210+ // TODO: show this flag only to repo admins
211+ fmt .Fprintf (opts .IO .ErrOut , "To use administrator privileges to immediately merge the pull request, add the `--admin` flag.\n " )
212+ }
198213 return cmdutil .SilentError
199214 }
200215
@@ -455,11 +470,17 @@ func (e *userEditor) Edit(filename, startingText string) (string, error) {
455470}
456471
457472// blockedReason translates various MergeStateStatus GraphQL values into human-readable reason
458- func blockedReason (status string ) string {
473+ func blockedReason (status string , useAdmin bool ) string {
459474 switch status {
460475 case "BLOCKED" :
476+ if useAdmin {
477+ return ""
478+ }
461479 return "the base branch policy prohibits the merge"
462480 case "BEHIND" :
481+ if useAdmin {
482+ return ""
483+ }
463484 return "the head branch is not up to date with the base branch"
464485 case "DIRTY" :
465486 return "the merge commit cannot be cleanly created"
@@ -468,6 +489,15 @@ func blockedReason(status string) string {
468489 }
469490}
470491
492+ func allowsAdminOverride (status string ) bool {
493+ switch status {
494+ case "BLOCKED" , "BEHIND" :
495+ return true
496+ default :
497+ return false
498+ }
499+ }
500+
471501func isImmediatelyMergeable (status string ) bool {
472502 switch status {
473503 case "CLEAN" , "HAS_HOOKS" , "UNSTABLE" :
0 commit comments