github.com/shashidharatd/test-infra@v0.0.0-20171006011030-71304e1ca560/prow/plugins/slackevents/slackevents.go (about)

     1  /*
     2  Copyright 2016 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 slackevents
    18  
    19  import (
    20  	"fmt"
    21  	"regexp"
    22  
    23  	"k8s.io/test-infra/prow/github"
    24  	"k8s.io/test-infra/prow/plugins"
    25  )
    26  
    27  const (
    28  	pluginName = "slackevents"
    29  )
    30  
    31  var sigMatcher = regexp.MustCompile(`(?m)@kubernetes/sig-([\w-]*)-(misc|test-failures|bugs|feature-requests|proposals|pr-reviews|api-reviews)`)
    32  
    33  type slackClient interface {
    34  	WriteMessage(text string, channel string) error
    35  }
    36  
    37  type githubClient interface {
    38  	BotName() (string, error)
    39  }
    40  
    41  type client struct {
    42  	GithubClient githubClient
    43  	SlackClient  slackClient
    44  	SlackConfig  plugins.Slack
    45  }
    46  
    47  func init() {
    48  	plugins.RegisterPushEventHandler(pluginName, handlePush)
    49  	plugins.RegisterGenericCommentHandler(pluginName, handleComment)
    50  }
    51  
    52  func handleComment(pc plugins.PluginClient, e github.GenericCommentEvent) error {
    53  	c := client{
    54  		GithubClient: pc.GitHubClient,
    55  		SlackConfig:  pc.PluginConfig.Slack,
    56  		SlackClient:  pc.SlackClient,
    57  	}
    58  	return echoToSlack(c, e)
    59  }
    60  
    61  func handlePush(pc plugins.PluginClient, pe github.PushEvent) error {
    62  	c := client{
    63  		GithubClient: pc.GitHubClient,
    64  		SlackConfig:  pc.PluginConfig.Slack,
    65  		SlackClient:  pc.SlackClient,
    66  	}
    67  	return notifyOnSlackIfManualMerge(c, pe)
    68  }
    69  
    70  func notifyOnSlackIfManualMerge(pc client, pe github.PushEvent) error {
    71  	//Fetch slackevent configuration for the repo we received the merge event.
    72  	if se := getSlackEvent(pc.SlackConfig.MergeWarnings, pe.Repo.Owner.Login, pe.Repo.Name); se != nil {
    73  		//If the slackevent whitelist has the merge user then no need to send a message.
    74  		if !stringInArray(pe.Pusher.Name, se.WhiteList) && !stringInArray(pe.Sender.Login, se.WhiteList) {
    75  			message := fmt.Sprintf("Warning: <@%s> manually merged %s", pe.Sender.Login, pe.Compare)
    76  			for _, channel := range se.Channels {
    77  				if err := pc.SlackClient.WriteMessage(message, channel); err != nil {
    78  					return err
    79  				}
    80  			}
    81  		}
    82  	}
    83  	return nil
    84  }
    85  
    86  func getSlackEvent(slackEvents []plugins.MergeWarning, org, repo string) *plugins.MergeWarning {
    87  	for _, se := range slackEvents {
    88  		if stringInArray(org, se.Repos) || stringInArray(fmt.Sprintf("%s/%s", org, repo), se.Repos) {
    89  			return &se
    90  		}
    91  	}
    92  	return nil
    93  }
    94  
    95  func stringInArray(str string, list []string) bool {
    96  	for _, v := range list {
    97  		if v == str {
    98  			return true
    99  		}
   100  	}
   101  	return false
   102  }
   103  
   104  func echoToSlack(pc client, e github.GenericCommentEvent) error {
   105  	// Ignore bot comments and comments that aren't new.
   106  	botName, err := pc.GithubClient.BotName()
   107  	if err != nil {
   108  		return err
   109  	}
   110  	if e.User.Login == botName {
   111  		return nil
   112  	}
   113  	if e.Action != github.GenericCommentActionCreated {
   114  		return nil
   115  	}
   116  
   117  	sigMatches := sigMatcher.FindAllStringSubmatch(e.Body, -1)
   118  
   119  	for _, match := range sigMatches {
   120  		sig := "sig-" + match[1]
   121  		// Check if this sig is a slack channel that should be messaged.
   122  		found := false
   123  		for _, channel := range pc.SlackConfig.MentionChannels {
   124  			if channel == sig {
   125  				found = true
   126  				break
   127  			}
   128  		}
   129  		if !found {
   130  			continue
   131  		}
   132  
   133  		msg := fmt.Sprintf("%s was mentioned by <@%s> on Github. (%s)\n>>>%s", sig, e.User.Login, e.HTMLURL, e.Body)
   134  		if err := pc.SlackClient.WriteMessage(msg, sig); err != nil {
   135  			return fmt.Errorf("Failed to send message on slack channel: %q with message %q. Err: %v", sig, msg, err)
   136  		}
   137  	}
   138  	return nil
   139  }