github.com/shashidharatd/test-infra@v0.0.0-20171006011030-71304e1ca560/prow/plugins/trigger/ic.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 trigger 18 19 import ( 20 "fmt" 21 "regexp" 22 23 "k8s.io/test-infra/prow/github" 24 "k8s.io/test-infra/prow/kube" 25 "k8s.io/test-infra/prow/pjutil" 26 "k8s.io/test-infra/prow/plugins" 27 ) 28 29 var okToTest = regexp.MustCompile(`(?m)^/ok-to-test\s*$`) 30 var retest = regexp.MustCompile(`(?m)^/retest\s*$`) 31 32 func handleIC(c client, trustedOrg string, ic github.IssueCommentEvent) error { 33 org := ic.Repo.Owner.Login 34 repo := ic.Repo.Name 35 number := ic.Issue.Number 36 commentAuthor := ic.Comment.User.Login 37 // Only take action when a comment is first created. 38 if ic.Action != github.IssueCommentActionCreated { 39 return nil 40 } 41 // If it's not an open PR, skip it. 42 if !ic.Issue.IsPullRequest() { 43 return nil 44 } 45 if ic.Issue.State != "open" { 46 return nil 47 } 48 // Skip bot comments. 49 botName, err := c.GitHubClient.BotName() 50 if err != nil { 51 return err 52 } 53 if commentAuthor == botName { 54 return nil 55 } 56 57 // Which jobs does the comment want us to run? 58 shouldRetestFailed := retest.MatchString(ic.Comment.Body) 59 requestedJobs := c.Config.MatchingPresubmits(ic.Repo.FullName, ic.Comment.Body, okToTest) 60 if !shouldRetestFailed && len(requestedJobs) == 0 { 61 // Check for the presence of the needs-ok-to-test label and remove it 62 // if a trusted member has commented "/ok-to-test". 63 if okToTest.MatchString(ic.Comment.Body) && ic.Issue.HasLabel(needsOkToTest) { 64 orgMember, err := c.GitHubClient.IsMember(trustedOrg, commentAuthor) 65 if err != nil { 66 return err 67 } 68 if orgMember { 69 return c.GitHubClient.RemoveLabel(ic.Repo.Owner.Login, ic.Repo.Name, ic.Issue.Number, needsOkToTest) 70 } 71 } 72 return nil 73 } 74 75 pr, err := c.GitHubClient.GetPullRequest(org, repo, number) 76 if err != nil { 77 return err 78 } 79 80 if shouldRetestFailed { 81 combinedStatus, err := c.GitHubClient.GetCombinedStatus(org, repo, pr.Head.SHA) 82 if err != nil { 83 return err 84 } 85 skipContexts := make(map[string]bool) // these succeeded or are running 86 runContexts := make(map[string]bool) // these failed and should be re-run 87 for _, status := range combinedStatus.Statuses { 88 state := status.State 89 if state == github.StatusSuccess || state == github.StatusPending { 90 skipContexts[status.Context] = true 91 } else if state == github.StatusError || state == github.StatusFailure { 92 runContexts[status.Context] = true 93 } 94 } 95 requestedJobs = append(requestedJobs, c.Config.RetestPresubmits(ic.Repo.FullName, skipContexts, runContexts)...) 96 } 97 98 // Skip untrusted users. 99 orgMember, err := c.GitHubClient.IsMember(trustedOrg, commentAuthor) 100 if err != nil { 101 return err 102 } else if !orgMember { 103 trusted, err := trustedPullRequest(c.GitHubClient, *pr, trustedOrg) 104 if err != nil { 105 return err 106 } 107 if !trusted { 108 resp := fmt.Sprintf("you can't request testing unless you are a [%s](https://github.com/orgs/%s/people) member.", trustedOrg, trustedOrg) 109 c.Logger.Infof("Commenting \"%s\".", resp) 110 return c.GitHubClient.CreateComment(org, repo, number, plugins.FormatICResponse(ic.Comment, resp)) 111 } 112 } 113 114 if okToTest.MatchString(ic.Comment.Body) && ic.Issue.HasLabel(needsOkToTest) { 115 if err := c.GitHubClient.RemoveLabel(ic.Repo.Owner.Login, ic.Repo.Name, ic.Issue.Number, needsOkToTest); err != nil { 116 c.Logger.WithError(err).Errorf("Failed at removing %s label", needsOkToTest) 117 } 118 } 119 120 ref, err := c.GitHubClient.GetRef(org, repo, "heads/"+pr.Base.Ref) 121 if err != nil { 122 return err 123 } 124 125 var errors []error 126 for _, job := range requestedJobs { 127 if !job.RunsAgainstBranch(pr.Base.Ref) { 128 if err := c.GitHubClient.CreateStatus(org, repo, pr.Head.SHA, github.Status{ 129 State: github.StatusSuccess, 130 Context: job.Context, 131 Description: "Skipped", 132 }); err != nil { 133 return err 134 } 135 continue 136 } 137 c.Logger.Infof("Starting %s build.", job.Name) 138 kr := kube.Refs{ 139 Org: org, 140 Repo: repo, 141 BaseRef: pr.Base.Ref, 142 BaseSHA: ref, 143 Pulls: []kube.Pull{ 144 { 145 Number: number, 146 Author: pr.User.Login, 147 SHA: pr.Head.SHA, 148 }, 149 }, 150 } 151 if _, err := c.KubeClient.CreateProwJob(pjutil.NewProwJob(pjutil.PresubmitSpec(job, kr))); err != nil { 152 errors = append(errors, err) 153 } 154 } 155 if len(errors) > 0 { 156 return fmt.Errorf("errors starting jobs: %v", errors) 157 } 158 return nil 159 }