github.com/shashidharatd/test-infra@v0.0.0-20171006011030-71304e1ca560/mungegithub/mungers/nag-flake-issues.go (about) 1 /* 2 Copyright 2015 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 mungers 18 19 import ( 20 "time" 21 22 "github.com/google/go-github/github" 23 "k8s.io/kubernetes/pkg/util/sets" 24 "k8s.io/test-infra/mungegithub/features" 25 mgh "k8s.io/test-infra/mungegithub/github" 26 c "k8s.io/test-infra/mungegithub/mungers/matchers/comment" 27 "k8s.io/test-infra/mungegithub/mungers/mungerutil" 28 "k8s.io/test-infra/mungegithub/options" 29 ) 30 31 const ( 32 flakeNagNotifyName = "FLAKE-PING" 33 // defaultTimePeriod is priority/P1 (to get a human to prioritize) 34 defaultTimePeriod = 4 * 24 * time.Hour 35 ) 36 37 var ( 38 // Only include priorities that you care about. Others won't be pinged 39 timePeriods = map[string]time.Duration{ 40 "priority/P0": 2 * 24 * time.Hour, 41 "priority/P1": 8 * 24 * time.Hour, 42 "priority/P2": time.Duration(1<<63 - 1), 43 "priority/P3": time.Duration(1<<63 - 1), 44 } 45 ) 46 47 // NagFlakeIssues pings assignees on flaky-test issues 48 type NagFlakeIssues struct { 49 botName string 50 } 51 52 var _ Munger = &NagFlakeIssues{} 53 54 func init() { 55 n := &NagFlakeIssues{} 56 RegisterMungerOrDie(n) 57 RegisterStaleIssueComments(n) 58 } 59 60 // Name is the name usable in --pr-mungers 61 func (NagFlakeIssues) Name() string { return "nag-flake-issues" } 62 63 // RequiredFeatures is a slice of 'features' that must be provided 64 func (NagFlakeIssues) RequiredFeatures() []string { return []string{} } 65 66 // Initialize will initialize the munger 67 func (n *NagFlakeIssues) Initialize(config *mgh.Config, features *features.Features) error { 68 n.botName = config.BotName 69 return nil 70 } 71 72 // EachLoop is called at the start of every munge loop 73 func (NagFlakeIssues) EachLoop() error { return nil } 74 75 // RegisterOptions registers options for this munger; returns any that require a restart when changed. 76 func (NagFlakeIssues) RegisterOptions(opts *options.Options) sets.String { return nil } 77 78 // findTimePeriod returns how often we should ping based on priority 79 func findTimePeriod(labels []github.Label) time.Duration { 80 priorities := mgh.GetLabelsWithPrefix(labels, "priority/") 81 if len(priorities) == 0 { 82 return defaultTimePeriod 83 } 84 // If we have multiple priority labels (shouldn't happen), use the first one 85 period, ok := timePeriods[priorities[0]] 86 if !ok { 87 return defaultTimePeriod 88 } 89 return period 90 } 91 92 // Munge is the workhorse the will actually make updates to the PR 93 func (n *NagFlakeIssues) Munge(obj *mgh.MungeObject) { 94 if obj.IsPR() || !obj.HasLabel("kind/flake") { 95 return 96 } 97 98 issueComments, ok := obj.ListComments() 99 if !ok { 100 return 101 } 102 comments := c.FromIssueComments(issueComments) 103 104 // Use the pinger to notify assignees: 105 // - Set time period based on configuration (at the top of this file) 106 // - Mention list of assignees as an argument 107 // - Start the ping timer after the last HumanActor comment 108 109 // How often should we ping 110 period := findTimePeriod(obj.Issue.Labels) 111 112 // Who are we pinging 113 who := mungerutil.GetIssueUsers(obj.Issue).Assignees.Mention().Join() 114 if who == "" { 115 return 116 } 117 118 // When does the pinger start 119 startDate := c.LastComment(comments, c.HumanActor(n.botName), obj.Issue.CreatedAt) 120 121 // Get a notification if it's time to ping. 122 notif := c.NewPinger(flakeNagNotifyName, n.botName). 123 SetDescription("This flaky-test issue would love to have more attention."). 124 SetTimePeriod(period).PingNotification( 125 comments, 126 who, 127 startDate, 128 ) 129 if notif != nil { 130 obj.WriteComment(notif.String()) 131 } 132 } 133 134 // StaleIssueComments returns a slice of stale issue comments. 135 func (n *NagFlakeIssues) StaleIssueComments(obj *mgh.MungeObject, issueComments []*github.IssueComment) []*github.IssueComment { 136 comments := c.FromIssueComments(issueComments) 137 // Remove all pings written before the last human actor comment 138 filtered := c.FilterComments(comments, c.And([]c.Matcher{ 139 c.MungerNotificationName(flakeNagNotifyName, n.botName), 140 c.CreatedBefore(*c.LastComment(comments, c.HumanActor(n.botName), &time.Time{})), 141 })) 142 issueCommentsFiltered := []*github.IssueComment{} 143 for _, comment := range filtered { 144 issueCommentsFiltered = append(issueCommentsFiltered, comment.Source.(*github.IssueComment)) 145 } 146 return issueCommentsFiltered 147 }