github.com/zppinho/prow@v0.0.0-20240510014325-1738badeb017/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  }