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 }