github.com/zppinho/prow@v0.0.0-20240510014325-1738badeb017/pkg/config/inrepoconfig_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 config 18 19 import ( 20 "errors" 21 "fmt" 22 "os" 23 "path" 24 "testing" 25 26 "github.com/google/go-cmp/cmp" 27 "sigs.k8s.io/prow/pkg/git/localgit" 28 "sigs.k8s.io/prow/pkg/git/v2" 29 "sigs.k8s.io/prow/pkg/kube" 30 ) 31 32 var defaultBranch = localgit.DefaultBranch("") 33 34 func TestDefaultProwYAMLGetterV2(t *testing.T) { 35 testDefaultProwYAMLGetter(localgit.NewV2, t) 36 } 37 38 func testDefaultProwYAMLGetter(clients localgit.Clients, t *testing.T) { 39 org, defaultRepo := "org", "repo" 40 testCases := []struct { 41 name string 42 baseContent map[string][]byte 43 headContent map[string][]byte 44 config *Config 45 dontPassGitClient bool 46 validate func(*ProwYAML, error) error 47 repo string 48 }{ 49 // presubmits 50 { 51 name: "Basic happy path (presubmits)", 52 baseContent: map[string][]byte{ 53 ".prow.yaml": []byte(`presubmits: [{"name": "hans", "annotations": {"foo.bar": "foobar"}, "spec": {"containers": [{}]}}]`), 54 }, 55 validate: func(p *ProwYAML, err error) error { 56 if err != nil { 57 return fmt.Errorf("unexpected error: %w", err) 58 } 59 if n := len(p.Presubmits); n != 1 || p.Presubmits[0].Name != "hans" { 60 return fmt.Errorf(`expected exactly one presubmit with name "hans", got %v`, p.Presubmits) 61 } 62 if diff := cmp.Diff(p.Presubmits[0].Annotations, map[string]string{"foo.bar": "foobar"}); diff != "" { 63 return errors.New(diff) 64 } 65 return nil 66 }, 67 }, 68 { 69 name: "Merging is executed (presubmits)", 70 headContent: map[string][]byte{ 71 ".prow.yaml": []byte(`presubmits: [{"name": "hans", "spec": {"containers": [{}]}}]`), 72 }, 73 validate: func(p *ProwYAML, err error) error { 74 if err != nil { 75 return fmt.Errorf("unexpected error: %w", err) 76 } 77 if n := len(p.Presubmits); n != 1 || p.Presubmits[0].Name != "hans" { 78 return fmt.Errorf(`expected exactly one presubmit with name "hans", got %v`, p.Presubmits) 79 } 80 return nil 81 }, 82 }, 83 { 84 name: "Presubmit defaulting is executed", 85 baseContent: map[string][]byte{ 86 ".prow.yaml": []byte(`presubmits: [{"name": "hans", "spec": {"containers": [{}]}}]`), 87 }, 88 validate: func(p *ProwYAML, err error) error { 89 if err != nil { 90 return fmt.Errorf("unexpected error: %w", err) 91 } 92 if n := len(p.Presubmits); n != 1 || p.Presubmits[0].Name != "hans" { 93 return fmt.Errorf(`expected exactly one presubmit with name "hans", got %v`, p.Presubmits) 94 } 95 if p.Presubmits[0].Context != "hans" { 96 return fmt.Errorf(`expected defaulting to set context to "hans", was %q`, p.Presubmits[0].Context) 97 } 98 return nil 99 }, 100 }, 101 { 102 name: "Presubmit validation is executed", 103 baseContent: map[string][]byte{ 104 ".prow.yaml": []byte(`presubmits: [{"name": "hans", "spec": {"containers": [{}]}},{"name": "hans", "spec": {"containers": [{}]}}]`), 105 }, 106 validate: func(_ *ProwYAML, err error) error { 107 if err == nil { 108 return errors.New("error is nil") 109 } 110 expectedErrMsg := "duplicated presubmit jobs (consider both inrepo and central config): [hans]" 111 if err.Error() != expectedErrMsg { 112 return fmt.Errorf("expected error message to be %q, was %q", expectedErrMsg, err.Error()) 113 } 114 return nil 115 }, 116 }, 117 { 118 name: "Presubmit validation includes static presubmits", 119 baseContent: map[string][]byte{ 120 ".prow.yaml": []byte(`presubmits: [{"name": "hans", "spec": {"containers": [{}]}}]`), 121 }, 122 config: &Config{JobConfig: JobConfig{ 123 PresubmitsStatic: map[string][]Presubmit{ 124 org + "/" + defaultRepo: {{Reporter: Reporter{Context: "hans"}, JobBase: JobBase{Name: "hans"}}}, 125 }, 126 }}, 127 validate: func(_ *ProwYAML, err error) error { 128 if err == nil { 129 return errors.New("error is nil") 130 } 131 expectedErrMsg := "duplicated presubmit jobs (consider both inrepo and central config): [hans]" 132 if err.Error() != expectedErrMsg { 133 return fmt.Errorf("expected error message to be %q, was %q", expectedErrMsg, err.Error()) 134 } 135 return nil 136 }, 137 }, 138 { 139 name: "Branchconfig on presubmit is allowed", 140 baseContent: map[string][]byte{ 141 ".prow.yaml": []byte(`presubmits: [{"name": "hans", "spec": {"containers": [{}]}, "branches":["master"]}]`), 142 }, 143 validate: func(p *ProwYAML, err error) error { 144 if err != nil { 145 return fmt.Errorf("unexpected error: %w", err) 146 } 147 if n := len(p.Presubmits); n != 1 || p.Presubmits[0].Name != "hans" { 148 return fmt.Errorf(`expected exactly one postsubmit with name "hans", got %v`, p.Presubmits) 149 } 150 if n := len(p.Presubmits[0].Branches); n != 1 || p.Presubmits[0].Branches[0] != "master" { 151 return fmt.Errorf(`expected exactly one postsubmit branch with name "master", got %v`, p.Presubmits[0].Branches) 152 } 153 return nil 154 }, 155 }, 156 { 157 name: "Not allowed cluster is rejected (presubmits)", 158 baseContent: map[string][]byte{ 159 ".prow.yaml": []byte(`presubmits: [{"name": "hans", "cluster": "privileged", "spec": {"containers": [{}]}}]`), 160 }, 161 validate: func(_ *ProwYAML, err error) error { 162 if err == nil { 163 return errors.New("error is nil") 164 } 165 expectedErrMsg := "cluster \"privileged\" is not allowed for repository \"org/repo\"" 166 if err.Error() != expectedErrMsg { 167 return fmt.Errorf("expected error message to be %q, was %q", expectedErrMsg, err.Error()) 168 } 169 return nil 170 }, 171 }, 172 // postsubmits 173 { 174 name: "Basic happy path (postsubmits)", 175 baseContent: map[string][]byte{ 176 ".prow.yaml": []byte(`postsubmits: [{"name": "hans", "spec": {"containers": [{}]}}]`), 177 }, 178 validate: func(p *ProwYAML, err error) error { 179 if err != nil { 180 return fmt.Errorf("unexpected error: %w", err) 181 } 182 if n := len(p.Postsubmits); n != 1 || p.Postsubmits[0].Name != "hans" { 183 return fmt.Errorf(`expected exactly one postsubmit with name "hans", got %v`, p.Postsubmits) 184 } 185 return nil 186 }, 187 }, 188 { 189 name: "Postsubmit defaulting is executed", 190 baseContent: map[string][]byte{ 191 ".prow.yaml": []byte(`postsubmits: [{"name": "hans", "spec": {"containers": [{}]}}]`), 192 }, 193 validate: func(p *ProwYAML, err error) error { 194 if err != nil { 195 return fmt.Errorf("unexpected error: %w", err) 196 } 197 if n := len(p.Postsubmits); n != 1 || p.Postsubmits[0].Name != "hans" { 198 return fmt.Errorf(`expected exactly one postsubmit with name "hans", got %v`, p.Postsubmits) 199 } 200 if p.Postsubmits[0].Context != "hans" { 201 return fmt.Errorf(`expected defaulting to set context to "hans", was %q`, p.Postsubmits[0].Context) 202 } 203 return nil 204 }, 205 }, 206 { 207 name: "Postsubmit validation is executed", 208 baseContent: map[string][]byte{ 209 ".prow.yaml": []byte(`postsubmits: [{"name": "hans", "spec": {"containers": [{}]}},{"name": "hans", "spec": {"containers": [{}]}}]`), 210 }, 211 validate: func(_ *ProwYAML, err error) error { 212 if err == nil { 213 return errors.New("error is nil") 214 } 215 expectedErrMsg := "duplicated postsubmit jobs (consider both inrepo and central config): [hans]" 216 if err.Error() != expectedErrMsg { 217 return fmt.Errorf("expected error message to be %q, was %q", expectedErrMsg, err.Error()) 218 } 219 return nil 220 }, 221 }, 222 { 223 name: "Postsubmit validation includes static postsubmits", 224 baseContent: map[string][]byte{ 225 ".prow.yaml": []byte(`postsubmits: [{"name": "hans", "spec": {"containers": [{}]}}]`), 226 }, 227 config: &Config{JobConfig: JobConfig{ 228 PostsubmitsStatic: map[string][]Postsubmit{ 229 org + "/" + defaultRepo: {{Reporter: Reporter{Context: "hans"}, JobBase: JobBase{Name: "hans"}}}, 230 }, 231 }}, 232 validate: func(_ *ProwYAML, err error) error { 233 if err == nil { 234 return errors.New("error is nil") 235 } 236 expectedErrMsg := "duplicated postsubmit jobs (consider both inrepo and central config): [hans]" 237 if err.Error() != expectedErrMsg { 238 return fmt.Errorf("expected error message to be %q, was %q", expectedErrMsg, err.Error()) 239 } 240 return nil 241 }, 242 }, 243 { 244 name: "Branchconfig on postsubmit is allowed", 245 baseContent: map[string][]byte{ 246 ".prow.yaml": []byte(`postsubmits: [{"name": "hans", "spec": {"containers": [{}]}, "branches":["master"]}]`), 247 }, 248 validate: func(p *ProwYAML, err error) error { 249 if err != nil { 250 return fmt.Errorf("unexpected error: %w", err) 251 } 252 if n := len(p.Postsubmits); n != 1 || p.Postsubmits[0].Name != "hans" { 253 return fmt.Errorf(`expected exactly one postsubmit with name "hans", got %v`, p.Postsubmits) 254 } 255 if n := len(p.Postsubmits[0].Branches); n != 1 || p.Postsubmits[0].Branches[0] != "master" { 256 return fmt.Errorf(`expected exactly one postsubmit branch with name "master", got %v`, p.Postsubmits[0].Branches) 257 } 258 return nil 259 }, 260 }, 261 // prowyaml 262 { 263 name: "Not allowed cluster is rejected", 264 baseContent: map[string][]byte{ 265 ".prow.yaml": []byte(`postsubmits: [{"name": "hans", "cluster": "privileged", "spec": {"containers": [{}]}}]`), 266 }, 267 validate: func(_ *ProwYAML, err error) error { 268 if err == nil { 269 return errors.New("error is nil") 270 } 271 expectedErrMsg := "cluster \"privileged\" is not allowed for repository \"org/repo\"" 272 if err.Error() != expectedErrMsg { 273 return fmt.Errorf("expected error message to be %q, was %q", expectedErrMsg, err.Error()) 274 } 275 return nil 276 }, 277 }, 278 { 279 name: "No prow.yaml, no error, no nullpointer", 280 validate: func(p *ProwYAML, err error) error { 281 if err != nil { 282 return fmt.Errorf("unexpected error: %w", err) 283 } 284 if p == nil { 285 return errors.New("prowYAML is nil") 286 } 287 if n := len(p.Presubmits); n != 0 { 288 return fmt.Errorf("expected to get zero presubmits, got %d", n) 289 } 290 return nil 291 }, 292 }, 293 { 294 name: "Yaml unmarshaling is not strict", 295 baseContent: map[string][]byte{ 296 ".prow.yaml": []byte(`postsubmits: [{"name": "hans", "undef_attr": true, "spec": {"containers": [{}]}}]`), 297 }, 298 validate: func(p *ProwYAML, err error) error { 299 if err != nil { 300 return fmt.Errorf("unexpected error: %w", err) 301 } 302 if n := len(p.Postsubmits); n != 1 || p.Postsubmits[0].Name != "hans" { 303 return fmt.Errorf(`expected exactly one postsubmit with name "hans", got %v`, p.Postsubmits) 304 } 305 return nil 306 }, 307 }, 308 // git client 309 { 310 name: "No panic on nil gitClient", 311 dontPassGitClient: true, 312 validate: func(_ *ProwYAML, err error) error { 313 if err == nil || err.Error() != "gitClient is nil" { 314 return fmt.Errorf(`expected error to be "gitClient is nil", was %v`, err) 315 } 316 return nil 317 }, 318 }, 319 // .prow directory 320 { 321 name: "Basic happy path (.prow directory, single file)", 322 baseContent: map[string][]byte{ 323 ".prow/base.yaml": []byte(`presubmits: [{"name": "hans", "spec": {"containers": [{}]}}]`), 324 }, 325 validate: func(p *ProwYAML, err error) error { 326 if err != nil { 327 return fmt.Errorf("unexpected error: %w", err) 328 } 329 if n := len(p.Presubmits); n != 1 || p.Presubmits[0].Name != "hans" { 330 return fmt.Errorf(`expected exactly one presubmit with name "hans", got %v`, p.Presubmits) 331 } 332 return nil 333 }, 334 }, 335 { 336 name: "Prefer .prow directory over .prow.yaml file", 337 baseContent: map[string][]byte{ 338 ".prow.yaml": []byte(`presubmits: [{"name": "hans", "spec": {"containers": [{}]}}]`), 339 ".prow/base.yaml": []byte(`presubmits: [{"name": "kurt", "spec": {"containers": [{}]}}]`), 340 }, 341 validate: func(p *ProwYAML, err error) error { 342 if err != nil { 343 return fmt.Errorf("unexpected error: %w", err) 344 } 345 if n := len(p.Presubmits); n != 1 || p.Presubmits[0].Name != "kurt" { 346 return fmt.Errorf(`expected exactly one presubmit with name "kurt", got %v`, p.Presubmits) 347 } 348 return nil 349 }, 350 }, 351 { 352 name: "Merge presubmits under .prow directory", 353 baseContent: map[string][]byte{ 354 ".prow/one.yaml": []byte(`presubmits: [{"name": "hans", "spec": {"containers": [{}]}}]`), 355 ".prow/two.yaml": []byte(`presubmits: [{"name": "kurt", "spec": {"containers": [{}]}}]`), 356 }, 357 validate: func(p *ProwYAML, err error) error { 358 if err != nil { 359 return fmt.Errorf("unexpected error: %w", err) 360 } 361 if n := len(p.Presubmits); n != 2 || 362 p.Presubmits[0].Name != "hans" || 363 p.Presubmits[1].Name != "kurt" { 364 return fmt.Errorf(`expected exactly two presubmit with name "hans" and "kurt", got %v`, p.Presubmits) 365 } 366 return nil 367 }, 368 }, 369 { 370 name: "Merge presubmits several levels under .prow directory", 371 baseContent: map[string][]byte{ 372 ".prow/sub1/sub2/one.yaml": []byte(`presubmits: [{"name": "hans", "spec": {"containers": [{}]}}]`), 373 ".prow/sub3/two.yaml": []byte(`presubmits: [{"name": "kurt", "spec": {"containers": [{}]}}]`), 374 }, 375 validate: func(p *ProwYAML, err error) error { 376 if err != nil { 377 return fmt.Errorf("unexpected error: %w", err) 378 } 379 if n := len(p.Presubmits); n != 2 || 380 p.Presubmits[0].Name != "hans" || 381 p.Presubmits[1].Name != "kurt" { 382 return fmt.Errorf(`expected exactly two presubmit with name "hans" and "kurt", got %v`, p.Presubmits) 383 } 384 return nil 385 }, 386 }, 387 { 388 name: "Merge postsubmits under .prow directory", 389 baseContent: map[string][]byte{ 390 ".prow/one.yaml": []byte(`postsubmits: [{"name": "hans", "spec": {"containers": [{}]}}]`), 391 ".prow/two.yaml": []byte(`postsubmits: [{"name": "kurt", "spec": {"containers": [{}]}}]`), 392 }, 393 validate: func(p *ProwYAML, err error) error { 394 if err != nil { 395 return fmt.Errorf("unexpected error: %w", err) 396 } 397 if n := len(p.Postsubmits); n != 2 || 398 p.Postsubmits[0].Name != "hans" || 399 p.Postsubmits[1].Name != "kurt" { 400 return fmt.Errorf(`expected exactly two postsubmit with name "hans" and "kurt", got %v`, p.Postsubmits) 401 } 402 return nil 403 }, 404 }, 405 { 406 name: "Merge postsubmits several levels under .prow directory", 407 baseContent: map[string][]byte{ 408 ".prow/sub1/sub2/one.yaml": []byte(`postsubmits: [{"name": "hans", "spec": {"containers": [{}]}}]`), 409 ".prow/sub3/two.yaml": []byte(`postsubmits: [{"name": "kurt", "spec": {"containers": [{}]}}]`), 410 }, 411 validate: func(p *ProwYAML, err error) error { 412 if err != nil { 413 return fmt.Errorf("unexpected error: %w", err) 414 } 415 if n := len(p.Postsubmits); n != 2 || 416 p.Postsubmits[0].Name != "hans" || 417 p.Postsubmits[1].Name != "kurt" { 418 return fmt.Errorf(`expected exactly two postsubmit with names "hans" and "kurt", got %v`, p.Postsubmits) 419 } 420 return nil 421 }, 422 }, 423 { 424 name: "Merge presets under .prow directory", 425 baseContent: map[string][]byte{ 426 ".prow/one.yaml": []byte(`presets: [{"labels": {"hans": "hansValue"}}]`), 427 ".prow/two.yaml": []byte(`presets: [{"labels": {"kurt": "kurtValue"}}]`), 428 }, 429 validate: func(p *ProwYAML, err error) error { 430 if err != nil { 431 return fmt.Errorf("unexpected error: %w", err) 432 } 433 if n := len(p.Presets); n != 2 || 434 p.Presets[0].Labels["hans"] != "hansValue" || 435 p.Presets[1].Labels["kurt"] != "kurtValue" { 436 return fmt.Errorf(`expected exactly two presets with labels "hans": "hansValue" and "kurt": "kurtValue", got %v`, p.Presets) 437 } 438 return nil 439 }, 440 }, 441 { 442 name: "Merge presets several levels under .prow directory", 443 baseContent: map[string][]byte{ 444 ".prow/sub1/sub2/one.yaml": []byte(`presets: [{"labels": {"hans": "hansValue"}}]`), 445 ".prow/sub3/two.yaml": []byte(`presets: [{"labels": {"kurt": "kurtValue"}}]`), 446 }, 447 validate: func(p *ProwYAML, err error) error { 448 if err != nil { 449 return fmt.Errorf("unexpected error: %w", err) 450 } 451 if n := len(p.Presets); n != 2 || 452 p.Presets[0].Labels["hans"] != "hansValue" || 453 p.Presets[1].Labels["kurt"] != "kurtValue" { 454 return fmt.Errorf(`expected exactly two presets with labels "hans": "hansValue" and "kurt": "kurtValue", got %v`, p.Presets) 455 } 456 return nil 457 }, 458 }, 459 { 460 name: "Merge presubmits, postsubmits and presets several levels under .prow directory", 461 baseContent: map[string][]byte{ 462 ".prow/sub1/sub2/one.yaml": []byte(`presubmits: [{"name": "hans", "spec": {"containers": [{}]}}] 463 postsubmits: [{"name": "karl", "spec": {"containers": [{}]}}] 464 presets: [{"labels": {"karl": "karlValue"}}] 465 `), 466 ".prow/sub3/two.yaml": []byte(`presubmits: [{"name": "kurt", "spec": {"containers": [{}]}}] 467 postsubmits: [{"name": "oli", "spec": {"containers": [{}]}}]`), 468 ".prow/sub4//sub5/sub6/three.yaml": []byte(`presets: [{"labels": {"henning": "henningValue"}}]`), 469 }, 470 validate: func(p *ProwYAML, err error) error { 471 if err != nil { 472 return fmt.Errorf("unexpected error: %w", err) 473 } 474 if n := len(p.Presubmits); n != 2 || 475 p.Presubmits[0].Name != "hans" || 476 p.Presubmits[1].Name != "kurt" { 477 return fmt.Errorf(`expected exactly two presubmits with names "hans" and "kurt" got %v`, p.Presubmits) 478 } 479 if n := len(p.Postsubmits); n != 2 || 480 p.Postsubmits[0].Name != "karl" || 481 p.Postsubmits[1].Name != "oli" { 482 return fmt.Errorf(`expected exactly two postsubmits with names "karl" and "oli", got %v`, p.Postsubmits) 483 } 484 if n := len(p.Presets); n != 2 || 485 p.Presets[0].Labels["karl"] != "karlValue" || 486 p.Presets[1].Labels["henning"] != "henningValue" { 487 return fmt.Errorf(`expected exactly two presets with labels "karl": "karlValue" and "henning": "henningValue", got %v`, p.Presets) 488 } 489 return nil 490 }, 491 }, 492 { 493 name: "Non-.yaml files under .prow directory are allowed", 494 baseContent: map[string][]byte{ 495 ".prow/one.yaml": []byte(`presubmits: [{"name": "hans", "spec": {"containers": [{}]}}]`), 496 ".prow/OWNERS": []byte(`approvers: [approver1, approver2]`), 497 ".prow/sub/two.yaml": []byte(`presubmits: [{"name": "kurt", "spec": {"containers": [{}]}}]`), 498 ".prow/sub/OWNERS": []byte(`approvers: [approver3, approver4]`), 499 }, 500 validate: func(p *ProwYAML, err error) error { 501 if err != nil { 502 return fmt.Errorf("unexpected error: %w", err) 503 } 504 if n := len(p.Presubmits); n != 2 || 505 p.Presubmits[0].Name != "hans" || 506 p.Presubmits[1].Name != "kurt" { 507 return fmt.Errorf(`expected exactly two presubmit with name "hans" and "kurt", got %v`, p.Presubmits) 508 } 509 return nil 510 }, 511 }, 512 { 513 name: "Both .yaml and .yml files are allowed under .prow directory)", 514 baseContent: map[string][]byte{ 515 ".prow/one.yaml": []byte(`presubmits: [{"name": "hans", "spec": {"containers": [{}]}}]`), 516 ".prow/two.yml": []byte(`presubmits: [{"name": "kurt", "spec": {"containers": [{}]}}]`), 517 }, 518 validate: func(p *ProwYAML, err error) error { 519 if err != nil { 520 return fmt.Errorf("unexpected error: %w", err) 521 } 522 if n := len(p.Presubmits); n != 2 || 523 p.Presubmits[0].Name != "hans" || 524 p.Presubmits[1].Name != "kurt" { 525 return fmt.Errorf(`expected exactly two presubmit with name "hans" and "kurt", got %v`, p.Presubmits) 526 } 527 return nil 528 }, 529 }, 530 { 531 name: "Basic happy path (presubmits, gerrit repo)", 532 baseContent: map[string][]byte{ 533 ".prow.yaml": []byte(`presubmits: [{"name": "hans", "spec": {"containers": [{}]}}]`), 534 }, 535 validate: func(p *ProwYAML, err error) error { 536 if err != nil { 537 return fmt.Errorf("unexpected error: %w", err) 538 } 539 if n := len(p.Presubmits); n != 1 || p.Presubmits[0].Name != "hans" { 540 return fmt.Errorf(`expected exactly one presubmit with name "hans", got %v`, p.Presubmits) 541 } 542 return nil 543 }, 544 repo: "repo/name", 545 }, 546 } 547 548 for idx := range testCases { 549 tc := testCases[idx] 550 t.Run(tc.name, func(t *testing.T) { 551 t.Parallel() 552 553 repo := defaultRepo 554 if len(tc.repo) > 0 { 555 repo = tc.repo 556 } 557 558 lg, gc, err := clients() 559 if err != nil { 560 t.Fatalf("Making local git repo: %v", err) 561 } 562 defer func() { 563 if err := lg.Clean(); err != nil { 564 t.Errorf("Error cleaning LocalGit: %v", err) 565 } 566 if err := gc.Clean(); err != nil { 567 t.Errorf("Error cleaning Client: %v", err) 568 } 569 }() 570 571 if err := lg.MakeFakeRepo(org, repo); err != nil { 572 t.Fatalf("Making fake repo: %v", err) 573 } 574 if tc.baseContent != nil { 575 if err := lg.AddCommit(org, repo, tc.baseContent); err != nil { 576 t.Fatalf("failed to commit baseContent: %v", err) 577 } 578 } 579 if tc.headContent != nil { 580 if err := lg.CheckoutNewBranch(org, repo, "can-I-haz-pulled"); err != nil { 581 t.Fatalf("failed to create new branch: %v", err) 582 } 583 if err := lg.AddCommit(org, repo, tc.headContent); err != nil { 584 t.Fatalf("failed to add head commit: %v", err) 585 } 586 } 587 588 baseSHA, err := lg.RevParse(org, repo, defaultBranch) 589 if err != nil { 590 t.Fatalf("failed to get baseSHA: %v", err) 591 } 592 headSHA, err := lg.RevParse(org, repo, "HEAD") 593 if err != nil { 594 t.Fatalf("failed to head headSHA: %v", err) 595 } 596 597 if tc.config == nil { 598 tc.config = &Config{ 599 ProwConfig: ProwConfig{ 600 InRepoConfig: InRepoConfig{ 601 AllowedClusters: map[string][]string{"*": {kube.DefaultClusterAlias}}, 602 }, 603 }, 604 } 605 } 606 // Validation fails when no NS is provided 607 tc.config.PodNamespace = "my-ns" 608 609 testGC := gc 610 if tc.dontPassGitClient { 611 testGC = nil 612 } 613 614 var p *ProwYAML 615 if headSHA == baseSHA { 616 p, err = prowYAMLGetterWithDefaults(tc.config, testGC, org+"/"+repo, "main", baseSHA) 617 } else { 618 p, err = prowYAMLGetterWithDefaults(tc.config, testGC, org+"/"+repo, "main", baseSHA, headSHA) 619 } 620 621 if err := tc.validate(p, err); err != nil { 622 t.Fatal(err) 623 } 624 625 // Empty base branch string shouldn't affect how we can fetch the configs. 626 if headSHA == baseSHA { 627 p, err = prowYAMLGetterWithDefaults(tc.config, testGC, org+"/"+repo, "", baseSHA) 628 } else { 629 p, err = prowYAMLGetterWithDefaults(tc.config, testGC, org+"/"+repo, "", baseSHA, headSHA) 630 } 631 632 if err := tc.validate(p, err); err != nil { 633 t.Fatal(err) 634 } 635 636 }) 637 } 638 } 639 640 func TestDefaultProwYAMLGetter_RejectsJustOrgV2(t *testing.T) { 641 testDefaultProwYAMLGetter_RejectsJustOrg(localgit.NewV2, t) 642 } 643 644 func testDefaultProwYAMLGetter_RejectsJustOrg(clients localgit.Clients, t *testing.T) { 645 lg, gc, err := clients() 646 if err != nil { 647 t.Fatalf("Making local git repo: %v", err) 648 } 649 defer func() { 650 if err := lg.Clean(); err != nil { 651 t.Errorf("Error cleaning LocalGit: %v", err) 652 } 653 if err := gc.Clean(); err != nil { 654 t.Errorf("Error cleaning Client: %v", err) 655 } 656 }() 657 658 identifier := "my-repo" 659 if err := lg.MakeFakeRepo(identifier, ""); err != nil { 660 t.Fatalf("Making fake repo: %v", err) 661 } 662 expectedErrMsg := `didn't get two results when splitting repo identifier "my-repo"` 663 if _, err := prowYAMLGetterWithDefaults(&Config{}, gc, identifier, "", ""); err == nil || err.Error() != expectedErrMsg { 664 t.Errorf("Error %v does not have expected message %s", err, expectedErrMsg) 665 } 666 } 667 668 type testClientFactory struct { 669 git.ClientFactory // This will be nil during testing, we override the functions that are used. 670 rcMap map[string]git.RepoClient 671 clientsCreated int 672 } 673 674 func (cf *testClientFactory) ClientFor(org, repo string) (git.RepoClient, error) { 675 cf.clientsCreated++ 676 // Returning this RepoClient ensures that only Fetch() is called and that Close() is not. 677 678 return &fetchOnlyNoCleanRepoClient{cf.rcMap[repo]}, nil 679 } 680 681 func (cf *testClientFactory) ClientForWithRepoOpts(org, repo string, repoOpts git.RepoOpts) (git.RepoClient, error) { 682 cf.clientsCreated++ 683 // Returning this RepoClient ensures that only Fetch() is called and that Close() is not. 684 685 return &fetchOnlyNoCleanRepoClient{cf.rcMap[repo]}, nil 686 } 687 688 type fetchOnlyNoCleanRepoClient struct { 689 git.RepoClient // This will be nil during testing, we override the functions that are allowed to be used. 690 } 691 692 func (rc *fetchOnlyNoCleanRepoClient) Fetch(arg ...string) error { 693 return nil 694 } 695 696 // Override Close to make sure when Close is called it would error out 697 func (rc *fetchOnlyNoCleanRepoClient) Close() error { 698 panic("This is not supposed to be called") 699 } 700 701 func TestInRepoConfigClean(t *testing.T) { 702 t.Parallel() 703 org, repo := "org", "repo" 704 705 lg, c, _ := localgit.NewV2() 706 rcMap := make(map[string]git.RepoClient) 707 if err := lg.MakeFakeRepo(org, repo); err != nil { 708 t.Fatal(err) 709 } 710 rc, err := c.ClientFor(org, repo) 711 if err != nil { 712 t.Fatal(err) 713 } 714 rcMap[repo] = rc 715 716 cf := &testClientFactory{ 717 rcMap: rcMap, 718 } 719 720 // First time clone should work 721 repoClient, err := cf.ClientFor(org, repo) 722 if err != nil { 723 t.Fatalf("Unexpected error getting repo client for thread 1: %v.", err) 724 } 725 726 // Now dirty the repo 727 dir := repoClient.Directory() 728 f := path.Join(dir, "new-file") 729 if err := os.WriteFile(f, []byte("something"), 0644); err != nil { 730 t.Fatal(err) 731 } 732 repoClient.Clean() 733 734 // Second time should be none dirty 735 repoClient, err = cf.ClientFor(org, repo) 736 if err != nil { 737 t.Fatalf("Unexpected error getting repo client for thread 1: %v.", err) 738 } 739 repoClient.Clean() 740 741 _, err = os.Stat(f) 742 if err == nil || !os.IsNotExist(err) { 743 t.Fatalf("%s should have been deleted", f) 744 } 745 }