github.com/munnerz/test-infra@v0.0.0-20190108210205-ce3d181dc989/prow/plugins/lifecycle/reopen.go (about)

     1  /*
     2  Copyright 2017 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package lifecycle
    18  
    19  import (
    20  	"fmt"
    21  	"regexp"
    22  
    23  	"github.com/sirupsen/logrus"
    24  
    25  	"k8s.io/test-infra/prow/github"
    26  	"k8s.io/test-infra/prow/plugins"
    27  )
    28  
    29  var reopenRe = regexp.MustCompile(`(?mi)^/reopen\s*$`)
    30  
    31  type githubClient interface {
    32  	IsCollaborator(owner, repo, login string) (bool, error)
    33  	CreateComment(owner, repo string, number int, comment string) error
    34  	ReopenIssue(owner, repo string, number int) error
    35  	ReopenPR(owner, repo string, number int) error
    36  }
    37  
    38  func handleReopen(gc githubClient, log *logrus.Entry, e *github.GenericCommentEvent) error {
    39  	// Only consider closed issues and new comments.
    40  	if e.IssueState != "closed" || e.Action != github.GenericCommentActionCreated {
    41  		return nil
    42  	}
    43  
    44  	if !reopenRe.MatchString(e.Body) {
    45  		return nil
    46  	}
    47  
    48  	org := e.Repo.Owner.Login
    49  	repo := e.Repo.Name
    50  	number := e.Number
    51  	commentAuthor := e.User.Login
    52  
    53  	isAuthor := e.IssueAuthor.Login == commentAuthor
    54  	isCollaborator, err := gc.IsCollaborator(org, repo, commentAuthor)
    55  	if err != nil {
    56  		log.WithError(err).Errorf("Failed IsCollaborator(%s, %s, %s)", org, repo, commentAuthor)
    57  	}
    58  
    59  	// Only authors and collaborators are allowed to reopen issues or PRs.
    60  	if !isAuthor && !isCollaborator {
    61  		response := "You can't reopen an issue/PR unless you authored it or you are a collaborator."
    62  		log.Infof("Commenting \"%s\".", response)
    63  		return gc.CreateComment(
    64  			org,
    65  			repo,
    66  			number,
    67  			plugins.FormatResponseRaw(e.Body, e.HTMLURL, commentAuthor, response),
    68  		)
    69  	}
    70  
    71  	if e.IsPR {
    72  		log.Info("/reopen PR")
    73  		if err := gc.ReopenPR(org, repo, number); err != nil {
    74  			if scbc, ok := err.(github.StateCannotBeChanged); ok {
    75  				resp := fmt.Sprintf("Failed to re-open PR: %v", scbc)
    76  				return gc.CreateComment(
    77  					org,
    78  					repo,
    79  					number,
    80  					plugins.FormatResponseRaw(e.Body, e.HTMLURL, e.User.Login, resp),
    81  				)
    82  			}
    83  			return err
    84  		}
    85  		// Add a comment after reopening the PR to leave an audit trail of who
    86  		// asked to reopen it.
    87  		return gc.CreateComment(
    88  			org,
    89  			repo,
    90  			number,
    91  			plugins.FormatResponseRaw(e.Body, e.HTMLURL, commentAuthor, "Reopened this PR."),
    92  		)
    93  	}
    94  
    95  	log.Info("/reopen issue")
    96  	if err := gc.ReopenIssue(org, repo, number); err != nil {
    97  		if scbc, ok := err.(github.StateCannotBeChanged); ok {
    98  			resp := fmt.Sprintf("Failed to re-open Issue: %v", scbc)
    99  			return gc.CreateComment(
   100  				org,
   101  				repo,
   102  				number,
   103  				plugins.FormatResponseRaw(e.Body, e.HTMLURL, e.User.Login, resp),
   104  			)
   105  		}
   106  		return err
   107  	}
   108  	// Add a comment after reopening the issue to leave an audit trail of who
   109  	// asked to reopen it.
   110  	return gc.CreateComment(
   111  		org,
   112  		repo,
   113  		number,
   114  		plugins.FormatResponseRaw(e.Body, e.HTMLURL, commentAuthor, "Reopened this issue."),
   115  	)
   116  }