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