github.com/shashidharatd/test-infra@v0.0.0-20171006011030-71304e1ca560/prow/plugins/wip/wip-label.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 wip will label a PR a work-in-progress if the author provides
    18  // a prefix to their pull request title to the same effect. The submit-
    19  // queue will not merge pull requests with the work-in-progress label.
    20  // The label will be removed when the title changes to no longer begin
    21  // with the prefix.
    22  package wip
    23  
    24  import (
    25  	"fmt"
    26  	"regexp"
    27  
    28  	"github.com/sirupsen/logrus"
    29  
    30  	"k8s.io/test-infra/prow/github"
    31  	"k8s.io/test-infra/prow/plugins"
    32  )
    33  
    34  const (
    35  	label      = "do-not-merge/work-in-progress"
    36  	pluginName = "wip"
    37  )
    38  
    39  var (
    40  	titleRegex = regexp.MustCompile(`(?i)^\W?WIP\W`)
    41  )
    42  
    43  type event struct {
    44  	org        string
    45  	repo       string
    46  	number     int
    47  	hasLabel   bool
    48  	needsLabel bool
    49  }
    50  
    51  func init() {
    52  	plugins.RegisterPullRequestHandler(pluginName, handlePullRequest)
    53  }
    54  
    55  // Strict subset of *github.Client methods.
    56  type githubClient interface {
    57  	GetIssueLabels(org, repo string, number int) ([]github.Label, error)
    58  	AddLabel(owner, repo string, number int, label string) error
    59  	RemoveLabel(owner, repo string, number int, label string) error
    60  	CreateComment(org, repo string, number int, comment string) error
    61  }
    62  
    63  func handlePullRequest(pc plugins.PluginClient, pe github.PullRequestEvent) error {
    64  	// These are the only actions indicating the PR title may have changed.
    65  	if pe.Action != github.PullRequestActionOpened &&
    66  		pe.Action != github.PullRequestActionReopened &&
    67  		pe.Action != github.PullRequestActionEdited {
    68  		return nil
    69  	}
    70  
    71  	var (
    72  		org    = pe.PullRequest.Base.Repo.Owner.Login
    73  		repo   = pe.PullRequest.Base.Repo.Name
    74  		number = pe.PullRequest.Number
    75  		title  = pe.PullRequest.Title
    76  	)
    77  
    78  	currentLabels, err := pc.GitHubClient.GetIssueLabels(org, repo, number)
    79  	if err != nil {
    80  		return fmt.Errorf("could not get labels for PR %s/%s:%d in WIP plugin: %v", org, repo, number, err)
    81  	}
    82  	hasLabel := false
    83  	for _, l := range currentLabels {
    84  		if l.Name == label {
    85  			hasLabel = true
    86  		}
    87  	}
    88  
    89  	needsLabel := titleRegex.MatchString(title)
    90  
    91  	e := &event{
    92  		org:        org,
    93  		repo:       repo,
    94  		number:     number,
    95  		hasLabel:   hasLabel,
    96  		needsLabel: needsLabel,
    97  	}
    98  	return handle(pc.GitHubClient, pc.Logger, e)
    99  }
   100  
   101  // handle interacts with GitHub to drive the pull request to the
   102  // proper state by adding and removing comments and labels. If a
   103  // PR has a WIP prefix, it needs an explanatory comment and label.
   104  // Otherwise, neither should be present.
   105  func handle(gc githubClient, le *logrus.Entry, e *event) error {
   106  	if e.needsLabel && !e.hasLabel {
   107  		if err := gc.AddLabel(e.org, e.repo, e.number, label); err != nil {
   108  			le.Warnf("error while adding label %q: %v", label, err)
   109  			return err
   110  		}
   111  	} else if !e.needsLabel && e.hasLabel {
   112  		if err := gc.RemoveLabel(e.org, e.repo, e.number, label); err != nil {
   113  			le.Warnf("error while removing label %q: %v", label, err)
   114  			return err
   115  		}
   116  	}
   117  	return nil
   118  }