sigs.k8s.io/prow@v0.0.0-20240503223140-c5e374dc7eb1/pkg/plugins/invalidcommitmsg/invalidcommitmsg_test.go (about) 1 /* 2 Copyright 2019 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 invalidcommitmsg 18 19 import ( 20 "fmt" 21 "reflect" 22 "testing" 23 24 "github.com/google/go-cmp/cmp" 25 "github.com/sirupsen/logrus" 26 27 "sigs.k8s.io/prow/pkg/github" 28 "sigs.k8s.io/prow/pkg/github/fakegithub" 29 ) 30 31 type fakePruner struct{} 32 33 func (fp *fakePruner) PruneComments(shouldPrune func(github.IssueComment) bool) {} 34 35 func makeFakePullRequestEvent(action github.PullRequestEventAction, title string) github.PullRequestEvent { 36 return github.PullRequestEvent{ 37 Action: action, 38 Number: 3, 39 Repo: github.Repo{ 40 Owner: github.User{ 41 Login: "k", 42 }, 43 Name: "k", 44 }, 45 PullRequest: github.PullRequest{ 46 Title: title, 47 }, 48 } 49 } 50 51 var invalidCommitComment = `k/k#3:[Keywords](https://help.github.com/articles/closing-issues-using-keywords) which can automatically close issues and at(@) or hashtag(#) mentions are not allowed in commit messages. 52 53 **The list of commits with invalid commit messages**: 54 55 - [sha1](https://github.com/k/k/commits/sha1) this is a @mention 56 - [sha2](https://github.com/k/k/commits/sha2) this @menti-on has a hyphen 57 - [sha3](https://github.com/k/k/commits/sha3) this @Menti-On has mixed case letters 58 - [sha4](https://github.com/k/k/commits/sha4) fixes k/k#9999 59 - [sha5](https://github.com/k/k/commits/sha5) Close k/k#9999 60 - [sha6](https://github.com/k/k/commits/sha6) resolved k/k#9999 61 62 <details> 63 64 Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md). If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes-sigs/prow](https://github.com/kubernetes-sigs/prow/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands). 65 </details> 66 ` 67 68 var invalidPRTitleComment = `k/k#3:[Keywords](https://help.github.com/articles/closing-issues-using-keywords) which can automatically close issues and at(@) mentions are not allowed in the title of a Pull Request. 69 70 You can edit the title by writing **/retitle <new-title>** in a comment. 71 72 <details> 73 When GitHub merges a Pull Request, the title is included in the merge commit. To avoid invalid keywords in the merge commit, please edit the title of the PR. 74 75 Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md). If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes-sigs/prow](https://github.com/kubernetes-sigs/prow/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands). 76 </details> 77 ` 78 79 func TestHandlePullRequest(t *testing.T) { 80 var testcases = []struct { 81 name string 82 83 // PR settings 84 action github.PullRequestEventAction 85 commits []github.RepositoryCommit 86 title string 87 hasInvalidCommitMessageLabel bool 88 89 // expectations 90 addedLabel string 91 removedLabel string 92 addedComments []string 93 }{ 94 { 95 name: "unsupported PR action -> no-op", 96 action: github.PullRequestActionLabeled, 97 }, 98 { 99 name: "contains valid message -> no-op", 100 action: github.PullRequestActionOpened, 101 commits: []github.RepositoryCommit{ 102 {SHA: "sha1", Commit: github.GitCommit{Message: "this is a valid message"}}, 103 {SHA: "sha2", Commit: github.GitCommit{Message: "fixing k/k#9999"}}, 104 {SHA: "sha3", Commit: github.GitCommit{Message: "not a @ mention"}}, 105 {SHA: "sha4", Commit: github.GitCommit{Message: "escape @\u200bmention with zero width unicode"}}, 106 }, 107 hasInvalidCommitMessageLabel: false, 108 }, 109 { 110 name: "msg contains invalid keywords -> add label and comment", 111 action: github.PullRequestActionOpened, 112 commits: []github.RepositoryCommit{ 113 {SHA: "sha1", Commit: github.GitCommit{Message: "this is a @mention"}}, 114 {SHA: "sha2", Commit: github.GitCommit{Message: "this @menti-on has a hyphen"}}, 115 {SHA: "sha3", Commit: github.GitCommit{Message: "this @Menti-On has mixed case letters"}}, 116 {SHA: "sha4", Commit: github.GitCommit{Message: "fixes k/k#9999"}}, 117 {SHA: "sha5", Commit: github.GitCommit{Message: "Close k/k#9999"}}, 118 {SHA: "sha6", Commit: github.GitCommit{Message: "resolved k/k#9999"}}, 119 {SHA: "sha7", Commit: github.GitCommit{Message: "this is an email@address and is valid"}}, 120 }, 121 hasInvalidCommitMessageLabel: false, 122 123 addedLabel: fmt.Sprintf("k/k#3:%s", invalidCommitMsgLabel), 124 addedComments: []string{invalidCommitComment}, 125 }, 126 { 127 name: "msg does not contain invalid keywords but has label -> remove label", 128 action: github.PullRequestActionOpened, 129 commits: []github.RepositoryCommit{ 130 {SHA: "sha", Commit: github.GitCommit{Message: "this is a valid message"}}, 131 }, 132 hasInvalidCommitMessageLabel: true, 133 134 removedLabel: fmt.Sprintf("k/k#3:%s", invalidCommitMsgLabel), 135 }, 136 { 137 name: "contains valid title -> no-op", 138 action: github.PullRequestActionOpened, 139 commits: []github.RepositoryCommit{ 140 {SHA: "sha1", Commit: github.GitCommit{Message: "this is a valid message"}}, 141 }, 142 title: "valid title", 143 hasInvalidCommitMessageLabel: false, 144 }, 145 { 146 name: "contains invalid title with @mention -> add label and comment", 147 action: github.PullRequestActionOpened, 148 commits: []github.RepositoryCommit{ 149 {SHA: "sha1", Commit: github.GitCommit{Message: "this is a valid message"}}, 150 }, 151 title: "title with @mention", 152 hasInvalidCommitMessageLabel: false, 153 addedLabel: fmt.Sprintf("k/k#3:%s", invalidCommitMsgLabel), 154 addedComments: []string{invalidPRTitleComment}, 155 }, 156 { 157 name: "contains invalid title with fixes keyword -> add label and comment", 158 action: github.PullRequestActionOpened, 159 commits: []github.RepositoryCommit{ 160 {SHA: "sha1", Commit: github.GitCommit{Message: "this is a valid message"}}, 161 }, 162 title: "fixes #9999", 163 hasInvalidCommitMessageLabel: false, 164 addedLabel: fmt.Sprintf("k/k#3:%s", invalidCommitMsgLabel), 165 addedComments: []string{invalidPRTitleComment}, 166 }, 167 { 168 name: "contains invalid title and invalid commits -> add label and 2 comments", 169 action: github.PullRequestActionOpened, 170 commits: []github.RepositoryCommit{ 171 {SHA: "sha1", Commit: github.GitCommit{Message: "this is a @mention"}}, 172 {SHA: "sha2", Commit: github.GitCommit{Message: "this @menti-on has a hyphen"}}, 173 {SHA: "sha3", Commit: github.GitCommit{Message: "this @Menti-On has mixed case letters"}}, 174 {SHA: "sha4", Commit: github.GitCommit{Message: "fixes k/k#9999"}}, 175 {SHA: "sha5", Commit: github.GitCommit{Message: "Close k/k#9999"}}, 176 {SHA: "sha6", Commit: github.GitCommit{Message: "resolved k/k#9999"}}, 177 {SHA: "sha7", Commit: github.GitCommit{Message: "this is an email@address and is valid"}}, 178 }, 179 title: "title with @mention", 180 hasInvalidCommitMessageLabel: false, 181 addedLabel: fmt.Sprintf("k/k#3:%s", invalidCommitMsgLabel), 182 addedComments: []string{invalidCommitComment, invalidPRTitleComment}, 183 }, 184 { 185 name: "valid commits and invalid title, and has label -> keep label and add comment", 186 action: github.PullRequestActionOpened, 187 commits: []github.RepositoryCommit{ 188 {SHA: "sha", Commit: github.GitCommit{Message: "this is a valid message"}}, 189 }, 190 title: "title with @mention", 191 hasInvalidCommitMessageLabel: true, 192 addedComments: []string{invalidPRTitleComment}, 193 }, 194 { 195 name: "invalid commits and valid title, and has label -> keep label and add comment", 196 action: github.PullRequestActionOpened, 197 commits: []github.RepositoryCommit{ 198 {SHA: "sha1", Commit: github.GitCommit{Message: "this is a @mention"}}, 199 {SHA: "sha2", Commit: github.GitCommit{Message: "this @menti-on has a hyphen"}}, 200 {SHA: "sha3", Commit: github.GitCommit{Message: "this @Menti-On has mixed case letters"}}, 201 {SHA: "sha4", Commit: github.GitCommit{Message: "fixes k/k#9999"}}, 202 {SHA: "sha5", Commit: github.GitCommit{Message: "Close k/k#9999"}}, 203 {SHA: "sha6", Commit: github.GitCommit{Message: "resolved k/k#9999"}}, 204 {SHA: "sha7", Commit: github.GitCommit{Message: "this is an email@address and is valid"}}, 205 }, 206 title: "valid title", 207 hasInvalidCommitMessageLabel: true, 208 addedComments: []string{invalidCommitComment}, 209 }, 210 { 211 name: "valid title and valid commits, and has label -> remove label", 212 action: github.PullRequestActionOpened, 213 commits: []github.RepositoryCommit{ 214 {SHA: "sha", Commit: github.GitCommit{Message: "this is a valid message"}}, 215 }, 216 title: "valid title", 217 hasInvalidCommitMessageLabel: true, 218 removedLabel: fmt.Sprintf("k/k#3:%s", invalidCommitMsgLabel), 219 }, 220 } 221 222 for _, tc := range testcases { 223 t.Run(tc.name, func(t *testing.T) { 224 title := "fake title" 225 if tc.title != "" { 226 title = tc.title 227 } 228 229 event := makeFakePullRequestEvent(tc.action, title) 230 fc := fakegithub.NewFakeClient() 231 fc.PullRequests = map[int]*github.PullRequest{event.Number: &event.PullRequest} 232 fc.IssueComments = make(map[int][]github.IssueComment) 233 fc.CommitMap = map[string][]github.RepositoryCommit{ 234 "k/k#3": tc.commits, 235 } 236 237 if tc.hasInvalidCommitMessageLabel { 238 fc.IssueLabelsAdded = append(fc.IssueLabelsAdded, fmt.Sprintf("k/k#3:%s", invalidCommitMsgLabel)) 239 } 240 if err := handle(fc, logrus.WithField("plugin", pluginName), event, &fakePruner{}); err != nil { 241 t.Errorf("For case %s, didn't expect error from invalidcommitmsg plugin: %v", tc.name, err) 242 } 243 244 ok := tc.addedLabel == "" 245 if !ok { 246 for _, label := range fc.IssueLabelsAdded { 247 if reflect.DeepEqual(tc.addedLabel, label) { 248 ok = true 249 break 250 } 251 } 252 } 253 if !ok { 254 t.Errorf("Expected to add: %#v, Got %#v in case %s.", tc.addedLabel, fc.IssueLabelsAdded, tc.name) 255 } 256 257 ok = tc.removedLabel == "" 258 if !ok { 259 for _, label := range fc.IssueLabelsRemoved { 260 if reflect.DeepEqual(tc.removedLabel, label) { 261 ok = true 262 break 263 } 264 } 265 } 266 if !ok { 267 t.Errorf("Expected to remove: %#v, Got %#v in case %s.", tc.removedLabel, fc.IssueLabelsRemoved, tc.name) 268 } 269 270 comments := fc.IssueCommentsAdded 271 if len(comments) != len(tc.addedComments) { 272 t.Errorf("Expected %v comments, but received %v", len(tc.addedComments), len(comments)) 273 return 274 } 275 276 if diff := cmp.Diff(comments, tc.addedComments); diff != "" { 277 t.Errorf("Actual comments differ from expected comments: %s", diff) 278 } 279 }) 280 } 281 }