github.com/abayer/test-infra@v0.0.5/prow/hook/events.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 hook 18 19 import ( 20 "github.com/sirupsen/logrus" 21 22 "k8s.io/test-infra/prow/commentpruner" 23 "k8s.io/test-infra/prow/github" 24 "k8s.io/test-infra/prow/plugins" 25 ) 26 27 const failedCommentCoerceFmt = "Could not coerce %s event to a GenericCommentEvent. Unknown 'action': %q." 28 29 var ( 30 nonCommentIssueActions = map[github.IssueEventAction]bool{ 31 github.IssueActionAssigned: true, 32 github.IssueActionUnassigned: true, 33 github.IssueActionLabeled: true, 34 github.IssueActionUnlabeled: true, 35 github.IssueActionMilestoned: true, 36 github.IssueActionDemilestoned: true, 37 github.IssueActionClosed: true, 38 github.IssueActionReopened: true, 39 } 40 nonCommentPullRequestActions = map[github.PullRequestEventAction]bool{ 41 github.PullRequestActionAssigned: true, 42 github.PullRequestActionUnassigned: true, 43 github.PullRequestActionReviewRequested: true, 44 github.PullRequestActionReviewRequestRemoved: true, 45 github.PullRequestActionLabeled: true, 46 github.PullRequestActionUnlabeled: true, 47 github.PullRequestActionClosed: true, 48 github.PullRequestActionReopened: true, 49 github.PullRequestActionSynchronize: true, 50 } 51 ) 52 53 func (s *Server) handleReviewEvent(l *logrus.Entry, re github.ReviewEvent) { 54 defer s.wg.Done() 55 l = l.WithFields(logrus.Fields{ 56 github.OrgLogField: re.Repo.Owner.Login, 57 github.RepoLogField: re.Repo.Name, 58 github.PrLogField: re.PullRequest.Number, 59 "review": re.Review.ID, 60 "reviewer": re.Review.User.Login, 61 "url": re.Review.HTMLURL, 62 }) 63 l.Infof("Review %s.", re.Action) 64 for p, h := range s.Plugins.ReviewEventHandlers(re.PullRequest.Base.Repo.Owner.Login, re.PullRequest.Base.Repo.Name) { 65 s.wg.Add(1) 66 go func(p string, h plugins.ReviewEventHandler) { 67 defer s.wg.Done() 68 pc := s.Plugins.PluginClient 69 pc.Logger = l.WithField("plugin", p) 70 pc.Config = s.ConfigAgent.Config() 71 pc.PluginConfig = s.Plugins.Config() 72 pc.CommentPruner = commentpruner.NewEventClient( 73 pc.GitHubClient, 74 l.WithField("client", "commentpruner"), 75 re.Repo.Owner.Login, 76 re.Repo.Name, 77 re.PullRequest.Number, 78 ) 79 if err := h(pc, re); err != nil { 80 pc.Logger.WithError(err).Error("Error handling ReviewEvent.") 81 } 82 }(p, h) 83 } 84 action := genericCommentAction(string(re.Action)) 85 if action == "" { 86 l.Errorf(failedCommentCoerceFmt, "pull_request_review", string(re.Action)) 87 return 88 } 89 s.handleGenericComment( 90 l, 91 &github.GenericCommentEvent{ 92 GUID: re.GUID, 93 IsPR: true, 94 Action: action, 95 Body: re.Review.Body, 96 HTMLURL: re.Review.HTMLURL, 97 Number: re.PullRequest.Number, 98 Repo: re.Repo, 99 User: re.Review.User, 100 IssueAuthor: re.PullRequest.User, 101 Assignees: re.PullRequest.Assignees, 102 IssueState: re.PullRequest.State, 103 IssueBody: re.PullRequest.Body, 104 IssueHTMLURL: re.PullRequest.HTMLURL, 105 }, 106 ) 107 } 108 109 func (s *Server) handleReviewCommentEvent(l *logrus.Entry, rce github.ReviewCommentEvent) { 110 defer s.wg.Done() 111 l = l.WithFields(logrus.Fields{ 112 github.OrgLogField: rce.Repo.Owner.Login, 113 github.RepoLogField: rce.Repo.Name, 114 github.PrLogField: rce.PullRequest.Number, 115 "review": rce.Comment.ReviewID, 116 "commenter": rce.Comment.User.Login, 117 "url": rce.Comment.HTMLURL, 118 }) 119 l.Infof("Review comment %s.", rce.Action) 120 for p, h := range s.Plugins.ReviewCommentEventHandlers(rce.PullRequest.Base.Repo.Owner.Login, rce.PullRequest.Base.Repo.Name) { 121 s.wg.Add(1) 122 go func(p string, h plugins.ReviewCommentEventHandler) { 123 defer s.wg.Done() 124 pc := s.Plugins.PluginClient 125 pc.Logger = l.WithField("plugin", p) 126 pc.Config = s.ConfigAgent.Config() 127 pc.PluginConfig = s.Plugins.Config() 128 pc.CommentPruner = commentpruner.NewEventClient( 129 pc.GitHubClient, 130 l.WithField("client", "commentpruner"), 131 rce.Repo.Owner.Login, 132 rce.Repo.Name, 133 rce.PullRequest.Number, 134 ) 135 if err := h(pc, rce); err != nil { 136 pc.Logger.WithError(err).Error("Error handling ReviewCommentEvent.") 137 } 138 }(p, h) 139 } 140 action := genericCommentAction(string(rce.Action)) 141 if action == "" { 142 l.Errorf(failedCommentCoerceFmt, "pull_request_review_comment", string(rce.Action)) 143 return 144 } 145 s.handleGenericComment( 146 l, 147 &github.GenericCommentEvent{ 148 GUID: rce.GUID, 149 IsPR: true, 150 Action: action, 151 Body: rce.Comment.Body, 152 HTMLURL: rce.Comment.HTMLURL, 153 Number: rce.PullRequest.Number, 154 Repo: rce.Repo, 155 User: rce.Comment.User, 156 IssueAuthor: rce.PullRequest.User, 157 Assignees: rce.PullRequest.Assignees, 158 IssueState: rce.PullRequest.State, 159 IssueBody: rce.PullRequest.Body, 160 IssueHTMLURL: rce.PullRequest.HTMLURL, 161 }, 162 ) 163 } 164 165 func (s *Server) handlePullRequestEvent(l *logrus.Entry, pr github.PullRequestEvent) { 166 defer s.wg.Done() 167 l = l.WithFields(logrus.Fields{ 168 github.OrgLogField: pr.Repo.Owner.Login, 169 github.RepoLogField: pr.Repo.Name, 170 github.PrLogField: pr.Number, 171 "author": pr.PullRequest.User.Login, 172 "url": pr.PullRequest.HTMLURL, 173 }) 174 l.Infof("Pull request %s.", pr.Action) 175 for p, h := range s.Plugins.PullRequestHandlers(pr.PullRequest.Base.Repo.Owner.Login, pr.PullRequest.Base.Repo.Name) { 176 s.wg.Add(1) 177 go func(p string, h plugins.PullRequestHandler) { 178 defer s.wg.Done() 179 pc := s.Plugins.PluginClient 180 pc.Logger = l.WithField("plugin", p) 181 pc.Config = s.ConfigAgent.Config() 182 pc.PluginConfig = s.Plugins.Config() 183 pc.CommentPruner = commentpruner.NewEventClient( 184 pc.GitHubClient, 185 l.WithField("client", "commentpruner"), 186 pr.Repo.Owner.Login, 187 pr.Repo.Name, 188 pr.PullRequest.Number, 189 ) 190 if err := h(pc, pr); err != nil { 191 pc.Logger.WithError(err).Error("Error handling PullRequestEvent.") 192 } 193 }(p, h) 194 } 195 action := genericCommentAction(string(pr.Action)) 196 if action == "" { 197 if !nonCommentPullRequestActions[pr.Action] { 198 l.Errorf(failedCommentCoerceFmt, "pull_request", string(pr.Action)) 199 } 200 return 201 } 202 s.handleGenericComment( 203 l, 204 &github.GenericCommentEvent{ 205 GUID: pr.GUID, 206 IsPR: true, 207 Action: action, 208 Body: pr.PullRequest.Body, 209 HTMLURL: pr.PullRequest.HTMLURL, 210 Number: pr.PullRequest.Number, 211 Repo: pr.Repo, 212 User: pr.PullRequest.User, 213 IssueAuthor: pr.PullRequest.User, 214 Assignees: pr.PullRequest.Assignees, 215 IssueState: pr.PullRequest.State, 216 IssueBody: pr.PullRequest.Body, 217 IssueHTMLURL: pr.PullRequest.HTMLURL, 218 }, 219 ) 220 } 221 222 func (s *Server) handlePushEvent(l *logrus.Entry, pe github.PushEvent) { 223 defer s.wg.Done() 224 l = l.WithFields(logrus.Fields{ 225 github.OrgLogField: pe.Repo.Owner.Name, 226 github.RepoLogField: pe.Repo.Name, 227 "ref": pe.Ref, 228 "head": pe.After, 229 }) 230 l.Info("Push event.") 231 for p, h := range s.Plugins.PushEventHandlers(pe.Repo.Owner.Name, pe.Repo.Name) { 232 s.wg.Add(1) 233 go func(p string, h plugins.PushEventHandler) { 234 defer s.wg.Done() 235 pc := s.Plugins.PluginClient 236 pc.Logger = l.WithField("plugin", p) 237 pc.Config = s.ConfigAgent.Config() 238 pc.PluginConfig = s.Plugins.Config() 239 if err := h(pc, pe); err != nil { 240 pc.Logger.WithError(err).Error("Error handling PushEvent.") 241 } 242 }(p, h) 243 } 244 } 245 246 func (s *Server) handleIssueEvent(l *logrus.Entry, i github.IssueEvent) { 247 defer s.wg.Done() 248 l = l.WithFields(logrus.Fields{ 249 github.OrgLogField: i.Repo.Owner.Login, 250 github.RepoLogField: i.Repo.Name, 251 github.PrLogField: i.Issue.Number, 252 "author": i.Issue.User.Login, 253 "url": i.Issue.HTMLURL, 254 }) 255 l.Infof("Issue %s.", i.Action) 256 for p, h := range s.Plugins.IssueHandlers(i.Repo.Owner.Login, i.Repo.Name) { 257 s.wg.Add(1) 258 go func(p string, h plugins.IssueHandler) { 259 defer s.wg.Done() 260 pc := s.Plugins.PluginClient 261 pc.Logger = l.WithField("plugin", p) 262 pc.Config = s.ConfigAgent.Config() 263 pc.PluginConfig = s.Plugins.Config() 264 pc.CommentPruner = commentpruner.NewEventClient( 265 pc.GitHubClient, 266 l.WithField("client", "commentpruner"), 267 i.Repo.Owner.Login, 268 i.Repo.Name, 269 i.Issue.Number, 270 ) 271 if err := h(pc, i); err != nil { 272 pc.Logger.WithError(err).Error("Error handling IssueEvent.") 273 } 274 }(p, h) 275 } 276 action := genericCommentAction(string(i.Action)) 277 if action == "" { 278 if !nonCommentIssueActions[i.Action] { 279 l.Errorf(failedCommentCoerceFmt, "pull_request", string(i.Action)) 280 } 281 return 282 } 283 s.handleGenericComment( 284 l, 285 &github.GenericCommentEvent{ 286 GUID: i.GUID, 287 IsPR: i.Issue.IsPullRequest(), 288 Action: action, 289 Body: i.Issue.Body, 290 HTMLURL: i.Issue.HTMLURL, 291 Number: i.Issue.Number, 292 Repo: i.Repo, 293 User: i.Issue.User, 294 IssueAuthor: i.Issue.User, 295 Assignees: i.Issue.Assignees, 296 IssueState: i.Issue.State, 297 IssueBody: i.Issue.Body, 298 IssueHTMLURL: i.Issue.HTMLURL, 299 }, 300 ) 301 } 302 303 func (s *Server) handleIssueCommentEvent(l *logrus.Entry, ic github.IssueCommentEvent) { 304 defer s.wg.Done() 305 l = l.WithFields(logrus.Fields{ 306 github.OrgLogField: ic.Repo.Owner.Login, 307 github.RepoLogField: ic.Repo.Name, 308 github.PrLogField: ic.Issue.Number, 309 "author": ic.Comment.User.Login, 310 "url": ic.Comment.HTMLURL, 311 }) 312 l.Infof("Issue comment %s.", ic.Action) 313 for p, h := range s.Plugins.IssueCommentHandlers(ic.Repo.Owner.Login, ic.Repo.Name) { 314 s.wg.Add(1) 315 go func(p string, h plugins.IssueCommentHandler) { 316 defer s.wg.Done() 317 pc := s.Plugins.PluginClient 318 pc.Logger = l.WithField("plugin", p) 319 pc.Config = s.ConfigAgent.Config() 320 pc.PluginConfig = s.Plugins.Config() 321 pc.CommentPruner = commentpruner.NewEventClient( 322 pc.GitHubClient, 323 l.WithField("client", "commentpruner"), 324 ic.Repo.Owner.Login, 325 ic.Repo.Name, 326 ic.Issue.Number, 327 ) 328 if err := h(pc, ic); err != nil { 329 pc.Logger.WithError(err).Error("Error handling IssueCommentEvent.") 330 } 331 }(p, h) 332 } 333 action := genericCommentAction(string(ic.Action)) 334 if action == "" { 335 l.Errorf(failedCommentCoerceFmt, "issue_comment", string(ic.Action)) 336 return 337 } 338 s.handleGenericComment( 339 l, 340 &github.GenericCommentEvent{ 341 GUID: ic.GUID, 342 IsPR: ic.Issue.IsPullRequest(), 343 Action: action, 344 Body: ic.Comment.Body, 345 HTMLURL: ic.Comment.HTMLURL, 346 Number: ic.Issue.Number, 347 Repo: ic.Repo, 348 User: ic.Comment.User, 349 IssueAuthor: ic.Issue.User, 350 Assignees: ic.Issue.Assignees, 351 IssueState: ic.Issue.State, 352 IssueBody: ic.Issue.Body, 353 IssueHTMLURL: ic.Issue.HTMLURL, 354 }, 355 ) 356 } 357 358 func (s *Server) handleStatusEvent(l *logrus.Entry, se github.StatusEvent) { 359 defer s.wg.Done() 360 l = l.WithFields(logrus.Fields{ 361 github.OrgLogField: se.Repo.Owner.Login, 362 github.RepoLogField: se.Repo.Name, 363 "context": se.Context, 364 "sha": se.SHA, 365 "state": se.State, 366 "id": se.ID, 367 }) 368 l.Infof("Status description %s.", se.Description) 369 for p, h := range s.Plugins.StatusEventHandlers(se.Repo.Owner.Login, se.Repo.Name) { 370 s.wg.Add(1) 371 go func(p string, h plugins.StatusEventHandler) { 372 defer s.wg.Done() 373 pc := s.Plugins.PluginClient 374 pc.Logger = l.WithField("plugin", p) 375 pc.Config = s.ConfigAgent.Config() 376 pc.PluginConfig = s.Plugins.Config() 377 if err := h(pc, se); err != nil { 378 pc.Logger.WithError(err).Error("Error handling StatusEvent.") 379 } 380 }(p, h) 381 } 382 } 383 384 // genericCommentAction normalizes the action string to a GenericCommentEventAction or returns "" 385 // if the action is unrelated to the comment text. (For example a PR 'label' action.) 386 func genericCommentAction(action string) github.GenericCommentEventAction { 387 switch action { 388 case "created", "opened", "submitted": 389 return github.GenericCommentActionCreated 390 case "edited": 391 return github.GenericCommentActionEdited 392 case "deleted", "dismissed": 393 return github.GenericCommentActionDeleted 394 } 395 // The action is not related to the text body. 396 return "" 397 } 398 399 func (s *Server) handleGenericComment(l *logrus.Entry, ce *github.GenericCommentEvent) { 400 for p, h := range s.Plugins.GenericCommentHandlers(ce.Repo.Owner.Login, ce.Repo.Name) { 401 s.wg.Add(1) 402 go func(p string, h plugins.GenericCommentHandler) { 403 defer s.wg.Done() 404 pc := s.Plugins.PluginClient 405 pc.Logger = l.WithField("plugin", p) 406 pc.Config = s.ConfigAgent.Config() 407 pc.PluginConfig = s.Plugins.Config() 408 pc.CommentPruner = commentpruner.NewEventClient( 409 pc.GitHubClient, 410 l.WithField("client", "commentpruner"), 411 ce.Repo.Owner.Login, 412 ce.Repo.Name, 413 ce.Number, 414 ) 415 if err := h(pc, *ce); err != nil { 416 pc.Logger.WithError(err).Error("Error handling GenericCommentEvent.") 417 } 418 }(p, h) 419 } 420 }