github.com/munnerz/test-infra@v0.0.0-20190108210205-ce3d181dc989/prow/plugins/shrug/shrug.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 shrug
    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/labels"
    27  	"k8s.io/test-infra/prow/pluginhelp"
    28  	"k8s.io/test-infra/prow/plugins"
    29  )
    30  
    31  const pluginName = "shrug"
    32  
    33  var (
    34  	shrugRe   = regexp.MustCompile(`(?mi)^/shrug\s*$`)
    35  	unshrugRe = regexp.MustCompile(`(?mi)^/unshrug\s*$`)
    36  )
    37  
    38  type event struct {
    39  	org           string
    40  	repo          string
    41  	number        int
    42  	prAuthor      string
    43  	commentAuthor string
    44  	body          string
    45  	assignees     []github.User
    46  	hasLabel      func(label string) (bool, error)
    47  	htmlurl       string
    48  }
    49  
    50  func init() {
    51  	plugins.RegisterGenericCommentHandler(pluginName, handleGenericComment, helpProvider)
    52  }
    53  
    54  func helpProvider(config *plugins.Configuration, enabledRepos []string) (*pluginhelp.PluginHelp, error) {
    55  	// The Config field is omitted because this plugin is not configurable.
    56  	pluginHelp := &pluginhelp.PluginHelp{
    57  		Description: labels.Shrug,
    58  	}
    59  	pluginHelp.AddCommand(pluginhelp.Command{
    60  		Usage:       "/[un]shrug",
    61  		Description: labels.Shrug,
    62  		Featured:    false,
    63  		WhoCanUse:   "Anyone, " + labels.Shrug,
    64  		Examples:    []string{"/shrug", "/unshrug"},
    65  	})
    66  	return pluginHelp, nil
    67  }
    68  
    69  type githubClient interface {
    70  	AddLabel(owner, repo string, number int, label string) error
    71  	CreateComment(owner, repo string, number int, comment string) error
    72  	RemoveLabel(owner, repo string, number int, label string) error
    73  	GetIssueLabels(org, repo string, number int) ([]github.Label, error)
    74  }
    75  
    76  func handleGenericComment(pc plugins.Agent, e github.GenericCommentEvent) error {
    77  	return handle(pc.GitHubClient, pc.Logger, &e)
    78  }
    79  
    80  func handle(gc githubClient, log *logrus.Entry, e *github.GenericCommentEvent) error {
    81  	if e.Action != github.GenericCommentActionCreated {
    82  		return nil
    83  	}
    84  
    85  	wantShrug := false
    86  	if shrugRe.MatchString(e.Body) {
    87  		wantShrug = true
    88  	} else if unshrugRe.MatchString(e.Body) {
    89  		wantShrug = false
    90  	} else {
    91  		return nil
    92  	}
    93  
    94  	org := e.Repo.Owner.Login
    95  	repo := e.Repo.Name
    96  
    97  	// Only add the label if it doesn't have it yet.
    98  	hasShrug := false
    99  	issueLabels, err := gc.GetIssueLabels(org, repo, e.Number)
   100  	if err != nil {
   101  		log.WithError(err).Errorf("Failed to get the labels on %s/%s#%d.", org, repo, e.Number)
   102  	}
   103  	for _, candidate := range issueLabels {
   104  		if candidate.Name == labels.Shrug {
   105  			hasShrug = true
   106  			break
   107  		}
   108  	}
   109  	if hasShrug && !wantShrug {
   110  		log.Info("Removing Shrug label.")
   111  		resp := "¯\\\\\\_(ツ)\\_/¯"
   112  		log.Infof("Commenting with \"%s\".", resp)
   113  		if err := gc.CreateComment(org, repo, e.Number, plugins.FormatResponseRaw(e.Body, e.HTMLURL, e.User.Login, resp)); err != nil {
   114  			return fmt.Errorf("failed to comment on %s/%s#%d: %v", org, repo, e.Number, err)
   115  		}
   116  		return gc.RemoveLabel(org, repo, e.Number, labels.Shrug)
   117  	} else if !hasShrug && wantShrug {
   118  		log.Info("Adding Shrug label.")
   119  		return gc.AddLabel(org, repo, e.Number, labels.Shrug)
   120  	}
   121  	return nil
   122  }