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  }