func (config *SubmitQueueConfig) handlePR(e2e *e2eTester, pr *github_api.PullRequest, issue *github_api.Issue) { if config.userWhitelist == nil { config.RefreshWhitelist() } userSet := config.userWhitelist if !github.HasLabel(issue.Labels, config.WhitelistOverride) && !userSet.Has(*pr.User.Login) { glog.V(4).Infof("Dropping %d since %s isn't in whitelist and %s isn't present", *pr.Number, *pr.User.Login, config.WhitelistOverride) if !github.HasLabel(issue.Labels, NeedsOKToMergeLabel) { config.AddLabels(*pr.Number, []string{NeedsOKToMergeLabel}) body := "The author of this PR is not in the whitelist for merge, can one of the admins add the 'ok-to-merge' label?" config.WriteComment(*pr.Number, body) } return } // Tidy up the issue list. if github.HasLabel(issue.Labels, NeedsOKToMergeLabel) { config.RemoveLabel(*pr.Number, NeedsOKToMergeLabel) } lastModifiedTime, err := config.LastModifiedTime(*pr.Number) if err != nil { glog.Errorf("Failed to get last modified time, skipping PR: %d", *pr.Number) return } if ok, err := config.validateLGTMAfterPush(pr, lastModifiedTime); err != nil { glog.Errorf("Error validating LGTM: %v, Skipping: %d", err, *pr.Number) return } else if !ok { glog.Errorf("PR pushed after LGTM, attempting to remove LGTM and skipping") staleLGTMBody := "LGTM was before last commit, removing LGTM" config.WriteComment(*pr.Number, staleLGTMBody) config.RemoveLabel(*pr.Number, "lgtm") return } if mergeable, err := config.IsPRMergeable(pr); err != nil { glog.V(2).Infof("Skipping %d - unable to determine mergeability", *pr.Number) } else if !mergeable { glog.V(2).Infof("Skipping %d - not mergable", *pr.Number) } // Validate the status information for this PR contexts := config.RequiredStatusContexts if len(config.DontRequireE2ELabel) == 0 || !github.HasLabel(issue.Labels, config.DontRequireE2ELabel) { contexts = append(contexts, config.E2EStatusContext) } if ok, err := config.ValidateStatus(*pr.Number, contexts, false); !ok || err != nil { glog.Errorf("Error validating PR status: %v", err) return } if err := e2e.runE2ETests(pr, issue); err != nil { glog.Errorf("Error running e2e test: %v", err) return } return }
func (NeedsRebaseMunger) MungePullRequest(config *config.MungeConfig, pr *github.PullRequest, issue *github.Issue, commits []github.RepositoryCommit, events []github.IssueEvent) { mergeable, err := config.IsPRMergeable(pr) if err != nil { glog.V(2).Infof("Skipping %d - problem determining mergeable", *pr.Number) return } if mergeable && github_util.HasLabel(issue.Labels, needsRebase) { config.RemoveLabel(*pr.Number, needsRebase) } if !mergeable && !github_util.HasLabel(issue.Labels, needsRebase) { config.AddLabels(*pr.Number, []string{needsRebase}) } }
// This is called on a potentially mergeable PR func (e *e2eTester) runE2ETests(pr *github_api.PullRequest, issue *github_api.Issue) error { e.locked(func() { e.state.CurrentPR = prInfo(pr) }) defer e.locked(func() { e.state.CurrentPR = nil }) e.msg("Considering PR %d", *pr.Number) e.waitForStableBuilds() // if there is a 'e2e-not-required' label, just merge it. if len(e.Config.DontRequireE2ELabel) > 0 && github_util.HasLabel(issue.Labels, e.Config.DontRequireE2ELabel) { e.msg("Merging %d since %s is set", *pr.Number, e.Config.DontRequireE2ELabel) return e.Config.MergePR(*pr.Number, "submit-queue") } body := "@k8s-bot test this [submit-queue is verifying that this PR is safe to merge]" if err := e.Config.WriteComment(*pr.Number, body); err != nil { e.error(err) return err } // Wait for the build to start err := e.Config.WaitForPending(*pr.Number) // Wait for the status to go back to 'success' ok, err := e.Config.ValidateStatus(*pr.Number, []string{}, true) if err != nil { e.error(err) return err } if !ok { e.msg("Status after build is not 'success', skipping PR %d", *pr.Number) return nil } return e.Config.MergePR(*pr.Number, "submit-queue") }
func (OkToTestMunger) MungePullRequest(config *config.MungeConfig, pr *github.PullRequest, issue *github.Issue, commits []github.RepositoryCommit, events []github.IssueEvent) { if !github_util.HasLabel(issue.Labels, "lgtm") { return } status, err := config.GetStatus(*pr.Number, []string{"Jenkins GCE e2e"}) if err != nil { glog.Errorf("unexpected error getting status: %v", err) return } if status == "incomplete" { glog.V(2).Infof("status is incomplete, adding ok to test") msg := `@k8s-bot ok to test pr builder appears to be missing, activating due to 'lgtm' label.` config.WriteComment(*pr.Number, msg) } }
// MungePullRequest is the workhorse the will actually make updates to the PR func (LGTMAfterCommitMunger) MungePullRequest(config *config.MungeConfig, pr *github.PullRequest, issue *github.Issue, commits []github.RepositoryCommit, events []github.IssueEvent) { lastModified := lastModifiedTime(commits) lgtmTime := lgtmTime(events) if lastModified == nil || lgtmTime == nil { return } if !github_util.HasLabel(issue.Labels, "lgtm") { return } if lastModified.After(*lgtmTime) { lgtmRemovedBody := "PR changed after LGTM, removing LGTM." if err := config.WriteComment(*pr.Number, lgtmRemovedBody); err != nil { return } config.RemoveLabel(*pr.Number, "lgtm") } }
// MungePullRequest is the workhorse the will actually make updates to the PR func (p *PathLabelMunger) MungePullRequest(config *config.MungeConfig, pr *github.PullRequest, issue *github.Issue, commits []github.RepositoryCommit, events []github.IssueEvent) { if p.labelMap == nil { if err := p.loadPathMap(); err != nil { return } } labelMap := *p.labelMap needsLabels := sets.NewString() for _, c := range commits { for _, f := range c.Files { for prefix, label := range labelMap { if strings.HasPrefix(*f.Filename, prefix) && !github_util.HasLabel(issue.Labels, label) { needsLabels.Insert(label) } } } } if needsLabels.Len() != 0 { config.AddLabels(*pr.Number, needsLabels.List()) } }
func (PingCIMunger) MungePullRequest(config *config.MungeConfig, pr *github.PullRequest, issue *github.Issue, commits []github.RepositoryCommit, events []github.IssueEvent) { if !github_util.HasLabel(issue.Labels, "lgtm") { return } if mergeable, err := config.IsPRMergeable(pr); err != nil { glog.V(2).Infof("Skipping %d - problem determining mergeability", *pr.Number) } else if !mergeable { glog.V(2).Infof("Skipping %d - not mergeable", *pr.Number) } status, err := config.GetStatus(pr, []string{"Shippable", "continuous-integration/travis-ci/pr"}) if err != nil { glog.Errorf("unexpected error getting status: %v", err) return } if status == "incomplete" { glog.V(2).Infof("status is incomplete, closing and re-opening") msg := "Continuous integration appears to have missed, closing and re-opening to trigger it" config.WriteComment(*pr.Number, msg) config.ClosePR(pr) time.Sleep(5 * time.Second) config.OpenPR(pr, 10) } }