diff --git a/prow/config/tide.go b/prow/config/tide.go index 7b39f4934f8fe..b37412ab5d9b3 100644 --- a/prow/config/tide.go +++ b/prow/config/tide.go @@ -85,6 +85,8 @@ func (t *Tide) MergeMethod(org, repo string) github.PullRequestMergeType { type TideQuery struct { Repos []string `json:"repos,omitempty"` + ExcludedBranches []string `json:"excludedBranches,omitempty"` + Labels []string `json:"labels,omitempty"` MissingLabels []string `json:"missingLabels,omitempty"` @@ -96,6 +98,9 @@ func (tq *TideQuery) Query() string { for _, r := range tq.Repos { toks = append(toks, fmt.Sprintf("repo:\"%s\"", r)) } + for _, b := range tq.ExcludedBranches { + toks = append(toks, fmt.Sprintf("-base:\"%s\"", b)) + } for _, l := range tq.Labels { toks = append(toks, fmt.Sprintf("label:\"%s\"", l)) } diff --git a/prow/tide/tide.go b/prow/tide/tide.go index 6118a6cc193c2..6dfc1fd177a30 100644 --- a/prow/tide/tide.go +++ b/prow/tide/tide.go @@ -192,6 +192,7 @@ func byRepoAndNumber(prs []PullRequest) map[string]PullRequest { func requirementDiff(pr *PullRequest, q *config.TideQuery) (string, int) { const maxLabelChars = 50 var desc string + var diff int // Drops labels if needed to fit the description text area, but keep at least 1. truncate := func(labels []string) []string { i := 1 @@ -246,11 +247,21 @@ func requirementDiff(pr *PullRequest, q *config.TideQuery) (string, int) { desc = fmt.Sprintf(" Should not have %s labels.", strings.Join(trunced, ", ")) } } + diff = len(missingLabels) + len(presentLabels) + + if desc == "" { + for _, excludedBranch := range q.ExcludedBranches { + if string(pr.BaseRef.Name) == excludedBranch { + desc = fmt.Sprintf(" Merging to branch %s is forbidden.", pr.BaseRef.Name) + } + } + diff = 1 + } // TODO(cjwagner): List reviews (states:[APPROVED], first: 1) as part of open // PR query and include status context description. - return desc, len(missingLabels) + len(presentLabels) + return desc, diff } // Returns expected status state and description. diff --git a/prow/tide/tide_test.go b/prow/tide/tide_test.go index 2c7b475fa832b..181f2d4a23e1b 100644 --- a/prow/tide/tide_test.go +++ b/prow/tide/tide_test.go @@ -386,8 +386,9 @@ func TestExpectedStatus(t *testing.T) { testcases := []struct { name string - labels []string - inPool bool + baseref string + labels []string + inPool bool state string desc string @@ -438,6 +439,15 @@ func TestExpectedStatus(t *testing.T) { state: github.StatusPending, desc: fmt.Sprintf(statusNotInPool, " Needs need-1 label."), }, + { + name: "against excluded branch", + baseref: "bad", + labels: neededLabels, + inPool: false, + + state: github.StatusPending, + desc: fmt.Sprintf(statusNotInPool, " Merging to branch bad is forbidden."), + }, { name: "unknown requirement", labels: neededLabels, @@ -458,8 +468,9 @@ func TestExpectedStatus(t *testing.T) { queriesByRepo := map[string]config.TideQueries{ "": { config.TideQuery{ - Labels: neededLabels, - MissingLabels: forbiddenLabels, + ExcludedBranches: []string{"bad"}, + Labels: neededLabels, + MissingLabels: forbiddenLabels, }, config.TideQuery{ Labels: []string{"1", "2", "3", "4", "5", "6", "7"}, // lots of requirements @@ -470,6 +481,12 @@ func TestExpectedStatus(t *testing.T) { for _, tc := range testcases { t.Logf("Test Case: %q\n", tc.name) var pr PullRequest + pr.BaseRef = struct { + Name githubql.String + Prefix githubql.String + }{ + Name: githubql.String(tc.baseref), + } for _, label := range tc.labels { pr.Labels.Nodes = append( pr.Labels.Nodes, @@ -1126,7 +1143,8 @@ func TestServeHTTP(t *testing.T) { } func TestHeadContexts(t *testing.T) { - type commitContext struct { // one context per commit for testing + type commitContext struct { + // one context per commit for testing context string sha string }