github.com/munnerz/test-infra@v0.0.0-20190108210205-ce3d181dc989/prow/plugins/heart/heart.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 heart 18 19 import ( 20 "fmt" 21 "math/rand" 22 "path/filepath" 23 "regexp" 24 "strings" 25 26 "github.com/sirupsen/logrus" 27 28 "k8s.io/test-infra/prow/github" 29 "k8s.io/test-infra/prow/pluginhelp" 30 "k8s.io/test-infra/prow/plugins" 31 ) 32 33 const ( 34 pluginName = "heart" 35 ownersFilename = "OWNERS" 36 ownersAliasesFilename = "OWNERS_ALIASES" 37 ) 38 39 var reactions = []string{ 40 github.ReactionThumbsUp, 41 github.ReactionLaugh, 42 github.ReactionHeart, 43 github.ReactionHooray, 44 } 45 46 func init() { 47 plugins.RegisterIssueCommentHandler(pluginName, handleIssueComment, helpProvider) 48 plugins.RegisterPullRequestHandler(pluginName, handlePullRequest, helpProvider) 49 } 50 51 func helpProvider(config *plugins.Configuration, enabledRepos []string) (*pluginhelp.PluginHelp, error) { 52 // The {WhoCanUse, Usage, Examples} fields are omitted because this plugin is not triggered with commands. 53 return &pluginhelp.PluginHelp{ 54 Description: "The heart plugin celebrates certain Github actions with the reaction emojis. Emojis are added to pull requests that make additions to OWNERS or OWNERS_ALIASES files and to comments left by specified \"adorees\".", 55 Config: map[string]string{ 56 "": fmt.Sprintf( 57 "The heart plugin is configured to react to comments, satisfying the regular expression %s, left by the following Github users: %s.", 58 config.Heart.CommentRegexp, 59 strings.Join(config.Heart.Adorees, ", "), 60 ), 61 }, 62 }, 63 nil 64 } 65 66 type githubClient interface { 67 CreateCommentReaction(org, repo string, ID int, reaction string) error 68 CreateIssueReaction(org, repo string, ID int, reaction string) error 69 GetPullRequestChanges(org, repo string, number int) ([]github.PullRequestChange, error) 70 } 71 72 type client struct { 73 GitHubClient githubClient 74 Logger *logrus.Entry 75 } 76 77 func getClient(pc plugins.Agent) client { 78 return client{ 79 GitHubClient: pc.GitHubClient, 80 Logger: pc.Logger, 81 } 82 } 83 84 func handleIssueComment(pc plugins.Agent, ic github.IssueCommentEvent) error { 85 if (pc.PluginConfig.Heart.Adorees == nil || len(pc.PluginConfig.Heart.Adorees) == 0) || len(pc.PluginConfig.Heart.CommentRegexp) == 0 { 86 return nil 87 } 88 return handleIC(getClient(pc), pc.PluginConfig.Heart.Adorees, pc.PluginConfig.Heart.CommentRe, ic) 89 } 90 91 func handlePullRequest(pc plugins.Agent, pre github.PullRequestEvent) error { 92 return handlePR(getClient(pc), pre) 93 } 94 95 func handleIC(c client, adorees []string, commentRe *regexp.Regexp, ic github.IssueCommentEvent) error { 96 // Only consider new comments on PRs. 97 if !ic.Issue.IsPullRequest() || ic.Action != github.IssueCommentActionCreated { 98 return nil 99 } 100 adoredLogin := false 101 for _, login := range adorees { 102 if ic.Comment.User.Login == login { 103 adoredLogin = true 104 break 105 } 106 } 107 if !adoredLogin { 108 return nil 109 } 110 111 if !commentRe.MatchString(ic.Comment.Body) { 112 return nil 113 } 114 115 c.Logger.Info("This is a wonderful thing!") 116 return c.GitHubClient.CreateCommentReaction( 117 ic.Repo.Owner.Login, 118 ic.Repo.Name, 119 ic.Comment.ID, 120 reactions[rand.Intn(len(reactions))]) 121 } 122 123 func handlePR(c client, pre github.PullRequestEvent) error { 124 // Only consider newly opened PRs 125 if pre.Action != github.PullRequestActionOpened { 126 return nil 127 } 128 129 org := pre.PullRequest.Base.Repo.Owner.Login 130 repo := pre.PullRequest.Base.Repo.Name 131 132 changes, err := c.GitHubClient.GetPullRequestChanges(org, repo, pre.PullRequest.Number) 133 if err != nil { 134 return err 135 } 136 137 // Smile at any change that adds to OWNERS files 138 for _, change := range changes { 139 _, filename := filepath.Split(change.Filename) 140 if (filename == ownersFilename || filename == ownersAliasesFilename) && change.Additions > 0 { 141 c.Logger.Info("Adding new OWNERS makes me happy!") 142 return c.GitHubClient.CreateIssueReaction( 143 pre.PullRequest.Base.Repo.Owner.Login, 144 pre.PullRequest.Base.Repo.Name, 145 pre.Number, 146 reactions[rand.Intn(len(reactions))]) 147 } 148 } 149 150 return nil 151 }