github.com/shashidharatd/test-infra@v0.0.0-20171006011030-71304e1ca560/mungegithub/mungers/stale-pending-ci.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 mungers
    18  
    19  import (
    20  	"fmt"
    21  	"time"
    22  
    23  	"k8s.io/kubernetes/pkg/util/sets"
    24  	"k8s.io/test-infra/mungegithub/features"
    25  	"k8s.io/test-infra/mungegithub/github"
    26  	"k8s.io/test-infra/mungegithub/mungeopts"
    27  	"k8s.io/test-infra/mungegithub/options"
    28  
    29  	"github.com/golang/glog"
    30  	githubapi "github.com/google/go-github/github"
    31  )
    32  
    33  const (
    34  	stalePendingCIHours = 24
    35  	pendingMsgFormat    = `@` + jenkinsBotName + ` test this issue: #IGNORE
    36  
    37  Tests have been pending for %d hours`
    38  )
    39  
    40  var (
    41  	pendingMsgBody = fmt.Sprintf(pendingMsgFormat, stalePendingCIHours)
    42  )
    43  
    44  // StalePendingCI will ask the testBot-to test any PR with a LGTM that has
    45  // been pending for more than 24 hours. This can happen when the jenkins VM
    46  // is restarted.
    47  //
    48  // The real fix would be for the jenkins VM restart to not move every single
    49  // PR to pending without actually testing...
    50  //
    51  // But this is our world and so we should really do this for all PRs which
    52  // aren't likely to get another push (everything that is mergeable). Since that
    53  // can be a lot of PRs, I'm just doing it for the LGTM PRs automatically...
    54  type StalePendingCI struct{}
    55  
    56  func init() {
    57  	s := &StalePendingCI{}
    58  	RegisterMungerOrDie(s)
    59  	RegisterStaleIssueComments(s)
    60  }
    61  
    62  // Name is the name usable in --pr-mungers
    63  func (s *StalePendingCI) Name() string { return "stale-pending-ci" }
    64  
    65  // RequiredFeatures is a slice of 'features' that must be provided
    66  func (s *StalePendingCI) RequiredFeatures() []string { return []string{} }
    67  
    68  // Initialize will initialize the munger
    69  func (s *StalePendingCI) Initialize(config *github.Config, features *features.Features) error {
    70  	return nil
    71  }
    72  
    73  // EachLoop is called at the start of every munge loop
    74  func (s *StalePendingCI) EachLoop() error { return nil }
    75  
    76  // RegisterOptions registers options for this munger; returns any that require a restart when changed.
    77  func (s *StalePendingCI) RegisterOptions(opts *options.Options) sets.String { return nil }
    78  
    79  // Munge is the workhorse the will actually make updates to the PR
    80  func (s *StalePendingCI) Munge(obj *github.MungeObject) {
    81  	if !obj.IsPR() {
    82  		return
    83  	}
    84  
    85  	if !obj.HasLabel(lgtmLabel) {
    86  		return
    87  	}
    88  
    89  	if mergeable, ok := obj.IsMergeable(); !ok || !mergeable {
    90  		return
    91  	}
    92  
    93  	status, ok := obj.GetStatusState(mungeopts.RequiredContexts.Retest)
    94  	if !ok || status != "pending" {
    95  		return
    96  	}
    97  
    98  	for _, context := range mungeopts.RequiredContexts.Retest {
    99  		statusTime, ok := obj.GetStatusTime(context)
   100  		if !ok || statusTime == nil {
   101  			glog.Errorf("%d: unable to determine time %q context was set", *obj.Issue.Number, context)
   102  			return
   103  		}
   104  		if time.Since(*statusTime) > stalePendingCIHours*time.Hour {
   105  			obj.WriteComment(pendingMsgBody)
   106  			return
   107  		}
   108  	}
   109  }
   110  
   111  func isStaleIssueComment(obj *github.MungeObject, comment *githubapi.IssueComment) bool {
   112  	if !obj.IsRobot(comment.User) {
   113  		return false
   114  	}
   115  	if *comment.Body != pendingMsgBody {
   116  		return false
   117  	}
   118  	stale := commentBeforeLastCI(obj, comment, mungeopts.RequiredContexts.Retest)
   119  	if stale {
   120  		glog.V(6).Infof("Found stale StalePendingCI comment")
   121  	}
   122  	return stale
   123  }
   124  
   125  // StaleIssueComments returns a slice of stale issue comments.
   126  func (s *StalePendingCI) StaleIssueComments(obj *github.MungeObject, comments []*githubapi.IssueComment) []*githubapi.IssueComment {
   127  	if mungeopts.RequiredContexts.Retest == nil {
   128  		return nil // mungers not initialized, cannot clean stale comments.
   129  	}
   130  	return forEachCommentTest(obj, comments, isStaleIssueComment)
   131  }