sigs.k8s.io/prow@v0.0.0-20240503223140-c5e374dc7eb1/pkg/plugins/require-matching-label/require-matching-label_test.go (about) 1 /* 2 Copyright 2018 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 requirematchinglabel 18 19 import ( 20 "regexp" 21 "testing" 22 23 "github.com/sirupsen/logrus" 24 "k8s.io/apimachinery/pkg/util/sets" 25 "sigs.k8s.io/prow/pkg/github" 26 "sigs.k8s.io/prow/pkg/labels" 27 "sigs.k8s.io/prow/pkg/plugins" 28 ) 29 30 type fakeGitHub struct { 31 labels sets.Set[string] 32 IssueLabelsAdded, IssueLabelsRemoved sets.Set[string] 33 commented bool 34 } 35 36 func newFakeGitHub(initialLabels ...string) *fakeGitHub { 37 return &fakeGitHub{ 38 labels: sets.New[string](initialLabels...), 39 IssueLabelsAdded: sets.New[string](), 40 IssueLabelsRemoved: sets.New[string](), 41 } 42 } 43 44 func (f *fakeGitHub) AddLabel(org, repo string, number int, label string) error { 45 f.labels.Insert(label) 46 f.IssueLabelsAdded.Insert(label) 47 return nil 48 } 49 50 func (f *fakeGitHub) RemoveLabel(org, repo string, number int, label string) error { 51 f.labels.Delete(label) 52 f.IssueLabelsRemoved.Insert(label) 53 return nil 54 } 55 56 func (f *fakeGitHub) CreateComment(org, repo string, number int, content string) error { 57 f.commented = true 58 return nil 59 } 60 61 func (f *fakeGitHub) GetIssueLabels(org, repo string, number int) ([]github.Label, error) { 62 res := make([]github.Label, 0, len(f.labels)) 63 for label := range f.labels { 64 res = append(res, github.Label{Name: label}) 65 } 66 return res, nil 67 } 68 69 func (f *fakeGitHub) GetPullRequest(org, repo string, number int) (*github.PullRequest, error) { 70 res := &github.PullRequest{} 71 return res, nil 72 } 73 74 type fakePruner struct{} 75 76 func (fp *fakePruner) PruneComments(shouldPrune func(github.IssueComment) bool) {} 77 78 func TestHandle(t *testing.T) { 79 configs := []plugins.RequireMatchingLabel{ 80 // needs-sig over k8s org (issues) 81 { 82 Org: "k8s", 83 Issues: true, 84 Re: regexp.MustCompile(`^(sig|wg|committee)/`), 85 MissingLabel: "needs-sig", 86 }, 87 88 // needs-kind over k8s/t-i repo (PRs) 89 { 90 Org: "k8s", 91 Repo: "t-i", 92 PRs: true, 93 Re: regexp.MustCompile(`^kind/`), 94 MissingLabel: "needs-kind", 95 }, 96 // needs-cat over k8s/t-i:meow branch (issues and PRs) (will comment) 97 { 98 Org: "k8s", 99 Repo: "t-i", 100 Branch: "meow", 101 Issues: true, 102 PRs: true, 103 Re: regexp.MustCompile(`^(cat|floof|loaf)$`), 104 MissingLabel: "needs-cat", 105 MissingComment: "Meow?", 106 }, 107 } 108 109 tcs := []struct { 110 name string 111 event *event 112 initialLabels []string 113 114 expectComment bool 115 expectedAdded sets.Set[string] 116 expectedRemoved sets.Set[string] 117 }{ 118 { 119 name: "ignore PRs", 120 event: &event{ 121 org: "k8s", 122 repo: "k8s", 123 branch: "foo", 124 }, 125 initialLabels: []string{labels.LGTM}, 126 }, 127 { 128 name: "ignore wrong org", 129 event: &event{ 130 org: "fejtaverse", 131 repo: "repo", 132 }, 133 initialLabels: []string{labels.LGTM}, 134 }, 135 { 136 name: "ignore unrelated label change", 137 event: &event{ 138 org: "k8s", 139 repo: "t-i", 140 branch: "master", 141 label: "unrelated", 142 }, 143 initialLabels: []string{labels.LGTM}, 144 }, 145 { 146 name: "add needs-kind label to PR", 147 event: &event{ 148 org: "k8s", 149 repo: "t-i", 150 branch: "master", 151 }, 152 initialLabels: []string{labels.LGTM}, 153 expectedAdded: sets.New[string]("needs-kind"), 154 }, 155 { 156 name: "remove needs-kind label from PR based on label change", 157 event: &event{ 158 org: "k8s", 159 repo: "t-i", 160 branch: "master", 161 label: "kind/best", 162 }, 163 initialLabels: []string{labels.LGTM, "needs-kind", "kind/best"}, 164 expectedRemoved: sets.New[string]("needs-kind"), 165 }, 166 { 167 name: "don't remove needs-kind label from issue based on label change (ignore issues)", 168 event: &event{ 169 org: "k8s", 170 repo: "t-i", 171 label: "kind/best", 172 }, 173 initialLabels: []string{labels.LGTM, "needs-kind", "kind/best", "sig/cats"}, 174 }, 175 { 176 name: "don't remove needs-kind label from PR already missing it", 177 event: &event{ 178 org: "k8s", 179 repo: "t-i", 180 branch: "master", 181 label: "kind/best", 182 }, 183 initialLabels: []string{labels.LGTM, "kind/best"}, 184 }, 185 { 186 name: "add org scoped needs-sig to issue", 187 event: &event{ 188 org: "k8s", 189 repo: "k8s", 190 label: "sig/bash", 191 }, 192 initialLabels: []string{labels.LGTM, "kind/best"}, 193 expectedAdded: sets.New[string]("needs-sig"), 194 }, 195 { 196 name: "don't add org scoped needs-sig to issue when another sig/* label remains", 197 event: &event{ 198 org: "k8s", 199 repo: "k8s", 200 label: "sig/bash", 201 }, 202 initialLabels: []string{labels.LGTM, "kind/best", "wg/foo"}, 203 }, 204 { 205 name: "add branch scoped needs-cat to issue", 206 event: &event{ 207 org: "k8s", 208 repo: "t-i", 209 label: "cat", 210 }, 211 initialLabels: []string{labels.LGTM, "wg/foo"}, 212 expectedAdded: sets.New[string]("needs-cat"), 213 expectComment: true, 214 }, 215 { 216 name: "add branch scoped needs-cat to PR", 217 event: &event{ 218 org: "k8s", 219 repo: "t-i", 220 branch: "meow", 221 }, 222 initialLabels: []string{labels.LGTM, "kind/best"}, 223 expectedAdded: sets.New[string]("needs-cat"), 224 expectComment: true, 225 }, 226 { 227 name: "remove branch scoped needs-cat from PR, add repo scoped needs-kind", 228 event: &event{ 229 org: "k8s", 230 repo: "t-i", 231 branch: "meow", 232 }, 233 initialLabels: []string{labels.LGTM, "needs-cat", "cat", "floof"}, 234 expectedAdded: sets.New[string]("needs-kind"), 235 expectedRemoved: sets.New[string]("needs-cat"), 236 }, 237 { 238 name: "add branch scoped needs-cat to issue, remove org scoped needs-sig", 239 event: &event{ 240 org: "k8s", 241 repo: "t-i", 242 }, 243 initialLabels: []string{labels.LGTM, "needs-sig", "wg/foo"}, 244 expectedAdded: sets.New[string]("needs-cat"), 245 expectedRemoved: sets.New[string]("needs-sig"), 246 expectComment: true, 247 }, 248 } 249 250 for _, tc := range tcs { 251 t.Logf("Running test case %q...", tc.name) 252 log := logrus.WithField("plugin", "require-matching-label") 253 fghc := newFakeGitHub(tc.initialLabels...) 254 if err := handle(log, fghc, &fakePruner{}, configs, tc.event); err != nil { 255 t.Fatalf("Unexpected error from handle: %v.", err) 256 } 257 258 if tc.expectComment && !fghc.commented { 259 t.Error("Expected a comment, but didn't get one.") 260 } else if !tc.expectComment && fghc.commented { 261 t.Error("Expected no comments to be created but got one.") 262 } 263 264 if !tc.expectedAdded.Equal(fghc.IssueLabelsAdded) { 265 t.Errorf("Expected the %q labels to be added, but got %q.", sets.List(tc.expectedAdded), sets.List(fghc.IssueLabelsAdded)) 266 } 267 268 if !tc.expectedRemoved.Equal(fghc.IssueLabelsRemoved) { 269 t.Errorf("Expected the %q labels to be removed, but got %q.", sets.List(tc.expectedRemoved), sets.List(fghc.IssueLabelsRemoved)) 270 } 271 } 272 }