github.com/abayer/test-infra@v0.0.5/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 ) 37 38 var mergeRe = regexp.MustCompile(`Automatic merge from submit-queue`) 39 40 var reactions = []string{ 41 github.ReactionThumbsUp, 42 github.ReactionLaugh, 43 github.ReactionHeart, 44 github.ReactionHooray, 45 } 46 47 func init() { 48 plugins.RegisterIssueCommentHandler(pluginName, handleIssueComment, helpProvider) 49 plugins.RegisterPullRequestHandler(pluginName, handlePullRequest, helpProvider) 50 } 51 52 func helpProvider(config *plugins.Configuration, enabledRepos []string) (*pluginhelp.PluginHelp, error) { 53 // The {WhoCanUse, Usage, Examples} fields are omitted because this plugin is not triggered with commands. 54 return &pluginhelp.PluginHelp{ 55 Description: "The heart plugin celebrates certain Github actions with the reaction emojis. Emojis are added to merge notifications left by mungegithub's submit-queue and to pull requests that make additions to OWNERS files.", 56 Config: map[string]string{ 57 "": fmt.Sprintf( 58 "The heart plugin is configured to react to merge notifications left by the following Github users: %s.", 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.PluginClient) client { 78 return client{ 79 GitHubClient: pc.GitHubClient, 80 Logger: pc.Logger, 81 } 82 } 83 84 func handleIssueComment(pc plugins.PluginClient, ic github.IssueCommentEvent) error { 85 return handleIC(getClient(pc), pc.PluginConfig.Heart.Adorees, ic) 86 } 87 88 func handlePullRequest(pc plugins.PluginClient, pre github.PullRequestEvent) error { 89 return handlePR(getClient(pc), pre) 90 } 91 92 func handleIC(c client, adorees []string, ic github.IssueCommentEvent) error { 93 // Only consider new comments on PRs. 94 if !ic.Issue.IsPullRequest() || ic.Action != github.IssueCommentActionCreated { 95 return nil 96 } 97 adoredLogin := false 98 for _, login := range adorees { 99 if ic.Comment.User.Login == login { 100 adoredLogin = true 101 break 102 } 103 } 104 if !adoredLogin { 105 return nil 106 } 107 108 if !mergeRe.MatchString(ic.Comment.Body) { 109 return nil 110 } 111 112 c.Logger.Info("This is a wonderful thing!") 113 return c.GitHubClient.CreateCommentReaction( 114 ic.Repo.Owner.Login, 115 ic.Repo.Name, 116 ic.Comment.ID, 117 reactions[rand.Intn(len(reactions))]) 118 } 119 120 func handlePR(c client, pre github.PullRequestEvent) error { 121 // Only consider newly opened PRs 122 if pre.Action != github.PullRequestActionOpened { 123 return nil 124 } 125 126 org := pre.PullRequest.Base.Repo.Owner.Login 127 repo := pre.PullRequest.Base.Repo.Name 128 129 changes, err := c.GitHubClient.GetPullRequestChanges(org, repo, pre.PullRequest.Number) 130 if err != nil { 131 return err 132 } 133 134 // Smile at any change that adds to OWNERS files 135 for _, change := range changes { 136 _, filename := filepath.Split(change.Filename) 137 if filename == ownersFilename && change.Additions > 0 { 138 c.Logger.Info("Adding new OWNERS makes me happy!") 139 return c.GitHubClient.CreateIssueReaction( 140 pre.PullRequest.Base.Repo.Owner.Login, 141 pre.PullRequest.Base.Repo.Name, 142 pre.Number, 143 reactions[rand.Intn(len(reactions))]) 144 } 145 } 146 147 return nil 148 }