diff --git a/contrib/submit-queue/github/github.go b/contrib/submit-queue/github/github.go index 63e598d3f5c..89a723337b6 100644 --- a/contrib/submit-queue/github/github.go +++ b/contrib/submit-queue/github/github.go @@ -86,6 +86,28 @@ type FilterConfig struct { RequiredStatusContexts []string } +func validateLGTMAfterPush(client *github.Client, user, project string, pr *github.PullRequest) (bool, error) { + var lgtmTime *time.Time + events, _, err := client.Issues.ListIssueEvents(user, project, *pr.Number, &github.ListOptions{}) + if err != nil { + glog.Errorf("Error getting events for issue: %v", err) + return false, err + } + for ix := range events { + event := &events[ix] + if *event.Event == "labeled" && *event.Label.Name == "lgtm" { + *lgtmTime = *event.CreatedAt + } + } + if lgtmTime == nil { + return false, fmt.Errorf("Couldn't find time for LGTM label, this shouldn't happen, skipping PR: %d", *pr.Number) + } + if pr.Head == nil || pr.Head.Repo == nil || pr.Head.Repo.PushedAt == nil { + return false, fmt.Errorf("Couldn't find push time for PR, this shouldn't happen, skipping PR: %d", *pr.Number) + } + return pr.Head.Repo.PushedAt.Before(*lgtmTime), nil +} + // For each PR in the project that matches: // * pr.Number > minPRNumber // * is mergeable @@ -124,6 +146,7 @@ func ForEachCandidatePRDo(client *github.Client, user, project string, fn PRFunc glog.Errorf("Failed to get issue for PR: %v", err) continue } + glog.V(8).Infof("%v", issue.Labels) if !hasLabels(issue.Labels, []string{"lgtm", "cla: yes"}) { continue @@ -133,6 +156,21 @@ func ForEachCandidatePRDo(client *github.Client, user, project string, fn PRFunc continue } + if ok, err := validateLGTMAfterPush(client, user, project, pr); err != nil { + glog.Errorf("Error validating LGTM: %v, Skipping: %d", err, *pr.Number) + continue + } else if !ok { + glog.Errorf("PR pushed after LGTM, attempting to remove LGTM and skipping") + staleLGTMBody := "LGTM was before last commit, removing LGTM" + if _, _, err := client.Issues.CreateComment(user, project, *pr.Number, &github.IssueComment{Body: &staleLGTMBody}); err != nil { + glog.Warningf("Failed to create remove label comment: %v", err) + } + if _, err := client.Issues.RemoveLabelForIssue(user, project, *pr.Number, "lgtm"); err != nil { + glog.Warningf("Failed to remove 'lgtm' label for stale lgtm on %d", *pr.Number) + } + continue + } + // This is annoying, github appears to only temporarily cache mergeability, if it is nil, wait // for an async refresh and retry. if pr.Mergeable == nil {