sigs.k8s.io/prow@v0.0.0-20240503223140-c5e374dc7eb1/pkg/plugins/merge-method-comment/merge-method-comment_test.go (about)

     1  /*
     2  Copyright 2020 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 mergemethodcomment
    18  
    19  import (
    20  	"fmt"
    21  	"strings"
    22  	"testing"
    23  
    24  	"sigs.k8s.io/prow/pkg/config"
    25  	"sigs.k8s.io/prow/pkg/git/types"
    26  	"sigs.k8s.io/prow/pkg/github"
    27  )
    28  
    29  const fakeBotName = "k8s-bot"
    30  
    31  type ghc struct {
    32  	*testing.T
    33  	comments         map[string][]github.IssueComment
    34  	createCommentErr error
    35  	listCommentsErr  error
    36  }
    37  
    38  func (c *ghc) CreateComment(org, repo string, num int, comment string) error {
    39  	c.T.Logf("CreateComment: %s/%s#%d: %s", org, repo, num, comment)
    40  	if c.createCommentErr != nil {
    41  		return c.createCommentErr
    42  	}
    43  	if len(c.comments) == 0 {
    44  		c.comments = make(map[string][]github.IssueComment)
    45  	}
    46  	orgRepoNum := fmt.Sprintf("%s/%s#%d", org, repo, num)
    47  	c.comments[orgRepoNum] = append(c.comments[orgRepoNum],
    48  		github.IssueComment{
    49  			Body: comment,
    50  			User: github.User{Login: fakeBotName},
    51  		},
    52  	)
    53  	return nil
    54  }
    55  
    56  func (c *ghc) ListIssueComments(org, repo string, num int) ([]github.IssueComment, error) {
    57  	c.T.Logf("ListIssueComments: %s/%s#%d", org, repo, num)
    58  	if c.listCommentsErr != nil {
    59  		return nil, c.listCommentsErr
    60  	}
    61  	return c.comments[fmt.Sprintf("%s/%s#%d", org, repo, num)], nil
    62  }
    63  
    64  func (c *ghc) BotUserChecker() (func(candidate string) bool, error) {
    65  	return func(candidate string) bool { return candidate == fakeBotName }, nil
    66  }
    67  
    68  func TestHandlePR(t *testing.T) {
    69  	singleCommitPR := github.PullRequest{
    70  		Number: 101,
    71  		Base: github.PullRequestBranch{
    72  			Repo: github.Repo{
    73  				Owner: github.User{
    74  					Login: "kubernetes",
    75  				},
    76  				Name: "kubernetes",
    77  			},
    78  		},
    79  		Commits: 1,
    80  	}
    81  	multipleCommitsPR := github.PullRequest{
    82  		Number: 101,
    83  		Base: github.PullRequestBranch{
    84  			Repo: github.Repo{
    85  				Owner: github.User{
    86  					Login: "kubernetes",
    87  				},
    88  				Name: "kubernetes",
    89  			},
    90  		},
    91  		Commits: 2,
    92  	}
    93  
    94  	cases := []struct {
    95  		name               string
    96  		client             *ghc
    97  		event              github.PullRequestEvent
    98  		defaultMergeMethod types.PullRequestMergeType
    99  		squashLabel        string
   100  		mergeLabel         string
   101  		err                error
   102  		comments           []github.IssueComment
   103  	}{
   104  		{
   105  			name:   "single commit",
   106  			client: &ghc{},
   107  			event: github.PullRequestEvent{
   108  				Action:      github.PullRequestActionOpened,
   109  				PullRequest: singleCommitPR,
   110  			},
   111  			squashLabel:        "squash-label",
   112  			defaultMergeMethod: types.MergeSquash,
   113  		},
   114  		{
   115  			name:   "multiple commits, merge by-default, squash label configured",
   116  			client: &ghc{},
   117  			event: github.PullRequestEvent{
   118  				Action:      github.PullRequestActionOpened,
   119  				PullRequest: multipleCommitsPR,
   120  			},
   121  			defaultMergeMethod: types.MergeMerge,
   122  			squashLabel:        "squash-label",
   123  			comments: []github.IssueComment{
   124  				{
   125  					Body: "You can request commits to be squashed using the label: squash-label",
   126  				},
   127  			},
   128  		},
   129  		{
   130  			name:   "multiple commits, merge by-default, squash label not configured",
   131  			client: &ghc{},
   132  			event: github.PullRequestEvent{
   133  				Action:      github.PullRequestActionOpened,
   134  				PullRequest: multipleCommitsPR,
   135  			},
   136  			defaultMergeMethod: types.MergeMerge,
   137  			comments: []github.IssueComment{
   138  				{
   139  					Body: "Commits will be merged, as no squash labels are defined",
   140  				},
   141  			},
   142  		},
   143  		{
   144  			name:   "multiple commits, squash by-default, merge label configured",
   145  			client: &ghc{},
   146  			event: github.PullRequestEvent{
   147  				Action:      github.PullRequestActionOpened,
   148  				PullRequest: multipleCommitsPR,
   149  			},
   150  			defaultMergeMethod: types.MergeSquash,
   151  			mergeLabel:         "merge-label",
   152  			comments: []github.IssueComment{
   153  				{
   154  					Body: "You can request commits to be merged using the label: merge-label",
   155  				},
   156  			},
   157  		},
   158  		{
   159  			name:   "multiple commits, squash by-default, merge label not configured",
   160  			client: &ghc{},
   161  			event: github.PullRequestEvent{
   162  				Action:      github.PullRequestActionOpened,
   163  				PullRequest: multipleCommitsPR,
   164  			},
   165  			defaultMergeMethod: types.MergeSquash,
   166  			comments: []github.IssueComment{
   167  				{
   168  					Body: "Commits will be squashed, as no merge labels are defined",
   169  				},
   170  			},
   171  		},
   172  		{
   173  			name: "do not create comment if already commented",
   174  			client: &ghc{
   175  				comments: map[string][]github.IssueComment{
   176  					"kubernetes/kubernetes#101": {
   177  						{
   178  							User: github.User{Login: "k8s-bot"},
   179  							Body: fmt.Sprintf("This PR has multiple commits, and the default merge method is: %s.\n%s",
   180  								types.MergeMerge,
   181  								"Commits will be merged, as no squash labels are defined"),
   182  						},
   183  					},
   184  				},
   185  			},
   186  			event: github.PullRequestEvent{
   187  				Action:      github.PullRequestActionOpened,
   188  				PullRequest: multipleCommitsPR,
   189  			},
   190  			defaultMergeMethod: types.MergeMerge,
   191  			comments: []github.IssueComment{
   192  				{
   193  					Body: "Commits will be merged, as no squash labels are defined",
   194  				},
   195  			},
   196  		},
   197  		{
   198  			name: "error listing issue comments",
   199  			client: &ghc{
   200  				listCommentsErr: fmt.Errorf("cannot list comments"),
   201  			},
   202  			defaultMergeMethod: types.MergeMerge,
   203  			event: github.PullRequestEvent{
   204  				Action:      github.PullRequestActionOpened,
   205  				PullRequest: multipleCommitsPR,
   206  			},
   207  			err: fmt.Errorf("error listing issue comments: %s", "cannot list comments"),
   208  		},
   209  		{
   210  			name: "error creating comment",
   211  			client: &ghc{
   212  				createCommentErr: fmt.Errorf("cannot create comment"),
   213  			},
   214  			defaultMergeMethod: types.MergeMerge,
   215  			event: github.PullRequestEvent{
   216  				Action:      github.PullRequestActionSynchronize,
   217  				PullRequest: multipleCommitsPR,
   218  			},
   219  			err: fmt.Errorf("cannot create comment"),
   220  		},
   221  		{
   222  			name:   "handle PR sync",
   223  			client: &ghc{},
   224  			event: github.PullRequestEvent{
   225  				Action:      github.PullRequestActionSynchronize,
   226  				PullRequest: multipleCommitsPR,
   227  			},
   228  			defaultMergeMethod: types.MergeMerge,
   229  			comments: []github.IssueComment{
   230  				{
   231  					Body: "Commits will be merged, as no squash labels are defined",
   232  				},
   233  			},
   234  		},
   235  		{
   236  			name:   "handle PR reopen",
   237  			client: &ghc{},
   238  			event: github.PullRequestEvent{
   239  				Action:      github.PullRequestActionReopened,
   240  				PullRequest: multipleCommitsPR,
   241  			},
   242  			defaultMergeMethod: types.MergeMerge,
   243  			comments: []github.IssueComment{
   244  				{
   245  					Body: "Commits will be merged, as no squash labels are defined",
   246  				},
   247  			},
   248  		},
   249  		{
   250  			name:   "handle PR edit",
   251  			client: &ghc{},
   252  			event: github.PullRequestEvent{
   253  				Action:      github.PullRequestActionEdited,
   254  				PullRequest: multipleCommitsPR,
   255  			},
   256  			defaultMergeMethod: types.MergeMerge,
   257  			comments: []github.IssueComment{
   258  				{
   259  					Body: "Commits will be merged, as no squash labels are defined",
   260  				},
   261  			},
   262  		},
   263  		{
   264  			name:   "ignore irrelevant events",
   265  			client: &ghc{},
   266  			event: github.PullRequestEvent{
   267  				Action:      github.PullRequestActionReviewRequested,
   268  				PullRequest: multipleCommitsPR,
   269  			},
   270  			defaultMergeMethod: types.MergeMerge,
   271  		},
   272  	}
   273  
   274  	for _, c := range cases {
   275  		t.Run(c.name, func(t *testing.T) {
   276  			if c.client == nil {
   277  				t.Fatalf("test case can not have nil github client")
   278  			}
   279  
   280  			// Set up test logging.
   281  			c.client.T = t
   282  
   283  			c.event.Number = 101
   284  			config := config.Tide{
   285  				TideGitHubConfig: config.TideGitHubConfig{
   286  					MergeType: map[string]config.TideOrgMergeType{
   287  						"kubernetes/kubernetes": {MergeType: c.defaultMergeMethod},
   288  					},
   289  					SquashLabel: c.squashLabel,
   290  					MergeLabel:  c.mergeLabel,
   291  				},
   292  			}
   293  			err := handlePR(c.client, config, c.event)
   294  
   295  			if err != nil && c.err == nil {
   296  				t.Fatalf("handlePR error: %v", err)
   297  			}
   298  
   299  			if err == nil && c.err != nil {
   300  				t.Fatalf("handlePR wanted error %v, got nil", err)
   301  			}
   302  
   303  			if got, want := err, c.err; got != nil && got.Error() != want.Error() {
   304  				t.Fatalf("handlePR errors mismatch: got %v, want %v", got, want)
   305  			}
   306  
   307  			if c.err != nil {
   308  				return
   309  			}
   310  
   311  			if got, want := len(c.client.comments["kubernetes/kubernetes#101"]), len(c.comments); got != want {
   312  				t.Logf("github client comments: got %v; want %v", c.client.comments, c.comments)
   313  				t.Fatalf("issue comments count mismatch: got %d, want %d", got, want)
   314  			}
   315  
   316  			for i, comment := range c.comments {
   317  				if !strings.Contains(c.client.comments["kubernetes/kubernetes#101"][i].Body, comment.Body) {
   318  					t.Fatalf("github client comment: got %s, expected it to contain: %s", c.client.comments["kubernetes/kubernetes#101"][i].Body, comment.Body)
   319  				}
   320  			}
   321  		})
   322  	}
   323  }