Example #1
0
// MungePullRequest is the workhorse the will actually make updates to the PR
func (LGTMAfterCommitMunger) MungePullRequest(config *github_util.Config, pr *github.PullRequest, issue *github.Issue, commits []github.RepositoryCommit, events []github.IssueEvent) {
	if !github_util.HasLabel(issue.Labels, "lgtm") {
		return
	}

	lastModified := github_util.LastModifiedTime(commits)
	lgtmTime := github_util.LabelTime("lgtm", events)

	if lastModified == nil || lgtmTime == nil {
		glog.Errorf("PR %d unable to determine lastModified or lgtmTime", *pr.Number)
		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")
	}
}
Example #2
0
func TestValidateLGTMAfterPush(t *testing.T) {
	tests := []struct {
		issueEvents  []github.IssueEvent
		shouldPass   bool
		lastModified time.Time
	}{
		{
			issueEvents: []github.IssueEvent{
				{
					Event: stringPtr("labeled"),
					Label: &github.Label{
						Name: stringPtr("lgtm"),
					},
					CreatedAt: timePtr(time.Unix(10, 0)),
				},
			},
			lastModified: time.Unix(9, 0),
			shouldPass:   true,
		},
		{
			issueEvents: []github.IssueEvent{
				{
					Event: stringPtr("labeled"),
					Label: &github.Label{
						Name: stringPtr("lgtm"),
					},
					CreatedAt: timePtr(time.Unix(10, 0)),
				},
			},
			lastModified: time.Unix(11, 0),
			shouldPass:   false,
		},
		{
			issueEvents: []github.IssueEvent{
				{
					Event: stringPtr("labeled"),
					Label: &github.Label{
						Name: stringPtr("lgtm"),
					},
					CreatedAt: timePtr(time.Unix(12, 0)),
				},
				{
					Event: stringPtr("labeled"),
					Label: &github.Label{
						Name: stringPtr("lgtm"),
					},
					CreatedAt: timePtr(time.Unix(11, 0)),
				},
				{
					Event: stringPtr("labeled"),
					Label: &github.Label{
						Name: stringPtr("lgtm"),
					},
					CreatedAt: timePtr(time.Unix(10, 0)),
				},
			},
			lastModified: time.Unix(11, 0),
			shouldPass:   true,
		},
		{
			issueEvents: []github.IssueEvent{
				{
					Event: stringPtr("labeled"),
					Label: &github.Label{
						Name: stringPtr("lgtm"),
					},
					CreatedAt: timePtr(time.Unix(10, 0)),
				},
				{
					Event: stringPtr("labeled"),
					Label: &github.Label{
						Name: stringPtr("lgtm"),
					},
					CreatedAt: timePtr(time.Unix(11, 0)),
				},
				{
					Event: stringPtr("labeled"),
					Label: &github.Label{
						Name: stringPtr("lgtm"),
					},
					CreatedAt: timePtr(time.Unix(12, 0)),
				},
			},
			lastModified: time.Unix(11, 0),
			shouldPass:   true,
		},
	}
	for _, test := range tests {
		config := &github_util.Config{}
		client, server, mux := github_test.InitTest()
		config.Org = "o"
		config.Project = "r"
		config.SetClient(client)

		mux.HandleFunc(fmt.Sprintf("/repos/o/r/issues/1/events"), func(w http.ResponseWriter, r *http.Request) {
			if r.Method != "GET" {
				t.Errorf("Unexpected method: %s", r.Method)
			}
			w.WriteHeader(http.StatusOK)
			data, err := json.Marshal(test.issueEvents)
			if err != nil {
				t.Errorf("Unexpected error: %v", err)
			}
			w.Write(data)

			commits, err := config.GetFilledCommits(1)
			if err != nil {
				t.Errorf("Unexpected error getting filled commits: %v", err)
			}

			events, err := config.GetAllEventsForPR(1)
			if err != nil {
				t.Errorf("Unexpected error getting events commits: %v", err)
			}
			lastModifiedTime := github_util.LastModifiedTime(commits)
			lgtmTime := github_util.LabelTime("lgtm", events)

			if lastModifiedTime == nil || lgtmTime == nil {
				t.Errorf("unexpected lastModifiedTime or lgtmTime == nil")
			}

			ok := !lastModifiedTime.After(*lgtmTime)

			if ok != test.shouldPass {
				t.Errorf("expected: %v, saw: %v", test.shouldPass, ok)
			}
		})
		server.Close()
	}
}
Example #3
0
// MungePullRequest is the workhorse the will actually make updates to the PR
func (sq *SubmitQueue) MungePullRequest(config *github_util.Config, pr *github_api.PullRequest, issue *github_api.Issue, commits []github_api.RepositoryCommit, events []github_api.IssueEvent) {
	e2e := sq.e2e
	userSet := sq.userWhitelist

	if !github_util.HasLabels(issue.Labels, []string{"cla: yes"}) {
		sq.SetPRStatus(pr, noCLA)
		return
	}

	if mergeable, err := config.IsPRMergeable(pr); err != nil {
		glog.V(2).Infof("Skipping %d - unable to determine mergeability", *pr.Number)
		sq.SetPRStatus(pr, undeterminedMergability)
		return
	} else if !mergeable {
		glog.V(4).Infof("Skipping %d - not mergable", *pr.Number)
		sq.SetPRStatus(pr, unmergeable)
		return
	}

	// Validate the status information for this PR
	contexts := sq.RequiredStatusContexts
	if len(sq.E2EStatusContext) > 0 && (len(sq.DontRequireE2ELabel) == 0 || !github_util.HasLabel(issue.Labels, sq.DontRequireE2ELabel)) {
		contexts = append(contexts, sq.E2EStatusContext)
	}
	if ok := config.IsStatusSuccess(pr, contexts); !ok {
		glog.Errorf("PR# %d Github CI status is not success", *pr.Number)
		sq.SetPRStatus(pr, ciFailure)
		return
	}

	if !github_util.HasLabel(issue.Labels, sq.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, sq.WhitelistOverride)
		if !github_util.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)
		}
		sq.SetPRStatus(pr, needsok)
		return
	}

	// Tidy up the issue list.
	if github_util.HasLabel(issue.Labels, needsOKToMergeLabel) {
		config.RemoveLabel(*pr.Number, needsOKToMergeLabel)
	}

	if !github_util.HasLabels(issue.Labels, []string{"lgtm"}) {
		sq.SetPRStatus(pr, noLGTM)
		return
	}

	lastModifiedTime := github_util.LastModifiedTime(commits)
	lgtmTime := github_util.LabelTime("lgtm", events)

	if lastModifiedTime == nil || lgtmTime == nil {
		glog.Errorf("PR %d was unable to determine when LGTM was added or when last modified", *pr.Number)
		sq.SetPRStatus(pr, unknown)
		return
	}

	if lastModifiedTime.After(*lgtmTime) {
		glog.V(4).Infof("PR %d changed after LGTM. Will not merge", *pr.Number)
		sq.SetPRStatus(pr, lgtmEarly)
		return
	}

	if !e2e.Stable() {
		sq.SetPRStatus(pr, e2eFailure)
		return
	}

	// if there is a 'e2e-not-required' label, just merge it.
	if len(sq.DontRequireE2ELabel) > 0 && github_util.HasLabel(issue.Labels, sq.DontRequireE2ELabel) {
		config.MergePR(pr, "submit-queue")
		sq.SetPRStatus(pr, merged)
		return
	}

	sq.SetPRStatus(pr, githube2e)
	sq.Lock()
	sq.githubE2ERequest <- true
	sq.needsGithubE2E[*pr.Number] = pr
	sq.Unlock()

	return
}