github.com/yrj2011/jx-test-infra@v0.0.0-20190529031832-7a2065ee98eb/prow/external-plugins/cherrypicker/server_test.go (about) 1 /* 2 Copyright 2017 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 main 18 19 import ( 20 "fmt" 21 "sync" 22 "testing" 23 24 "github.com/sirupsen/logrus" 25 26 "k8s.io/test-infra/prow/git/localgit" 27 "k8s.io/test-infra/prow/github" 28 ) 29 30 type fghc struct { 31 sync.Mutex 32 pr *github.PullRequest 33 isMember bool 34 35 patch []byte 36 comments []string 37 prs []string 38 prComments []github.IssueComment 39 createdNum int 40 orgMembers []github.TeamMember 41 } 42 43 func (f *fghc) AssignIssue(org, repo string, number int, logins []string) error { 44 f.Lock() 45 defer f.Unlock() 46 return nil 47 } 48 49 func (f *fghc) GetPullRequest(org, repo string, number int) (*github.PullRequest, error) { 50 f.Lock() 51 defer f.Unlock() 52 return f.pr, nil 53 } 54 55 func (f *fghc) GetPullRequestPatch(org, repo string, number int) ([]byte, error) { 56 f.Lock() 57 defer f.Unlock() 58 return f.patch, nil 59 } 60 61 func (f *fghc) CreateComment(org, repo string, number int, comment string) error { 62 f.Lock() 63 defer f.Unlock() 64 f.comments = append(f.comments, fmt.Sprintf("%s/%s#%d %s", org, repo, number, comment)) 65 return nil 66 } 67 68 func (f *fghc) IsMember(org, user string) (bool, error) { 69 f.Lock() 70 defer f.Unlock() 71 return f.isMember, nil 72 } 73 74 func (f *fghc) GetRepo(owner, name string) (github.Repo, error) { 75 f.Lock() 76 defer f.Unlock() 77 return github.Repo{}, nil 78 } 79 80 var expectedFmt = `repo=%s title=%q body=%q head=%s base=%s maintainer_can_modify=%t` 81 82 func (f *fghc) CreatePullRequest(org, repo, title, body, head, base string, canModify bool) (int, error) { 83 f.Lock() 84 defer f.Unlock() 85 f.prs = append(f.prs, fmt.Sprintf(expectedFmt, org+"/"+repo, title, body, head, base, canModify)) 86 return f.createdNum, nil 87 } 88 89 func (f *fghc) ListIssueComments(org, repo string, number int) ([]github.IssueComment, error) { 90 f.Lock() 91 defer f.Unlock() 92 return f.prComments, nil 93 } 94 95 func (f *fghc) ListOrgMembers(org, role string) ([]github.TeamMember, error) { 96 f.Lock() 97 defer f.Unlock() 98 if role != "all" { 99 return nil, fmt.Errorf("all is only supported role, not: %s", role) 100 } 101 return f.orgMembers, nil 102 } 103 104 func (f *fghc) CreateFork(org, repo string) error { 105 return nil 106 } 107 108 var initialFiles = map[string][]byte{ 109 "bar.go": []byte(`// Package bar does an interesting thing. 110 package bar 111 112 // Foo does a thing. 113 func Foo(wow int) int { 114 return 42 + wow 115 } 116 `), 117 } 118 119 var patch = []byte(`From af468c9e69dfdf39db591f1e3e8de5b64b0e62a2 Mon Sep 17 00:00:00 2001 120 From: Wise Guy <wise@guy.com> 121 Date: Thu, 19 Oct 2017 15:14:36 +0200 122 Subject: [PATCH] Update magic number 123 124 --- 125 bar.go | 3 ++- 126 1 file changed, 2 insertions(+), 1 deletion(-) 127 128 diff --git a/bar.go b/bar.go 129 index 1ea52dc..5bd70a9 100644 130 --- a/bar.go 131 +++ b/bar.go 132 @@ -3,5 +3,6 @@ package bar 133 134 // Foo does a thing. 135 func Foo(wow int) int { 136 - return 42 + wow 137 + // Needs to be 49 because of a reason. 138 + return 49 + wow 139 } 140 `) 141 142 func TestCherryPickIC(t *testing.T) { 143 lg, c, err := localgit.New() 144 if err != nil { 145 t.Fatalf("Making localgit: %v", err) 146 } 147 defer func() { 148 if err := lg.Clean(); err != nil { 149 t.Errorf("Cleaning up localgit: %v", err) 150 } 151 if err := c.Clean(); err != nil { 152 t.Errorf("Cleaning up client: %v", err) 153 } 154 }() 155 if err := lg.MakeFakeRepo("foo", "bar"); err != nil { 156 t.Fatalf("Making fake repo: %v", err) 157 } 158 if err := lg.AddCommit("foo", "bar", initialFiles); err != nil { 159 t.Fatalf("Adding initial commit: %v", err) 160 } 161 if err := lg.CheckoutNewBranch("foo", "bar", "stage"); err != nil { 162 t.Fatalf("Checking out pull branch: %v", err) 163 } 164 165 ghc := &fghc{ 166 pr: &github.PullRequest{ 167 Base: github.PullRequestBranch{ 168 Ref: "master", 169 }, 170 Merged: true, 171 Title: "This is a fix for X", 172 }, 173 isMember: true, 174 createdNum: 3, 175 patch: patch, 176 } 177 ic := github.IssueCommentEvent{ 178 Action: github.IssueCommentActionCreated, 179 Repo: github.Repo{ 180 Owner: github.User{ 181 Login: "foo", 182 }, 183 Name: "bar", 184 FullName: "foo/bar", 185 }, 186 Issue: github.Issue{ 187 Number: 2, 188 State: "closed", 189 PullRequest: &struct{}{}, 190 }, 191 Comment: github.IssueComment{ 192 User: github.User{ 193 Login: "wiseguy", 194 }, 195 Body: "/cherrypick stage", 196 }, 197 } 198 199 botName := "ci-robot" 200 expectedRepo := "foo/bar" 201 expectedTitle := "[stage] This is a fix for X" 202 expectedBody := "This is an automated cherry-pick of #2\n\n/assign wiseguy" 203 expectedBase := "stage" 204 expectedHead := fmt.Sprintf(botName+":"+cherryPickBranchFmt, 2, expectedBase) 205 expected := fmt.Sprintf(expectedFmt, expectedRepo, expectedTitle, expectedBody, expectedHead, expectedBase, true) 206 207 getSecret := func() []byte { 208 return []byte("sha=abcdefg") 209 } 210 211 s := &Server{ 212 botName: botName, 213 gc: c, 214 push: func(repo, newBranch string) error { return nil }, 215 ghc: ghc, 216 tokenGenerator: getSecret, 217 log: logrus.StandardLogger().WithField("client", "cherrypicker"), 218 repos: []github.Repo{{Fork: true, FullName: "ci-robot/bar"}}, 219 220 prowAssignments: true, 221 } 222 223 if err := s.handleIssueComment(logrus.NewEntry(logrus.StandardLogger()), ic); err != nil { 224 t.Errorf("unexpected error: %v", err) 225 } 226 if ghc.prs[0] != expected { 227 t.Errorf("Expected (%d):\n%s\nGot (%d):\n%+v\n", len(expected), expected, len(ghc.prs[0]), ghc.prs[0]) 228 } 229 } 230 231 func TestCherryPickPR(t *testing.T) { 232 lg, c, err := localgit.New() 233 if err != nil { 234 t.Fatalf("Making localgit: %v", err) 235 } 236 defer func() { 237 if err := lg.Clean(); err != nil { 238 t.Errorf("Cleaning up localgit: %v", err) 239 } 240 if err := c.Clean(); err != nil { 241 t.Errorf("Cleaning up client: %v", err) 242 } 243 }() 244 if err := lg.MakeFakeRepo("foo", "bar"); err != nil { 245 t.Fatalf("Making fake repo: %v", err) 246 } 247 if err := lg.AddCommit("foo", "bar", initialFiles); err != nil { 248 t.Fatalf("Adding initial commit: %v", err) 249 } 250 if err := lg.CheckoutNewBranch("foo", "bar", "release-1.5"); err != nil { 251 t.Fatalf("Checking out pull branch: %v", err) 252 } 253 if err := lg.CheckoutNewBranch("foo", "bar", "release-1.6"); err != nil { 254 t.Fatalf("Checking out pull branch: %v", err) 255 } 256 257 ghc := &fghc{ 258 orgMembers: []github.TeamMember{ 259 { 260 Login: "approver", 261 }, 262 { 263 Login: "merge-bot", 264 }, 265 }, 266 prComments: []github.IssueComment{ 267 { 268 User: github.User{ 269 Login: "developer", 270 }, 271 Body: "a review comment", 272 }, 273 { 274 User: github.User{ 275 Login: "approver", 276 }, 277 Body: "/cherrypick release-1.5\r", 278 }, 279 { 280 User: github.User{ 281 Login: "approver", 282 }, 283 Body: "/cherrypick release-1.6", 284 }, 285 { 286 User: github.User{ 287 Login: "fan", 288 }, 289 Body: "/cherrypick release-1.7", 290 }, 291 { 292 User: github.User{ 293 Login: "approver", 294 }, 295 Body: "/approve", 296 }, 297 { 298 User: github.User{ 299 Login: "merge-bot", 300 }, 301 Body: "Automatic merge from submit-queue.", 302 }, 303 }, 304 isMember: true, 305 createdNum: 3, 306 patch: patch, 307 } 308 pr := github.PullRequestEvent{ 309 Action: github.PullRequestActionClosed, 310 PullRequest: github.PullRequest{ 311 Base: github.PullRequestBranch{ 312 Ref: "master", 313 Repo: github.Repo{ 314 Owner: github.User{ 315 Login: "foo", 316 }, 317 Name: "bar", 318 }, 319 }, 320 Number: 2, 321 Merged: true, 322 MergeSHA: new(string), 323 Title: "This is a fix for Y", 324 }, 325 } 326 327 botName := "ci-robot" 328 329 getSecret := func() []byte { 330 return []byte("sha=abcdefg") 331 } 332 333 s := &Server{ 334 botName: botName, 335 gc: c, 336 push: func(repo, newBranch string) error { return nil }, 337 ghc: ghc, 338 tokenGenerator: getSecret, 339 log: logrus.StandardLogger().WithField("client", "cherrypicker"), 340 repos: []github.Repo{{Fork: true, FullName: "ci-robot/bar"}}, 341 342 prowAssignments: false, 343 } 344 345 if err := s.handlePullRequest(logrus.NewEntry(logrus.StandardLogger()), pr); err != nil { 346 t.Errorf("unexpected error: %v", err) 347 } 348 349 var expectedFn = func(branch string) string { 350 expectedRepo := "foo/bar" 351 expectedTitle := fmt.Sprintf("[%s] This is a fix for Y", branch) 352 expectedBody := "This is an automated cherry-pick of #2" 353 expectedHead := fmt.Sprintf(botName+":"+cherryPickBranchFmt, 2, branch) 354 return fmt.Sprintf(expectedFmt, expectedRepo, expectedTitle, expectedBody, expectedHead, branch, true) 355 } 356 357 if len(ghc.prs) != 2 { 358 t.Fatalf("Expected %d PRs, got %d", 2, len(ghc.prs)) 359 } 360 361 expectedBranches := []string{"release-1.5", "release-1.6"} 362 seenBranches := make(map[string]struct{}) 363 for _, pr := range ghc.prs { 364 if pr != expectedFn("release-1.5") && pr != expectedFn("release-1.6") { 365 t.Errorf("Unexpected PR:\n%s\nExpected to target one of the following branches: %v", pr, expectedBranches) 366 } 367 if pr == expectedFn("release-1.5") { 368 seenBranches["release-1.5"] = struct{}{} 369 } 370 if pr == expectedFn("release-1.6") { 371 seenBranches["release-1.6"] = struct{}{} 372 } 373 } 374 if len(seenBranches) != 2 { 375 t.Fatalf("Expected to see PRs for %d branches, got %d (%v)", 2, len(seenBranches), seenBranches) 376 } 377 }