github.com/redhat-appstudio/e2e-tests@v0.0.0-20240520140907-9709f6f59323/tests/build/build.go (about) 1 package build 2 3 import ( 4 "context" 5 "encoding/json" 6 "fmt" 7 "os" 8 "strings" 9 "time" 10 11 tektonutils "github.com/redhat-appstudio/release-service/tekton/utils" 12 "k8s.io/apimachinery/pkg/runtime" 13 14 pointer "k8s.io/utils/ptr" 15 16 "github.com/google/go-github/v44/github" 17 appservice "github.com/redhat-appstudio/application-api/api/v1alpha1" 18 "github.com/redhat-appstudio/e2e-tests/pkg/clients/has" 19 "github.com/redhat-appstudio/e2e-tests/pkg/utils/build" 20 "github.com/redhat-appstudio/e2e-tests/pkg/utils/tekton" 21 22 "github.com/devfile/library/v2/pkg/util" 23 "github.com/redhat-appstudio/e2e-tests/pkg/constants" 24 "github.com/redhat-appstudio/e2e-tests/pkg/utils" 25 pipeline "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1" 26 k8sErrors "k8s.io/apimachinery/pkg/api/errors" 27 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 28 29 imagecontollers "github.com/konflux-ci/image-controller/controllers" 30 . "github.com/onsi/ginkgo/v2" 31 . "github.com/onsi/gomega" 32 buildservice "github.com/redhat-appstudio/build-service/api/v1alpha1" 33 "github.com/redhat-appstudio/build-service/controllers" 34 "github.com/redhat-appstudio/e2e-tests/pkg/framework" 35 releasecommon "github.com/redhat-appstudio/e2e-tests/tests/release" 36 v1 "k8s.io/api/core/v1" 37 ) 38 39 var _ = framework.BuildSuiteDescribe("Build service E2E tests", Label("build", "HACBS"), func() { 40 41 var f *framework.Framework 42 AfterEach(framework.ReportFailure(&f)) 43 44 var err error 45 var osConsoleHost string 46 defer GinkgoRecover() 47 48 Describe("test PaC component build", Ordered, Label("github-webhook", "pac-build", "pipeline", "image-controller"), func() { 49 var applicationName, componentName, componentBaseBranchName, pacBranchName, testNamespace, defaultBranchTestComponentName, imageRepoName, robotAccountName string 50 var component *appservice.Component 51 52 var timeout, interval time.Duration 53 54 var prNumber int 55 var prHeadSha string 56 57 BeforeAll(func() { 58 if os.Getenv(constants.SKIP_PAC_TESTS_ENV) == "true" { 59 Skip("Skipping this test due to configuration issue with Spray proxy") 60 } 61 62 f, err = framework.NewFramework(utils.GetGeneratedNamespace("build-e2e")) 63 Expect(err).NotTo(HaveOccurred()) 64 testNamespace = f.UserNamespace 65 66 if utils.IsPrivateHostname(f.OpenshiftConsoleHost) { 67 Skip("Using private cluster (not reachable from Github), skipping...") 68 } 69 70 quayOrg := utils.GetEnv("DEFAULT_QUAY_ORG", "") 71 supports, err := build.DoesQuayOrgSupportPrivateRepo() 72 Expect(err).ShouldNot(HaveOccurred(), fmt.Sprintf("error while checking if quay org supports private repo: %+v", err)) 73 if !supports { 74 if quayOrg == "redhat-appstudio-qe" { 75 Fail("Failed to create private image repo in redhat-appstudio-qe org") 76 } else { 77 Skip("Quay org does not support private quay repository creation, please add support for private repo creation before running this test") 78 } 79 } 80 Expect(err).ShouldNot(HaveOccurred()) 81 82 applicationName = fmt.Sprintf("build-suite-test-application-%s", util.GenerateRandomString(4)) 83 _, err = f.AsKubeAdmin.HasController.CreateApplication(applicationName, testNamespace) 84 Expect(err).NotTo(HaveOccurred()) 85 86 componentName = fmt.Sprintf("%s-%s", "test-component-pac", util.GenerateRandomString(6)) 87 pacBranchName = constants.PaCPullRequestBranchPrefix + componentName 88 componentBaseBranchName = fmt.Sprintf("base-%s", util.GenerateRandomString(6)) 89 90 err = f.AsKubeAdmin.CommonController.Github.CreateRef(helloWorldComponentGitSourceRepoName, helloWorldComponentDefaultBranch, helloWorldComponentRevision, componentBaseBranchName) 91 Expect(err).ShouldNot(HaveOccurred()) 92 93 defaultBranchTestComponentName = fmt.Sprintf("test-custom-default-branch-%s", util.GenerateRandomString(6)) 94 }) 95 96 AfterAll(func() { 97 if !CurrentSpecReport().Failed() { 98 Expect(f.AsKubeAdmin.HasController.DeleteApplication(applicationName, testNamespace, false)).To(Succeed()) 99 Expect(f.SandboxController.DeleteUserSignup(f.UserName)).To(BeTrue()) 100 } 101 102 // Delete new branches created by PaC and a testing branch used as a component's base branch 103 err = f.AsKubeAdmin.CommonController.Github.DeleteRef(helloWorldComponentGitSourceRepoName, pacBranchName) 104 if err != nil { 105 Expect(err.Error()).To(ContainSubstring("Reference does not exist")) 106 } 107 err = f.AsKubeAdmin.CommonController.Github.DeleteRef(helloWorldComponentGitSourceRepoName, componentBaseBranchName) 108 if err != nil { 109 Expect(err.Error()).To(ContainSubstring("Reference does not exist")) 110 } 111 err = f.AsKubeAdmin.CommonController.Github.DeleteRef(helloWorldComponentGitSourceRepoName, constants.PaCPullRequestBranchPrefix+defaultBranchTestComponentName) 112 if err != nil { 113 Expect(err.Error()).To(ContainSubstring("Reference does not exist")) 114 } 115 116 // Delete created webhook from GitHub 117 cleanupWebhooks(f, helloWorldComponentGitSourceRepoName) 118 119 }) 120 121 validateChecks := func() { 122 var checkRun *github.CheckRun 123 timeout = time.Minute * 15 124 interval = time.Second * 10 125 126 Eventually(func() *github.CheckRun { 127 checkRuns, err := f.AsKubeAdmin.CommonController.Github.ListCheckRuns(helloWorldComponentGitSourceRepoName, prHeadSha) 128 Expect(err).ShouldNot(HaveOccurred()) 129 for _, cr := range checkRuns { 130 if strings.Contains(cr.GetDetailsURL(), osConsoleHost) { 131 checkRun = cr 132 return cr 133 } 134 } 135 return nil 136 }, timeout, interval).ShouldNot(BeNil(), fmt.Sprintf("timed out when waiting for the PaC Check run with `Details URL` field containing %s to appear in the Component repo %s in PR #%d", osConsoleHost, helloWorldComponentGitSourceRepoName, prNumber)) 137 138 Eventually(func() string { 139 checkRun, err = f.AsKubeAdmin.CommonController.Github.GetCheckRun(helloWorldComponentGitSourceRepoName, checkRun.GetID()) 140 Expect(err).ShouldNot(HaveOccurred()) 141 return checkRun.GetStatus() 142 }, timeout, interval).Should(Equal("completed"), fmt.Sprintf("timed out when waiting for the PaC Check suite status to be 'completed' in the Component repo %s in PR #%d", helloWorldComponentGitSourceRepoName, prNumber)) 143 Expect(checkRun.GetConclusion()).To(Equal("success"), fmt.Sprintf("the initial PR %d in %s repo doesn't contain the info about successful pipelinerun", prNumber, helloWorldComponentGitSourceRepoName)) 144 } 145 146 When("a new component without specified branch is created and with visibility private", Label("pac-custom-default-branch"), func() { 147 BeforeAll(func() { 148 componentObj := appservice.ComponentSpec{ 149 ComponentName: defaultBranchTestComponentName, 150 Application: applicationName, 151 Source: appservice.ComponentSource{ 152 ComponentSourceUnion: appservice.ComponentSourceUnion{ 153 GitSource: &appservice.GitSource{ 154 URL: helloWorldComponentGitSourceURL, 155 Revision: "", 156 }, 157 }, 158 }, 159 } 160 _, err = f.AsKubeAdmin.HasController.CreateComponent(componentObj, testNamespace, "", "", applicationName, false, utils.MergeMaps(constants.ComponentPaCRequestAnnotation, constants.ImageControllerAnnotationRequestPrivateRepo)) 161 Expect(err).ShouldNot(HaveOccurred()) 162 }) 163 164 It("correctly targets the default branch (that is not named 'main') with PaC", func() { 165 timeout = time.Second * 300 166 interval = time.Second * 1 167 Eventually(func() bool { 168 prs, err := f.AsKubeAdmin.CommonController.Github.ListPullRequests(helloWorldComponentGitSourceRepoName) 169 Expect(err).ShouldNot(HaveOccurred()) 170 171 for _, pr := range prs { 172 if pr.Head.GetRef() == constants.PaCPullRequestBranchPrefix+defaultBranchTestComponentName { 173 Expect(pr.GetBase().GetRef()).To(Equal(helloWorldComponentDefaultBranch)) 174 return true 175 } 176 } 177 return false 178 }, timeout, interval).Should(BeTrue(), fmt.Sprintf("timed out when waiting for init PaC PR to be created against %s branch in %s repository", helloWorldComponentDefaultBranch, helloWorldComponentGitSourceRepoName)) 179 }) 180 It("workspace parameter is set correctly in PaC repository CR", func() { 181 nsObj, err := f.AsKubeAdmin.CommonController.GetNamespace(testNamespace) 182 Expect(err).ShouldNot(HaveOccurred()) 183 wsName := nsObj.Labels["appstudio.redhat.com/workspace_name"] 184 repositoryParams, err := f.AsKubeAdmin.TektonController.GetRepositoryParams(defaultBranchTestComponentName, testNamespace) 185 Expect(err).ShouldNot(HaveOccurred(), "error while trying to get repository params") 186 paramExists := false 187 for _, param := range repositoryParams { 188 if param.Name == "appstudio_workspace" { 189 paramExists = true 190 Expect(param.Value).To(Equal(wsName), fmt.Sprintf("got workspace param value: %s, expected %s", param.Value, wsName)) 191 } 192 } 193 Expect(paramExists).To(BeTrue(), "appstudio_workspace param does not exists in repository CR") 194 195 }) 196 It("triggers a PipelineRun", func() { 197 timeout = time.Minute * 5 198 Eventually(func() error { 199 pr, err := f.AsKubeAdmin.HasController.GetComponentPipelineRun(defaultBranchTestComponentName, applicationName, testNamespace, "") 200 if err != nil { 201 GinkgoWriter.Printf("PipelineRun has not been created yet for the component %s/%s\n", testNamespace, defaultBranchTestComponentName) 202 return err 203 } 204 if !pr.HasStarted() { 205 return fmt.Errorf("pipelinerun %s/%s hasn't started yet", pr.GetNamespace(), pr.GetName()) 206 } 207 return nil 208 }, timeout, constants.PipelineRunPollingInterval).Should(Succeed(), fmt.Sprintf("timed out when waiting for the PipelineRun to start for the component %s/%s", defaultBranchTestComponentName, testNamespace)) 209 }) 210 It("component build status is set correctly", func() { 211 var buildStatus *controllers.BuildStatus 212 Eventually(func() (bool, error) { 213 component, err := f.AsKubeAdmin.HasController.GetComponent(defaultBranchTestComponentName, testNamespace) 214 if err != nil { 215 return false, err 216 } 217 218 buildStatusAnnotationValue := component.Annotations[controllers.BuildStatusAnnotationName] 219 GinkgoWriter.Printf(buildStatusAnnotationValueLoggingFormat, buildStatusAnnotationValue) 220 statusBytes := []byte(buildStatusAnnotationValue) 221 222 err = json.Unmarshal(statusBytes, &buildStatus) 223 if err != nil { 224 return false, err 225 } 226 227 if buildStatus.PaC != nil { 228 GinkgoWriter.Printf("state: %s\n", buildStatus.PaC.State) 229 GinkgoWriter.Printf("mergeUrl: %s\n", buildStatus.PaC.MergeUrl) 230 GinkgoWriter.Printf("errId: %d\n", buildStatus.PaC.ErrId) 231 GinkgoWriter.Printf("errMessage: %s\n", buildStatus.PaC.ErrMessage) 232 GinkgoWriter.Printf("configurationTime: %s\n", buildStatus.PaC.ConfigurationTime) 233 } else { 234 GinkgoWriter.Println("build status does not have PaC field") 235 } 236 237 return buildStatus.PaC != nil && buildStatus.PaC.State == "enabled" && buildStatus.PaC.MergeUrl != "" && buildStatus.PaC.ErrId == 0 && buildStatus.PaC.ConfigurationTime != "", nil 238 }, timeout, interval).Should(BeTrue(), "component build status has unexpected content") 239 }) 240 It("image repo and robot account created successfully", func() { 241 component, err := f.AsKubeAdmin.HasController.GetComponent(defaultBranchTestComponentName, testNamespace) 242 Expect(err).ShouldNot(HaveOccurred(), "could not get component %s in the %s namespace", defaultBranchTestComponentName, testNamespace) 243 244 annotations := component.GetAnnotations() 245 imageRepoName, err = build.GetQuayImageName(annotations) 246 Expect(err).ShouldNot(HaveOccurred(), "failed to read image repo name from %+v", annotations) 247 248 imageExist, err := build.DoesImageRepoExistInQuay(imageRepoName) 249 Expect(err).ShouldNot(HaveOccurred(), "failed while checking if image repo exists in quay with error: %+v", err) 250 Expect(imageExist).To(BeTrue(), "quay image does not exists") 251 252 robotAccountName = build.GetRobotAccountName(imageRepoName) 253 robotAccountExist, err := build.DoesRobotAccountExistInQuay(robotAccountName) 254 Expect(err).ShouldNot(HaveOccurred(), "failed while checking if robot account exists in quay with error: %+v", err) 255 Expect(robotAccountExist).To(BeTrue(), "quay robot account does not exists") 256 }) 257 It("created image repo is private", func() { 258 isPublic, err := build.IsImageRepoPublic(imageRepoName) 259 Expect(err).ShouldNot(HaveOccurred(), fmt.Sprintf("failed while checking if the image repo %s is private", imageRepoName)) 260 Expect(isPublic).To(BeFalse(), "Expected image repo to be private, but it is public") 261 }) 262 // skipped due to RHTAPBUGS-978 263 It("a related PipelineRun should be deleted after deleting the component", Pending, func() { 264 timeout = time.Second * 60 265 interval = time.Second * 1 266 Expect(f.AsKubeAdmin.HasController.DeleteComponent(defaultBranchTestComponentName, testNamespace, true)).To(Succeed()) 267 // Test removal of PipelineRun 268 var pr *pipeline.PipelineRun 269 Eventually(func() error { 270 pr, err = f.AsKubeAdmin.HasController.GetComponentPipelineRun(defaultBranchTestComponentName, applicationName, testNamespace, "") 271 if err == nil { 272 return fmt.Errorf("pipelinerun %s/%s is not removed yet", pr.GetNamespace(), pr.GetName()) 273 } 274 return err 275 }, timeout, constants.PipelineRunPollingInterval).Should(MatchError(ContainSubstring("no pipelinerun found")), fmt.Sprintf("timed out when waiting for the PipelineRun to be removed for Component %s/%s", testNamespace, defaultBranchTestComponentName)) 276 }) 277 // skipped due to RHTAPBUGS-978 278 It("PR branch should not exist in the repo", Pending, func() { 279 timeout = time.Second * 60 280 interval = time.Second * 1 281 branchName := constants.PaCPullRequestBranchPrefix + defaultBranchTestComponentName 282 Eventually(func() bool { 283 exists, err := f.AsKubeAdmin.CommonController.Github.ExistsRef(helloWorldComponentGitSourceRepoName, constants.PaCPullRequestBranchPrefix+defaultBranchTestComponentName) 284 Expect(err).ShouldNot(HaveOccurred()) 285 return exists 286 }, timeout, interval).Should(BeFalse(), fmt.Sprintf("timed out when waiting for the branch %s to be deleted from %s repository", branchName, helloWorldComponentGitSourceRepoName)) 287 }) 288 // skipped due to RHTAPBUGS-978 289 It("related image repo and the robot account should be deleted after deleting the component", Pending, func() { 290 timeout = time.Second * 10 291 interval = time.Second * 1 292 // Check image repo should not be deleted 293 Consistently(func() (bool, error) { 294 return build.DoesImageRepoExistInQuay(imageRepoName) 295 }, timeout, interval).Should(BeFalse(), fmt.Sprintf("image repo %s got deleted while it should not have", imageRepoName)) 296 // Check robot account should be deleted 297 timeout = time.Second * 60 298 Eventually(func() (bool, error) { 299 return build.DoesRobotAccountExistInQuay(robotAccountName) 300 }, timeout, interval).Should(BeFalse(), fmt.Sprintf("timed out when checking if robot account %s got deleted", robotAccountName)) 301 302 }) 303 }) 304 305 When("a new Component with specified custom branch is created", Label("build-custom-branch"), func() { 306 var outputImage string 307 BeforeAll(func() { 308 309 // create the build secret in the user namespace 310 secretName := "build-secret" 311 token := os.Getenv("GITHUB_TOKEN") 312 secretAnnotations := map[string]string{ 313 "appstudio.redhat.com/scm.repository": os.Getenv("MY_GITHUB_ORG") + "/*", 314 } 315 err = createBuildSecret(f, secretName, secretAnnotations, token) 316 Expect(err).ShouldNot(HaveOccurred()) 317 318 componentObj := appservice.ComponentSpec{ 319 ComponentName: componentName, 320 Application: applicationName, 321 Source: appservice.ComponentSource{ 322 ComponentSourceUnion: appservice.ComponentSourceUnion{ 323 GitSource: &appservice.GitSource{ 324 URL: helloWorldComponentGitSourceURL, 325 Revision: componentBaseBranchName, 326 }, 327 }, 328 }, 329 } 330 // Create a component with Git Source URL, a specified git branch and marking delete-repo=true 331 component, err = f.AsKubeAdmin.HasController.CreateComponent(componentObj, testNamespace, "", "", applicationName, false, utils.MergeMaps(constants.ComponentPaCRequestAnnotation, constants.ImageControllerAnnotationRequestPublicRepo)) 332 Expect(err).ShouldNot(HaveOccurred()) 333 }) 334 It("triggers a PipelineRun", func() { 335 timeout = time.Second * 600 336 interval = time.Second * 1 337 Eventually(func() error { 338 pr, err := f.AsKubeAdmin.HasController.GetComponentPipelineRun(componentName, applicationName, testNamespace, "") 339 if err != nil { 340 GinkgoWriter.Printf("PipelineRun has not been created yet for the component %s/%s\n", testNamespace, componentName) 341 return err 342 } 343 if !pr.HasStarted() { 344 return fmt.Errorf("pipelinerun %s/%s hasn't started yet", pr.GetNamespace(), pr.GetName()) 345 } 346 return nil 347 }, timeout, constants.PipelineRunPollingInterval).Should(Succeed(), fmt.Sprintf("timed out when waiting for the PipelineRun to start for the component %s/%s", testNamespace, componentName)) 348 }) 349 It("should lead to a PaC init PR creation", func() { 350 timeout = time.Second * 300 351 interval = time.Second * 1 352 353 Eventually(func() bool { 354 prs, err := f.AsKubeAdmin.CommonController.Github.ListPullRequests(helloWorldComponentGitSourceRepoName) 355 Expect(err).ShouldNot(HaveOccurred()) 356 357 for _, pr := range prs { 358 if pr.Head.GetRef() == pacBranchName { 359 prNumber = pr.GetNumber() 360 prHeadSha = pr.Head.GetSHA() 361 return true 362 } 363 } 364 return false 365 }, timeout, interval).Should(BeTrue(), fmt.Sprintf("timed out when waiting for init PaC PR (branch name '%s') to be created in %s repository", pacBranchName, helloWorldComponentGitSourceRepoName)) 366 }) 367 It("the PipelineRun should eventually finish successfully", func() { 368 Expect(f.AsKubeAdmin.HasController.WaitForComponentPipelineToBeFinished(component, "", 369 f.AsKubeAdmin.TektonController, &has.RetryOptions{Retries: 2, Always: true}, nil)).To(Succeed()) 370 }) 371 It("image repo and robot account created successfully", func() { 372 373 component, err := f.AsKubeAdmin.HasController.GetComponent(componentName, testNamespace) 374 Expect(err).ShouldNot(HaveOccurred(), fmt.Sprintf("could not get component %s in the %s namespace", componentName, testNamespace)) 375 376 annotations := component.GetAnnotations() 377 imageRepoName, err = build.GetQuayImageName(annotations) 378 Expect(err).ShouldNot(HaveOccurred(), fmt.Sprintf("failed to read image repo name from %+v", annotations)) 379 380 imageExist, err := build.DoesImageRepoExistInQuay(imageRepoName) 381 Expect(err).ShouldNot(HaveOccurred(), fmt.Sprintf("failed while checking if image repo exists in quay with error: %+v", err)) 382 Expect(imageExist).To(BeTrue(), fmt.Sprintf("quay image for repo %s does not exists", imageRepoName)) 383 384 robotAccountName = build.GetRobotAccountName(imageRepoName) 385 robotAccountExist, err := build.DoesRobotAccountExistInQuay(robotAccountName) 386 Expect(err).ShouldNot(HaveOccurred(), fmt.Sprintf("failed while checking if robot account exists in quay with error: %+v", err)) 387 Expect(robotAccountExist).To(BeTrue(), fmt.Sprintf("quay robot account %s does not exists", robotAccountName)) 388 389 }) 390 It("created image repo is public", func() { 391 isPublic, err := build.IsImageRepoPublic(imageRepoName) 392 Expect(err).ShouldNot(HaveOccurred(), fmt.Sprintf("failed while checking if the image repo %s is public", imageRepoName)) 393 Expect(isPublic).To(BeTrue(), "Expected image repo to changed to public, but it is private") 394 }) 395 It("image tag is updated successfully", func() { 396 // check if the image tag exists in quay 397 pipelineRun, err := f.AsKubeAdmin.HasController.GetComponentPipelineRun(componentName, applicationName, testNamespace, "") 398 Expect(err).ShouldNot(HaveOccurred()) 399 400 for _, p := range pipelineRun.Spec.Params { 401 if p.Name == "output-image" { 402 outputImage = p.Value.StringVal 403 } 404 } 405 Expect(outputImage).ToNot(BeEmpty(), "output image %s of the component could not be found", outputImage) 406 isExists, err := build.DoesTagExistsInQuay(outputImage) 407 Expect(err).ShouldNot(HaveOccurred(), "error while checking if the output image %s exists in quay", outputImage) 408 Expect(isExists).To(BeTrue(), "image tag does not exists in quay") 409 }) 410 411 It("should ensure pruning labels are set", func() { 412 pipelineRun, err := f.AsKubeAdmin.HasController.GetComponentPipelineRun(componentName, applicationName, testNamespace, "") 413 Expect(err).ShouldNot(HaveOccurred()) 414 415 image, err := build.ImageFromPipelineRun(pipelineRun) 416 Expect(err).ShouldNot(HaveOccurred()) 417 418 labels := image.Config.Config.Labels 419 Expect(labels).ToNot(BeEmpty()) 420 421 expiration, ok := labels["quay.expires-after"] 422 Expect(ok).To(BeTrue()) 423 Expect(expiration).To(Equal(utils.GetEnv(constants.IMAGE_TAG_EXPIRATION_ENV, constants.DefaultImageTagExpiration))) 424 }) 425 It("eventually leads to the PipelineRun status report at Checks tab", func() { 426 validateChecks() 427 }) 428 }) 429 430 When("the PaC init branch is updated", Label("build-custom-branch"), func() { 431 var createdFileSHA string 432 433 BeforeAll(func() { 434 fileToCreatePath := fmt.Sprintf(".tekton/%s-readme.md", componentName) 435 createdFile, err := f.AsKubeAdmin.CommonController.Github.CreateFile(helloWorldComponentGitSourceRepoName, fileToCreatePath, fmt.Sprintf("test PaC branch %s update", pacBranchName), pacBranchName) 436 Expect(err).NotTo(HaveOccurred()) 437 438 createdFileSHA = createdFile.GetSHA() 439 GinkgoWriter.Println("created file sha:", createdFileSHA) 440 }) 441 442 It("eventually leads to triggering another PipelineRun", func() { 443 timeout = time.Minute * 5 444 445 Eventually(func() error { 446 pr, err := f.AsKubeAdmin.HasController.GetComponentPipelineRun(componentName, applicationName, testNamespace, createdFileSHA) 447 if err != nil { 448 GinkgoWriter.Printf("PipelineRun has not been created yet for the component %s/%s\n", testNamespace, componentName) 449 return err 450 } 451 if !pr.HasStarted() { 452 return fmt.Errorf("pipelinerun %s/%s hasn't started yet", pr.GetNamespace(), pr.GetName()) 453 } 454 return nil 455 }, timeout, constants.PipelineRunPollingInterval).Should(Succeed(), fmt.Sprintf("timed out when waiting for the PipelineRun to start for the component %s/%s", testNamespace, componentName)) 456 }) 457 It("should lead to a PaC init PR update", func() { 458 timeout = time.Second * 300 459 interval = time.Second * 1 460 461 Eventually(func() bool { 462 prs, err := f.AsKubeAdmin.CommonController.Github.ListPullRequests(helloWorldComponentGitSourceRepoName) 463 Expect(err).ShouldNot(HaveOccurred()) 464 465 for _, pr := range prs { 466 if pr.Head.GetRef() == pacBranchName { 467 Expect(prHeadSha).NotTo(Equal(pr.Head.GetSHA())) 468 prNumber = pr.GetNumber() 469 prHeadSha = pr.Head.GetSHA() 470 return true 471 } 472 } 473 return false 474 }, timeout, interval).Should(BeTrue(), fmt.Sprintf("timed out when waiting for init PaC PR (branch name '%s') to be created in %s repository", pacBranchName, helloWorldComponentGitSourceRepoName)) 475 }) 476 It("PipelineRun should eventually finish", func() { 477 pr := &pipeline.PipelineRun{} 478 Expect(f.AsKubeAdmin.HasController.WaitForComponentPipelineToBeFinished(component, createdFileSHA, 479 f.AsKubeAdmin.TektonController, &has.RetryOptions{Retries: 2, Always: true}, pr)).To(Succeed()) 480 createdFileSHA = pr.Labels["pipelinesascode.tekton.dev/sha"] 481 }) 482 It("eventually leads to another update of a PR about the PipelineRun status report at Checks tab", func() { 483 validateChecks() 484 }) 485 }) 486 487 When("the PaC init branch is merged", Label("build-custom-branch"), func() { 488 var mergeResult *github.PullRequestMergeResult 489 var mergeResultSha string 490 var pipelineRun *pipeline.PipelineRun 491 492 BeforeAll(func() { 493 Eventually(func() error { 494 mergeResult, err = f.AsKubeAdmin.CommonController.Github.MergePullRequest(helloWorldComponentGitSourceRepoName, prNumber) 495 return err 496 }, time.Minute).Should(BeNil(), fmt.Sprintf("error when merging PaC pull request #%d in repo %s", prNumber, helloWorldComponentGitSourceRepoName)) 497 498 mergeResultSha = mergeResult.GetSHA() 499 GinkgoWriter.Println("merged result sha:", mergeResultSha) 500 }) 501 502 It("eventually leads to triggering another PipelineRun", func() { 503 timeout = time.Minute * 10 504 505 Eventually(func() error { 506 pipelineRun, err = f.AsKubeAdmin.HasController.GetComponentPipelineRun(componentName, applicationName, testNamespace, mergeResultSha) 507 if err != nil { 508 GinkgoWriter.Printf("PipelineRun has not been created yet for the component %s/%s\n", testNamespace, componentName) 509 return err 510 } 511 if !pipelineRun.HasStarted() { 512 return fmt.Errorf("pipelinerun %s/%s hasn't started yet", pipelineRun.GetNamespace(), pipelineRun.GetName()) 513 } 514 return nil 515 }, timeout, constants.PipelineRunPollingInterval).Should(Succeed(), fmt.Sprintf("timed out when waiting for the PipelineRun to start for the component %s/%s", testNamespace, componentName)) 516 }) 517 518 It("pipelineRun should eventually finish", func() { 519 Expect(f.AsKubeAdmin.HasController.WaitForComponentPipelineToBeFinished(component, 520 mergeResultSha, f.AsKubeAdmin.TektonController, &has.RetryOptions{Retries: 2, Always: true}, pipelineRun)).To(Succeed()) 521 mergeResultSha = pipelineRun.Labels["pipelinesascode.tekton.dev/sha"] 522 }) 523 524 It("does not have expiration set", func() { 525 image, err := build.ImageFromPipelineRun(pipelineRun) 526 Expect(err).ShouldNot(HaveOccurred()) 527 528 labels := image.Config.Config.Labels 529 Expect(labels).ToNot(BeEmpty()) 530 531 expiration, ok := labels["quay.expires-after"] 532 Expect(ok).To(BeFalse()) 533 Expect(expiration).To(BeEmpty()) 534 }) 535 536 It("After updating image visibility to private, it should not trigger another PipelineRun", func() { 537 Expect(f.AsKubeAdmin.TektonController.DeleteAllPipelineRunsInASpecificNamespace(testNamespace)).To(Succeed()) 538 Eventually(func() error { 539 err := f.AsKubeAdmin.HasController.SetComponentAnnotation(componentName, controllers.ImageRepoGenerateAnnotationName, constants.ImageControllerAnnotationRequestPrivateRepo[controllers.ImageRepoGenerateAnnotationName], testNamespace) 540 if err != nil { 541 GinkgoWriter.Printf("failed to update the component %s with error %v\n", componentName, err) 542 return err 543 } 544 return nil 545 }, time.Second*20, time.Second*1).Should(Succeed(), fmt.Sprintf("timed out when trying to update the component %s/%s", testNamespace, componentName)) 546 547 Consistently(func() bool { 548 componentPipelineRun, _ := f.AsKubeAdmin.HasController.GetComponentPipelineRun(componentName, applicationName, testNamespace, "") 549 return componentPipelineRun == nil 550 }, time.Minute, constants.PipelineRunPollingInterval).Should(BeTrue(), fmt.Sprintf("expected no PipelineRun to be triggered for the component %s in %s namespace", componentName, testNamespace)) 551 }) 552 It("check image repo status after switching to private", func() { 553 var imageStatus imagecontollers.ImageRepositoryStatus 554 Eventually(func() (bool, error) { 555 component, err := f.AsKubeAdmin.HasController.GetComponent(componentName, testNamespace) 556 if err != nil { 557 GinkgoWriter.Printf("error while getting component: %v\n", err) 558 return false, err 559 } 560 561 imageAnnotationValue := component.Annotations[controllers.ImageRepoAnnotationName] 562 GinkgoWriter.Printf("image annotation value: %s\n", imageAnnotationValue) 563 statusBytes := []byte(imageAnnotationValue) 564 565 err = json.Unmarshal(statusBytes, &imageStatus) 566 if err != nil { 567 GinkgoWriter.Printf("cannot unmarshal image status: %v\n", err) 568 return false, err 569 } 570 if imageStatus.Message != "" && strings.Contains(imageStatus.Message, "Quay organization plan doesn't allow private image repositories") { 571 return false, fmt.Errorf("failed to switch to private image") 572 } 573 return true, nil 574 }, time.Second*20, time.Second*2).Should(BeTrue(), "component image status annotation has unexpected content") 575 }) 576 It("image repo is updated to private", func() { 577 isPublic, err := build.IsImageRepoPublic(imageRepoName) 578 Expect(err).ShouldNot(HaveOccurred(), fmt.Sprintf("failed while checking if the image repo %s is private", imageRepoName)) 579 Expect(isPublic).To(BeFalse(), "Expected image repo to changed to private, but it is public") 580 }) 581 582 }) 583 584 When("the component is removed and recreated (with the same name in the same namespace)", Label("build-custom-branch"), func() { 585 BeforeAll(func() { 586 Expect(f.AsKubeAdmin.HasController.DeleteComponent(componentName, testNamespace, true)).To(Succeed()) 587 588 timeout = 1 * time.Minute 589 interval = 1 * time.Second 590 Eventually(func() bool { 591 _, err := f.AsKubeAdmin.HasController.GetComponent(componentName, testNamespace) 592 return k8sErrors.IsNotFound(err) 593 }, timeout, interval).Should(BeTrue(), fmt.Sprintf("timed out when waiting for the app %s/%s to be deleted", testNamespace, applicationName)) 594 // Check removal of image repo 595 Eventually(func() (bool, error) { 596 return build.DoesImageRepoExistInQuay(imageRepoName) 597 }, timeout, interval).Should(BeFalse(), fmt.Sprintf("timed out when waiting for image repo %s to be deleted", imageRepoName)) 598 // Check removal of robot account 599 Eventually(func() (bool, error) { 600 return build.DoesRobotAccountExistInQuay(robotAccountName) 601 }, timeout, interval).Should(BeFalse(), fmt.Sprintf("timed out when waiting for robot account %s to be deleted", robotAccountName)) 602 603 componentObj := appservice.ComponentSpec{ 604 ComponentName: componentName, 605 Source: appservice.ComponentSource{ 606 ComponentSourceUnion: appservice.ComponentSourceUnion{ 607 GitSource: &appservice.GitSource{ 608 URL: helloWorldComponentGitSourceURL, 609 Revision: componentBaseBranchName, 610 }, 611 }, 612 }, 613 } 614 _, err = f.AsKubeAdmin.HasController.CreateComponent(componentObj, testNamespace, "", "", applicationName, false, utils.MergeMaps(constants.ComponentPaCRequestAnnotation, constants.ImageControllerAnnotationRequestPublicRepo)) 615 Expect(err).ShouldNot(HaveOccurred()) 616 }) 617 618 It("should no longer lead to a creation of a PaC PR", func() { 619 timeout = time.Second * 10 620 interval = time.Second * 2 621 Consistently(func() error { 622 prs, err := f.AsKubeAdmin.CommonController.Github.ListPullRequests(helloWorldComponentGitSourceRepoName) 623 Expect(err).ShouldNot(HaveOccurred()) 624 625 for _, pr := range prs { 626 if pr.Head.GetRef() == pacBranchName { 627 return fmt.Errorf("did not expect a new PR created in %s repository after initial PaC configuration was already merged for the same component name and a namespace", helloWorldComponentGitSourceRepoName) 628 } 629 } 630 return nil 631 }, timeout, interval).Should(BeNil()) 632 }) 633 }) 634 }) 635 636 Describe("test pac with multiple components using same repository", Ordered, Label("pac-build", "multi-component"), func() { 637 var applicationName, testNamespace, multiComponentBaseBranchName, multiComponentPRBranchName, mergeResultSha string 638 var pacBranchNames []string 639 var prNumber int 640 var mergeResult *github.PullRequestMergeResult 641 var timeout time.Duration 642 643 BeforeAll(func() { 644 if os.Getenv(constants.SKIP_PAC_TESTS_ENV) == "true" { 645 Skip("Skipping this test due to configuration issue with Spray proxy") 646 } 647 f, err = framework.NewFramework(utils.GetGeneratedNamespace("build-e2e")) 648 Expect(err).NotTo(HaveOccurred()) 649 testNamespace = f.UserNamespace 650 651 if utils.IsPrivateHostname(f.OpenshiftConsoleHost) { 652 Skip("Using private cluster (not reachable from Github), skipping...") 653 } 654 655 applicationName = fmt.Sprintf("build-suite-positive-mc-%s", util.GenerateRandomString(4)) 656 _, err = f.AsKubeAdmin.HasController.CreateApplication(applicationName, testNamespace) 657 Expect(err).NotTo(HaveOccurred()) 658 659 multiComponentBaseBranchName = fmt.Sprintf("multi-component-base-%s", util.GenerateRandomString(6)) 660 err = f.AsKubeAdmin.CommonController.Github.CreateRef(multiComponentGitSourceRepoName, multiComponentDefaultBranch, multiComponentGitRevision, multiComponentBaseBranchName) 661 Expect(err).ShouldNot(HaveOccurred()) 662 663 //Branch for creating pull request 664 multiComponentPRBranchName = fmt.Sprintf("%s-%s", "pr-branch", util.GenerateRandomString(6)) 665 666 }) 667 668 AfterAll(func() { 669 if !CurrentSpecReport().Failed() { 670 Expect(f.AsKubeAdmin.HasController.DeleteApplication(applicationName, testNamespace, false)).To(Succeed()) 671 Expect(f.SandboxController.DeleteUserSignup(f.UserName)).To(BeTrue()) 672 } 673 674 // Delete new branches created by PaC and a testing branch used as a component's base branch 675 for _, pacBranchName := range pacBranchNames { 676 err = f.AsKubeAdmin.CommonController.Github.DeleteRef(multiComponentGitSourceRepoName, pacBranchName) 677 if err != nil { 678 Expect(err.Error()).To(ContainSubstring("Reference does not exist")) 679 } 680 } 681 // Delete the created base branch 682 err = f.AsKubeAdmin.CommonController.Github.DeleteRef(multiComponentGitSourceRepoName, multiComponentBaseBranchName) 683 if err != nil { 684 Expect(err.Error()).To(ContainSubstring("Reference does not exist")) 685 } 686 // Delete the created pr branch 687 err = f.AsKubeAdmin.CommonController.Github.DeleteRef(multiComponentGitSourceRepoName, multiComponentPRBranchName) 688 if err != nil { 689 Expect(err.Error()).To(ContainSubstring("Reference does not exist")) 690 } 691 }) 692 693 When("components are created in same namespace", func() { 694 var component *appservice.Component 695 696 for _, contextDir := range multiComponentContextDirs { 697 contextDir := contextDir 698 componentName := fmt.Sprintf("%s-%s", contextDir, util.GenerateRandomString(6)) 699 pacBranchName := constants.PaCPullRequestBranchPrefix + componentName 700 pacBranchNames = append(pacBranchNames, pacBranchName) 701 702 It(fmt.Sprintf("creates component with context directory %s", contextDir), func() { 703 componentObj := appservice.ComponentSpec{ 704 ComponentName: componentName, 705 Application: applicationName, 706 Source: appservice.ComponentSource{ 707 ComponentSourceUnion: appservice.ComponentSourceUnion{ 708 GitSource: &appservice.GitSource{ 709 URL: multiComponentGitSourceURL, 710 Revision: multiComponentBaseBranchName, 711 Context: contextDir, 712 }, 713 }, 714 }, 715 } 716 component, err = f.AsKubeAdmin.HasController.CreateComponent(componentObj, testNamespace, "", "", applicationName, false, utils.MergeMaps(constants.ComponentPaCRequestAnnotation, constants.ImageControllerAnnotationRequestPublicRepo)) 717 Expect(err).ShouldNot(HaveOccurred()) 718 }) 719 720 It(fmt.Sprintf("triggers a PipelineRun for component %s", componentName), func() { 721 timeout = time.Minute * 5 722 Eventually(func() error { 723 pr, err := f.AsKubeAdmin.HasController.GetComponentPipelineRun(componentName, applicationName, testNamespace, "") 724 if err != nil { 725 GinkgoWriter.Printf("PipelineRun has not been created yet for the component %s/%s\n", testNamespace, componentName) 726 return err 727 } 728 if !pr.HasStarted() { 729 return fmt.Errorf("pipelinerun %s/%s hasn't started yet", pr.GetNamespace(), pr.GetName()) 730 } 731 return nil 732 }, timeout, constants.PipelineRunPollingInterval).Should(Succeed(), fmt.Sprintf("timed out when waiting for the PipelineRun to start for the component %s/%s", componentName, testNamespace)) 733 }) 734 735 It(fmt.Sprintf("should lead to a PaC PR creation for component %s", componentName), func() { 736 timeout = time.Second * 300 737 interval := time.Second * 1 738 739 Eventually(func() bool { 740 prs, err := f.AsKubeAdmin.CommonController.Github.ListPullRequests(multiComponentGitSourceRepoName) 741 Expect(err).ShouldNot(HaveOccurred()) 742 743 for _, pr := range prs { 744 if pr.Head.GetRef() == pacBranchName { 745 prNumber = pr.GetNumber() 746 return true 747 } 748 } 749 return false 750 }, timeout, interval).Should(BeTrue(), fmt.Sprintf("timed out when waiting for PaC PR (branch name '%s') to be created in %s repository", pacBranchName, multiComponentGitSourceRepoName)) 751 }) 752 753 It(fmt.Sprintf("the PipelineRun should eventually finish successfully for component %s", componentName), func() { 754 Expect(f.AsKubeAdmin.HasController.WaitForComponentPipelineToBeFinished(component, "", 755 f.AsKubeAdmin.TektonController, &has.RetryOptions{Retries: 2, Always: true}, nil)).To(Succeed()) 756 }) 757 758 It("merging the PR should be successful", func() { 759 Eventually(func() error { 760 mergeResult, err = f.AsKubeAdmin.CommonController.Github.MergePullRequest(multiComponentGitSourceRepoName, prNumber) 761 return err 762 }, time.Minute).Should(BeNil(), fmt.Sprintf("error when merging PaC pull request #%d in repo %s", prNumber, multiComponentGitSourceRepoName)) 763 764 mergeResultSha = mergeResult.GetSHA() 765 GinkgoWriter.Printf("merged result sha: %s for PR #%d\n", mergeResultSha, prNumber) 766 767 }) 768 It("leads to triggering on push PipelineRun", func() { 769 timeout = time.Minute * 5 770 771 Eventually(func() error { 772 pipelineRun, err := f.AsKubeAdmin.HasController.GetComponentPipelineRun(componentName, applicationName, testNamespace, mergeResultSha) 773 if err != nil { 774 GinkgoWriter.Printf("Push PipelineRun has not been created yet for the component %s/%s\n", testNamespace, componentName) 775 return err 776 } 777 if !pipelineRun.HasStarted() { 778 return fmt.Errorf("push pipelinerun %s/%s hasn't started yet", pipelineRun.GetNamespace(), pipelineRun.GetName()) 779 } 780 return nil 781 }, timeout, constants.PipelineRunPollingInterval).Should(Succeed(), fmt.Sprintf("timed out when waiting for the PipelineRun to start for the component %s/%s", testNamespace, componentName)) 782 }) 783 } 784 It("only one component is changed", func() { 785 //Delete all the pipelineruns in the namespace before sending PR 786 Expect(f.AsKubeAdmin.TektonController.DeleteAllPipelineRunsInASpecificNamespace(testNamespace)).To(Succeed()) 787 //Create the ref, add the file and create the PR 788 err = f.AsKubeAdmin.CommonController.Github.CreateRef(multiComponentGitSourceRepoName, multiComponentDefaultBranch, mergeResultSha, multiComponentPRBranchName) 789 Expect(err).ShouldNot(HaveOccurred()) 790 fileToCreatePath := fmt.Sprintf("%s/sample-file.txt", multiComponentContextDirs[0]) 791 createdFileSha, err := f.AsKubeAdmin.CommonController.Github.CreateFile(multiComponentGitSourceRepoName, fileToCreatePath, fmt.Sprintf("sample test file inside %s", multiComponentContextDirs[0]), multiComponentPRBranchName) 792 Expect(err).ShouldNot(HaveOccurred(), fmt.Sprintf("error while creating file: %s", fileToCreatePath)) 793 pr, err := f.AsKubeAdmin.CommonController.Github.CreatePullRequest(multiComponentGitSourceRepoName, "sample pr title", "sample pr body", multiComponentPRBranchName, multiComponentBaseBranchName) 794 Expect(err).ShouldNot(HaveOccurred()) 795 GinkgoWriter.Printf("PR #%d got created with sha %s\n", pr.GetNumber(), createdFileSha.GetSHA()) 796 }) 797 It("only related pipelinerun should be triggered", func() { 798 Eventually(func() error { 799 pipelineRuns, err := f.AsKubeAdmin.HasController.GetAllPipelineRunsForApplication(applicationName, testNamespace) 800 if err != nil { 801 GinkgoWriter.Println("on pull PiplelineRun has not been created yet for the PR") 802 return err 803 } 804 if len(pipelineRuns.Items) != 1 || !strings.HasPrefix(pipelineRuns.Items[0].Name, multiComponentContextDirs[0]) { 805 return fmt.Errorf("pipelinerun created in the namespace %s is not as expected, got pipelineruns %v", testNamespace, pipelineRuns.Items) 806 } 807 return nil 808 }, time.Minute*5, constants.PipelineRunPollingInterval).Should(Succeed(), "timeout while waiting for PR pipeline to start") 809 }) 810 }) 811 When("a components is created with same git url in different namespace", func() { 812 var namespace, appName, compName string 813 var fw *framework.Framework 814 815 BeforeAll(func() { 816 fw, err = framework.NewFramework(utils.GetGeneratedNamespace("build-e2e")) 817 Expect(err).NotTo(HaveOccurred()) 818 namespace = fw.UserNamespace 819 820 appName = fmt.Sprintf("build-suite-negative-mc-%s", util.GenerateRandomString(4)) 821 _, err = f.AsKubeAdmin.HasController.CreateApplication(appName, namespace) 822 Expect(err).NotTo(HaveOccurred()) 823 824 compName = fmt.Sprintf("%s-%s", multiComponentContextDirs[0], util.GenerateRandomString(6)) 825 826 componentObj := appservice.ComponentSpec{ 827 ComponentName: compName, 828 Application: appName, 829 Source: appservice.ComponentSource{ 830 ComponentSourceUnion: appservice.ComponentSourceUnion{ 831 GitSource: &appservice.GitSource{ 832 URL: multiComponentGitSourceURL, 833 Revision: multiComponentBaseBranchName, 834 Context: multiComponentContextDirs[0], 835 }, 836 }, 837 }, 838 } 839 _, err = fw.AsKubeAdmin.HasController.CreateComponent(componentObj, namespace, "", "", appName, false, utils.MergeMaps(constants.ComponentPaCRequestAnnotation, constants.ImageControllerAnnotationRequestPublicRepo)) 840 Expect(err).ShouldNot(HaveOccurred()) 841 842 }) 843 844 AfterAll(func() { 845 if !CurrentSpecReport().Failed() { 846 Expect(fw.AsKubeAdmin.HasController.DeleteApplication(appName, namespace, false)).To(Succeed()) 847 Expect(fw.SandboxController.DeleteUserSignup(fw.UserName)).To(BeTrue()) 848 } 849 }) 850 851 It("should fail to configure PaC for the component", func() { 852 var buildStatus *controllers.BuildStatus 853 854 Eventually(func() (bool, error) { 855 component, err := fw.AsKubeAdmin.HasController.GetComponent(compName, namespace) 856 if err != nil { 857 GinkgoWriter.Printf("error while getting the component: %v\n", err) 858 return false, err 859 } 860 861 buildStatusAnnotationValue := component.Annotations[controllers.BuildStatusAnnotationName] 862 GinkgoWriter.Printf(buildStatusAnnotationValueLoggingFormat, buildStatusAnnotationValue) 863 statusBytes := []byte(buildStatusAnnotationValue) 864 865 err = json.Unmarshal(statusBytes, &buildStatus) 866 if err != nil { 867 GinkgoWriter.Printf("cannot unmarshal build status from component annotation: %v\n", err) 868 return false, err 869 } 870 871 GinkgoWriter.Printf("build status: %+v\n", buildStatus.PaC) 872 873 return buildStatus.PaC != nil && buildStatus.PaC.State == "error" && strings.Contains(buildStatus.PaC.ErrMessage, "Git repository is already handled by Pipelines as Code"), nil 874 }, time.Minute*2, time.Second*2).Should(BeTrue(), "build status is unexpected") 875 876 }) 877 878 }) 879 880 }) 881 Describe("test build secret lookup", Label("pac-build", "secret-lookup"), Ordered, func() { 882 var testNamespace, applicationName, firstComponentBaseBranchName, secondComponentBaseBranchName, firstComponentName, secondComponentName, firstPacBranchName, secondPacBranchName string 883 BeforeAll(func() { 884 if os.Getenv(constants.SKIP_PAC_TESTS_ENV) == "true" { 885 Skip("Skipping this test due to configuration issue with Spray proxy") 886 } 887 f, err = framework.NewFramework(utils.GetGeneratedNamespace("build-e2e")) 888 Expect(err).NotTo(HaveOccurred()) 889 testNamespace = f.UserNamespace 890 891 applicationName = fmt.Sprintf("build-secret-lookup-%s", util.GenerateRandomString(4)) 892 _, err = f.AsKubeAdmin.HasController.CreateApplication(applicationName, testNamespace) 893 Expect(err).NotTo(HaveOccurred()) 894 895 firstComponentBaseBranchName = fmt.Sprintf("component-one-base-%s", util.GenerateRandomString(6)) 896 err = f.AsKubeAdmin.CommonController.Github.CreateRef(secretLookupGitSourceRepoOneName, secretLookupDefaultBranchOne, secretLookupGitRevisionOne, firstComponentBaseBranchName) 897 Expect(err).ShouldNot(HaveOccurred()) 898 899 secondComponentBaseBranchName = fmt.Sprintf("component-two-base-%s", util.GenerateRandomString(6)) 900 err = f.AsKubeAdmin.CommonController.Github.CreateRef(secretLookupGitSourceRepoTwoName, secretLookupDefaultBranchTwo, secretLookupGitRevisionTwo, secondComponentBaseBranchName) 901 Expect(err).ShouldNot(HaveOccurred()) 902 903 }) 904 905 AfterAll(func() { 906 if !CurrentSpecReport().Failed() { 907 Expect(f.AsKubeAdmin.HasController.DeleteApplication(applicationName, testNamespace, false)).To(Succeed()) 908 Expect(f.SandboxController.DeleteUserSignup(f.UserName)).To(BeTrue()) 909 } 910 911 // Delete new branches created by PaC 912 err = f.AsKubeAdmin.CommonController.Github.DeleteRef(secretLookupGitSourceRepoOneName, firstPacBranchName) 913 if err != nil { 914 Expect(err.Error()).To(ContainSubstring("Reference does not exist")) 915 } 916 err = f.AsKubeAdmin.CommonController.Github.DeleteRef(secretLookupGitSourceRepoTwoName, secondPacBranchName) 917 if err != nil { 918 Expect(err.Error()).To(ContainSubstring("Reference does not exist")) 919 } 920 921 // Delete the created first component base branch 922 err = f.AsKubeAdmin.CommonController.Github.DeleteRef(secretLookupGitSourceRepoOneName, firstComponentBaseBranchName) 923 if err != nil { 924 Expect(err.Error()).To(ContainSubstring("Reference does not exist")) 925 } 926 // Delete the created second component base branch 927 err = f.AsKubeAdmin.CommonController.Github.DeleteRef(secretLookupGitSourceRepoTwoName, secondComponentBaseBranchName) 928 if err != nil { 929 Expect(err.Error()).To(ContainSubstring("Reference does not exist")) 930 } 931 932 // Delete created webhook from GitHub 933 cleanupWebhooks(f, secretLookupGitSourceRepoTwoName) 934 935 }) 936 When("two secrets are created", func() { 937 BeforeAll(func() { 938 // create the correct build secret for second component 939 secretName1 := "build-secret-1" 940 secretAnnotations := map[string]string{ 941 "appstudio.redhat.com/scm.repository": os.Getenv("MY_GITHUB_ORG") + "/" + secretLookupGitSourceRepoTwoName, 942 } 943 token := os.Getenv("GITHUB_TOKEN") 944 err = createBuildSecret(f, secretName1, secretAnnotations, token) 945 Expect(err).ShouldNot(HaveOccurred()) 946 947 // create incorrect build-secret for the first component 948 secretName2 := "build-secret-2" 949 dummyToken := "ghp_dummy_secret" 950 err = createBuildSecret(f, secretName2, nil, dummyToken) 951 Expect(err).ShouldNot(HaveOccurred()) 952 953 // component names and pac branch names 954 firstComponentName = fmt.Sprintf("%s-%s", "component-one", util.GenerateRandomString(4)) 955 secondComponentName = fmt.Sprintf("%s-%s", "component-two", util.GenerateRandomString(4)) 956 firstPacBranchName = constants.PaCPullRequestBranchPrefix + firstComponentName 957 secondPacBranchName = constants.PaCPullRequestBranchPrefix + secondComponentName 958 }) 959 960 It("creates first component", func() { 961 componentObj1 := appservice.ComponentSpec{ 962 ComponentName: firstComponentName, 963 Application: applicationName, 964 Source: appservice.ComponentSource{ 965 ComponentSourceUnion: appservice.ComponentSourceUnion{ 966 GitSource: &appservice.GitSource{ 967 URL: secretLookupComponentOneGitSourceURL, 968 Revision: firstComponentBaseBranchName, 969 }, 970 }, 971 }, 972 } 973 _, err := f.AsKubeAdmin.HasController.CreateComponent(componentObj1, testNamespace, "", "", applicationName, false, utils.MergeMaps(constants.ComponentPaCRequestAnnotation, constants.ImageControllerAnnotationRequestPublicRepo)) 974 Expect(err).ShouldNot(HaveOccurred()) 975 }) 976 It("creates second component", func() { 977 componentObj2 := appservice.ComponentSpec{ 978 ComponentName: secondComponentName, 979 Application: applicationName, 980 Source: appservice.ComponentSource{ 981 ComponentSourceUnion: appservice.ComponentSourceUnion{ 982 GitSource: &appservice.GitSource{ 983 URL: secretLookupComponentTwoGitSourceURL, 984 Revision: secondComponentBaseBranchName, 985 }, 986 }, 987 }, 988 } 989 _, err := f.AsKubeAdmin.HasController.CreateComponent(componentObj2, testNamespace, "", "", applicationName, false, utils.MergeMaps(constants.ComponentPaCRequestAnnotation, constants.ImageControllerAnnotationRequestPublicRepo)) 990 Expect(err).ShouldNot(HaveOccurred()) 991 }) 992 993 It("check first component annotation has errors", func() { 994 buildStatus := &controllers.BuildStatus{} 995 Eventually(func() (bool, error) { 996 component, err := f.AsKubeAdmin.HasController.GetComponent(firstComponentName, testNamespace) 997 if err != nil { 998 return false, err 999 } else if component == nil { 1000 return false, fmt.Errorf("got component as nil after getting component %s in namespace %s", firstComponentName, testNamespace) 1001 } 1002 buildStatusAnnotationValue := component.Annotations[controllers.BuildStatusAnnotationName] 1003 GinkgoWriter.Printf(buildStatusAnnotationValueLoggingFormat, buildStatusAnnotationValue) 1004 statusBytes := []byte(buildStatusAnnotationValue) 1005 err = json.Unmarshal(statusBytes, buildStatus) 1006 if err != nil { 1007 return false, err 1008 } 1009 return buildStatus.PaC != nil && buildStatus.PaC.State == "error" && strings.Contains(buildStatus.PaC.ErrMessage, "Access token is unrecognizable by GitHub"), nil 1010 }, time.Minute*2, 5*time.Second).Should(BeTrue(), "failed while checking build status for component %q is correct", firstComponentName) 1011 }) 1012 1013 It(fmt.Sprintf("triggered PipelineRun is for component %s", secondComponentName), func() { 1014 timeout = time.Minute * 5 1015 Eventually(func() error { 1016 pr, err := f.AsKubeAdmin.HasController.GetComponentPipelineRun(secondComponentName, applicationName, testNamespace, "") 1017 if err != nil { 1018 GinkgoWriter.Printf("PipelineRun has not been created yet for the component %s/%s\n", testNamespace, secondComponentName) 1019 return err 1020 } 1021 if !pr.HasStarted() { 1022 return fmt.Errorf("pipelinerun %s/%s hasn't started yet", pr.GetNamespace(), pr.GetName()) 1023 } 1024 return nil 1025 }, timeout, constants.PipelineRunPollingInterval).Should(Succeed(), fmt.Sprintf("timed out when waiting for the PipelineRun to start for the component %s/%s", secondComponentName, testNamespace)) 1026 }) 1027 1028 It("check only one pipelinerun should be triggered", func() { 1029 // Waiting for 2 minute to see if only one pipelinerun is triggered 1030 Consistently(func() (bool, error) { 1031 pipelineRuns, err := f.AsKubeAdmin.HasController.GetAllPipelineRunsForApplication(applicationName, testNamespace) 1032 if err != nil { 1033 return false, err 1034 } 1035 if len(pipelineRuns.Items) != 1 { 1036 return false, fmt.Errorf("plr count in the namespace %s is not one, got pipelineruns %v", testNamespace, pipelineRuns.Items) 1037 } 1038 return true, nil 1039 }, time.Minute*2, constants.PipelineRunPollingInterval).Should(BeTrue(), "timeout while checking if any more pipelinerun is triggered") 1040 }) 1041 }) 1042 }) 1043 Describe("test build annotations", Label("annotations"), Ordered, func() { 1044 var testNamespace, componentName, applicationName string 1045 var componentObj appservice.ComponentSpec 1046 var component *appservice.Component 1047 1048 var timeout, interval time.Duration 1049 1050 BeforeAll(func() { 1051 f, err = framework.NewFramework(utils.GetGeneratedNamespace("build-e2e")) 1052 Expect(err).ShouldNot(HaveOccurred()) 1053 testNamespace = f.UserNamespace 1054 1055 timeout = 5 * time.Minute 1056 interval = 5 * time.Second 1057 1058 applicationName = fmt.Sprintf("build-suite-test-application-%s", util.GenerateRandomString(4)) 1059 _, err = f.AsKubeAdmin.HasController.CreateApplication(applicationName, testNamespace) 1060 Expect(err).NotTo(HaveOccurred()) 1061 1062 componentName = fmt.Sprintf("%s-%s", "test-annotations", util.GenerateRandomString(6)) 1063 1064 }) 1065 1066 AfterAll(func() { 1067 if !CurrentSpecReport().Failed() { 1068 Expect(f.AsKubeAdmin.HasController.DeleteApplication(applicationName, testNamespace, false)).To(Succeed()) 1069 Expect(f.SandboxController.DeleteUserSignup(f.UserName)).To(BeTrue()) 1070 } 1071 1072 }) 1073 1074 When("component is created", func() { 1075 var lastBuildStartTime string 1076 1077 BeforeAll(func() { 1078 componentObj = appservice.ComponentSpec{ 1079 ComponentName: componentName, 1080 Application: applicationName, 1081 Source: appservice.ComponentSource{ 1082 ComponentSourceUnion: appservice.ComponentSourceUnion{ 1083 GitSource: &appservice.GitSource{ 1084 URL: annotationsTestGitSourceURL, 1085 Revision: annotationsTestRevision, 1086 }, 1087 }, 1088 }, 1089 } 1090 1091 component, err = f.AsKubeAdmin.HasController.CreateComponent(componentObj, testNamespace, "", "", applicationName, false, nil) 1092 Expect(component).ToNot(BeNil()) 1093 Expect(err).ShouldNot(HaveOccurred()) 1094 }) 1095 1096 It("triggers a pipeline run", func() { 1097 Eventually(func() error { 1098 pr, err := f.AsKubeAdmin.HasController.GetComponentPipelineRun(componentName, applicationName, testNamespace, "") 1099 if err != nil { 1100 GinkgoWriter.Printf("PipelineRun has not been created yet for the component %s/%s\n", testNamespace, componentName) 1101 return err 1102 } 1103 if !pr.HasStarted() { 1104 return fmt.Errorf("pipelinerun %s/%s hasn't started yet", pr.GetNamespace(), pr.GetName()) 1105 } 1106 return nil 1107 }, time.Minute*5, constants.PipelineRunPollingInterval).Should(Succeed(), fmt.Sprintf("timed out when waiting for the PipelineRun to start for the component %s/%s", testNamespace, componentName)) 1108 }) 1109 1110 It("component build status annotation is set correctly", func() { 1111 var buildStatus *controllers.BuildStatus 1112 1113 Eventually(func() (bool, error) { 1114 component, err := f.AsKubeAdmin.HasController.GetComponent(componentName, testNamespace) 1115 if err != nil { 1116 GinkgoWriter.Printf("cannot get the component: %v\n", err) 1117 return false, err 1118 } 1119 1120 buildStatusAnnotationValue := component.Annotations[controllers.BuildStatusAnnotationName] 1121 GinkgoWriter.Printf(buildStatusAnnotationValueLoggingFormat, buildStatusAnnotationValue) 1122 statusBytes := []byte(buildStatusAnnotationValue) 1123 1124 err = json.Unmarshal(statusBytes, &buildStatus) 1125 if err != nil { 1126 GinkgoWriter.Printf("cannot unmarshal build status: %v\n", err) 1127 return false, err 1128 } 1129 1130 if buildStatus.Simple != nil { 1131 GinkgoWriter.Printf("buildStartTime: %s\n", buildStatus.Simple.BuildStartTime) 1132 lastBuildStartTime = buildStatus.Simple.BuildStartTime 1133 } else { 1134 GinkgoWriter.Println("build status does not have simple field") 1135 } 1136 1137 return buildStatus.Simple != nil && buildStatus.Simple.BuildStartTime != "", nil 1138 }, timeout, interval).Should(BeTrue(), "build status has unexpected content") 1139 1140 //Expect pipelinerun count to be 1 1141 Eventually(func() error { 1142 pipelineRuns, err := f.AsKubeAdmin.HasController.GetAllPipelineRunsForApplication(applicationName, testNamespace) 1143 if err != nil { 1144 GinkgoWriter.Println("PiplelineRun has not been created yet") 1145 return err 1146 } 1147 if len(pipelineRuns.Items) != 1 { 1148 return fmt.Errorf("pipelinerun count in the namespace %s is not one, got pipelineruns %v", testNamespace, pipelineRuns.Items) 1149 } 1150 return nil 1151 }, time.Minute*5, constants.PipelineRunPollingInterval).Should(Succeed(), "timeout while waiting for first pipelinerun to start") 1152 }) 1153 1154 Specify("simple build can be triggered manually", func() { 1155 // Wait 1 second before sending the second build request, so that we get different buildStatus.Simple.BuildStartTime timestamp 1156 time.Sleep(1 * time.Second) 1157 Expect(f.AsKubeAdmin.HasController.SetComponentAnnotation(componentName, controllers.BuildRequestAnnotationName, controllers.BuildRequestTriggerSimpleBuildAnnotationValue, testNamespace)).To(Succeed()) 1158 }) 1159 1160 It("another pipelineRun is triggered", func() { 1161 //Expect pipelinerun count to be 2 1162 Eventually(func() error { 1163 pipelineRuns, err := f.AsKubeAdmin.HasController.GetAllPipelineRunsForApplication(applicationName, testNamespace) 1164 if err != nil { 1165 GinkgoWriter.Println("Second piplelineRun has not been created yet") 1166 return err 1167 } 1168 if len(pipelineRuns.Items) != 2 { 1169 return fmt.Errorf("pipelinerun count in the namespace %s is not two, got pipelineruns %v", testNamespace, pipelineRuns.Items) 1170 } 1171 return nil 1172 }, time.Minute*5, constants.PipelineRunPollingInterval).Should(Succeed(), "timeout while waiting for second pipelinerun to start") 1173 }) 1174 1175 It("component build annotation is correct", func() { 1176 var buildStatus *controllers.BuildStatus 1177 1178 Eventually(func() (bool, error) { 1179 component, err := f.AsKubeAdmin.HasController.GetComponent(componentName, testNamespace) 1180 if err != nil { 1181 GinkgoWriter.Printf("cannot get the component: %v\n", err) 1182 return false, err 1183 } 1184 1185 buildStatusAnnotationValue := component.Annotations[controllers.BuildStatusAnnotationName] 1186 GinkgoWriter.Printf(buildStatusAnnotationValueLoggingFormat, buildStatusAnnotationValue) 1187 statusBytes := []byte(buildStatusAnnotationValue) 1188 1189 err = json.Unmarshal(statusBytes, &buildStatus) 1190 if err != nil { 1191 GinkgoWriter.Printf("cannot unmarshal build status: %v\n", err) 1192 return false, err 1193 } 1194 1195 if buildStatus.Simple != nil { 1196 GinkgoWriter.Printf("buildStartTime: %s\n", buildStatus.Simple.BuildStartTime) 1197 } else { 1198 GinkgoWriter.Println("build status does not have simple field") 1199 } 1200 1201 return buildStatus.Simple != nil && buildStatus.Simple.BuildStartTime != lastBuildStartTime, nil 1202 }, timeout, interval).Should(BeTrue(), "build status has unexpected content") 1203 }) 1204 1205 It("handles invalid request annotation", func() { 1206 1207 invalidAnnotation := "foo" 1208 expectedInvalidAnnotationMessage := fmt.Sprintf("unexpected build request: %s", invalidAnnotation) 1209 1210 Expect(f.AsKubeAdmin.HasController.SetComponentAnnotation(componentName, controllers.BuildRequestAnnotationName, invalidAnnotation, testNamespace)).To(Succeed()) 1211 1212 // Waiting for 2 minute to see if any more pipelinerun is triggered 1213 Consistently(func() (bool, error) { 1214 pipelineRuns, err := f.AsKubeAdmin.HasController.GetAllPipelineRunsForApplication(applicationName, testNamespace) 1215 if err != nil { 1216 return false, err 1217 } 1218 if len(pipelineRuns.Items) != 2 { 1219 return false, fmt.Errorf("pipelinerun count in the namespace %s is not two, got pipelineruns %v", testNamespace, pipelineRuns.Items) 1220 } 1221 return true, nil 1222 }, time.Minute*2, constants.PipelineRunPollingInterval).Should(BeTrue(), "timeout while checking if any more pipelinerun is triggered") 1223 1224 buildStatus := &controllers.BuildStatus{} 1225 Eventually(func() error { 1226 component, err = f.AsKubeAdmin.HasController.GetComponent(componentName, testNamespace) 1227 if err != nil { 1228 return err 1229 } else if component == nil { 1230 return fmt.Errorf("got component as nil after getting component %s in namespace %s", componentName, testNamespace) 1231 } 1232 buildStatusAnnotationValue := component.Annotations[controllers.BuildStatusAnnotationName] 1233 GinkgoWriter.Printf(buildStatusAnnotationValueLoggingFormat, buildStatusAnnotationValue) 1234 statusBytes := []byte(buildStatusAnnotationValue) 1235 err = json.Unmarshal(statusBytes, buildStatus) 1236 if err != nil { 1237 return err 1238 } 1239 if !strings.Contains(buildStatus.Message, expectedInvalidAnnotationMessage) { 1240 return fmt.Errorf("build status message is not as expected, got: %q, expected: %q", buildStatus.Message, expectedInvalidAnnotationMessage) 1241 } 1242 return nil 1243 }, time.Minute*2, 2*time.Second).Should(Succeed(), "failed while checking build status message for component %q is correct after setting invalid annotations", componentName) 1244 }) 1245 }) 1246 }) 1247 1248 Describe("Creating component with container image source", Ordered, func() { 1249 var applicationName, componentName, testNamespace string 1250 var timeout time.Duration 1251 1252 BeforeAll(func() { 1253 applicationName = fmt.Sprintf("test-app-%s", util.GenerateRandomString(4)) 1254 f, err = framework.NewFramework(utils.GetGeneratedNamespace("build-e2e")) 1255 Expect(err).NotTo(HaveOccurred()) 1256 testNamespace = f.UserNamespace 1257 1258 _, err = f.AsKubeAdmin.HasController.CreateApplication(applicationName, testNamespace) 1259 Expect(err).NotTo(HaveOccurred()) 1260 1261 componentName = fmt.Sprintf("build-suite-test-component-image-source-%s", util.GenerateRandomString(6)) 1262 outputContainerImage := "" 1263 timeout = time.Second * 10 1264 // Create a component with containerImageSource being defined 1265 component := appservice.ComponentSpec{ 1266 ComponentName: fmt.Sprintf("build-suite-test-component-image-source-%s", util.GenerateRandomString(6)), 1267 ContainerImage: containerImageSource, 1268 } 1269 _, err = f.AsKubeAdmin.HasController.CreateComponent(component, testNamespace, outputContainerImage, "", applicationName, true, map[string]string{}) 1270 Expect(err).ShouldNot(HaveOccurred()) 1271 1272 // collect Build ResourceQuota metrics (temporary) 1273 err = f.AsKubeAdmin.CommonController.GetResourceQuotaInfo("build", testNamespace, appstudioCrdsBuild) 1274 Expect(err).NotTo(HaveOccurred()) 1275 err = f.AsKubeAdmin.CommonController.GetResourceQuotaInfo("build", testNamespace, computeBuild) 1276 Expect(err).NotTo(HaveOccurred()) 1277 }) 1278 1279 AfterAll(func() { 1280 // collect Build ResourceQuota metrics (temporary) 1281 err = f.AsKubeAdmin.CommonController.GetResourceQuotaInfo("build", testNamespace, appstudioCrdsBuild) 1282 Expect(err).NotTo(HaveOccurred()) 1283 err = f.AsKubeAdmin.CommonController.GetResourceQuotaInfo("build", testNamespace, computeBuild) 1284 Expect(err).NotTo(HaveOccurred()) 1285 if !CurrentSpecReport().Failed() { 1286 Expect(f.AsKubeAdmin.HasController.DeleteApplication(applicationName, testNamespace, false)).To(Succeed()) 1287 Expect(f.AsKubeAdmin.HasController.DeleteComponent(componentName, testNamespace, false)).To(Succeed()) 1288 Expect(f.AsKubeAdmin.TektonController.DeleteAllPipelineRunsInASpecificNamespace(testNamespace)).To(Succeed()) 1289 Expect(f.SandboxController.DeleteUserSignup(f.UserName)).To(BeTrue()) 1290 } 1291 }) 1292 1293 It("should not trigger a PipelineRun", func() { 1294 Consistently(func() bool { 1295 _, err := f.AsKubeAdmin.HasController.GetComponentPipelineRun(componentName, applicationName, testNamespace, "") 1296 Expect(err).To(HaveOccurred()) 1297 return strings.Contains(err.Error(), "no pipelinerun found") 1298 }, timeout, constants.PipelineRunPollingInterval).Should(BeTrue(), fmt.Sprintf("expected no PipelineRun to be triggered for the component %s in %s namespace", componentName, testNamespace)) 1299 }) 1300 }) 1301 1302 Describe("PLNSRVCE-799 - test pipeline selector", Label("pipeline-selector"), Ordered, func() { 1303 var timeout time.Duration 1304 var componentName, applicationName, testNamespace string 1305 var expectedAdditionalPipelineParam buildservice.PipelineParam 1306 var pr *pipeline.PipelineRun 1307 1308 BeforeAll(func() { 1309 f, err = framework.NewFramework(utils.GetGeneratedNamespace("build-e2e")) 1310 Expect(err).NotTo(HaveOccurred()) 1311 testNamespace = f.UserNamespace 1312 applicationName = fmt.Sprintf("test-app-%s", util.GenerateRandomString(4)) 1313 1314 _, err = f.AsKubeAdmin.HasController.CreateApplication(applicationName, testNamespace) 1315 Expect(err).NotTo(HaveOccurred()) 1316 1317 componentName = "build-suite-test-bundle-overriding" 1318 1319 expectedAdditionalPipelineParam = buildservice.PipelineParam{ 1320 Name: "test-custom-param-name", 1321 Value: "test-custom-param-value", 1322 } 1323 1324 timeout = time.Second * 600 1325 1326 // collect Build ResourceQuota metrics (temporary) 1327 err = f.AsKubeAdmin.CommonController.GetResourceQuotaInfo("build", testNamespace, appstudioCrdsBuild) 1328 Expect(err).NotTo(HaveOccurred()) 1329 err = f.AsKubeAdmin.CommonController.GetResourceQuotaInfo("build", testNamespace, computeBuild) 1330 Expect(err).NotTo(HaveOccurred()) 1331 }) 1332 1333 AfterAll(func() { 1334 // collect Build ResourceQuota metrics (temporary) 1335 err = f.AsKubeAdmin.CommonController.GetResourceQuotaInfo("build", testNamespace, appstudioCrdsBuild) 1336 Expect(err).NotTo(HaveOccurred()) 1337 err = f.AsKubeAdmin.CommonController.GetResourceQuotaInfo("build", testNamespace, computeBuild) 1338 Expect(err).NotTo(HaveOccurred()) 1339 1340 if !CurrentSpecReport().Failed() { 1341 Expect(f.AsKubeAdmin.HasController.DeleteApplication(applicationName, testNamespace, false)).To(Succeed()) 1342 Expect(f.AsKubeAdmin.HasController.DeleteComponent(componentName, testNamespace, false)).To(Succeed()) 1343 Expect(f.AsKubeAdmin.TektonController.DeleteAllPipelineRunsInASpecificNamespace(testNamespace)).To(Succeed()) 1344 Expect(f.SandboxController.DeleteUserSignup(f.UserName)).To(BeTrue()) 1345 } 1346 }) 1347 1348 It("a specific Pipeline bundle should be used and additional pipeline params should be added to the PipelineRun if all WhenConditions match", func() { 1349 // using cdq since git ref is not known 1350 cdq, err := f.AsKubeAdmin.HasController.CreateComponentDetectionQuery(componentName, testNamespace, helloWorldComponentGitSourceURL, "", "", "", false) 1351 Expect(err).NotTo(HaveOccurred()) 1352 Expect(cdq.Status.ComponentDetected).To(HaveLen(1), "Expected length of the detected Components was not 1") 1353 1354 for _, compDetected := range cdq.Status.ComponentDetected { 1355 // Since we only know the component name after cdq creation, 1356 // BuildPipelineSelector should be created before component creation and after cdq creation 1357 ps := &buildservice.BuildPipelineSelector{ 1358 ObjectMeta: metav1.ObjectMeta{ 1359 Name: "build-pipeline-selector", 1360 Namespace: testNamespace, 1361 }, 1362 Spec: buildservice.BuildPipelineSelectorSpec{Selectors: []buildservice.PipelineSelector{ 1363 { 1364 Name: "user-custom-selector", 1365 PipelineRef: *tekton.NewBundleResolverPipelineRef("docker-build", dummyPipelineBundleRef), 1366 PipelineParams: []buildservice.PipelineParam{expectedAdditionalPipelineParam}, 1367 WhenConditions: buildservice.WhenCondition{ 1368 ProjectType: "hello-world", 1369 DockerfileRequired: pointer.To[bool](true), 1370 ComponentName: compDetected.ComponentStub.ComponentName, 1371 Annotations: map[string]string{"skip-initial-checks": "true"}, 1372 Labels: constants.ComponentDefaultLabel, 1373 }, 1374 }, 1375 }}, 1376 } 1377 1378 Expect(f.AsKubeAdmin.CommonController.KubeRest().Create(context.Background(), ps)).To(Succeed()) 1379 c, err := f.AsKubeAdmin.HasController.CreateComponent(compDetected.ComponentStub, testNamespace, "", "", applicationName, true, map[string]string{}) 1380 Expect(err).NotTo(HaveOccurred()) 1381 componentName = c.Name 1382 } 1383 1384 Eventually(func() error { 1385 pr, err = f.AsKubeAdmin.HasController.GetComponentPipelineRun(componentName, applicationName, testNamespace, "") 1386 if err != nil { 1387 GinkgoWriter.Printf("PipelineRun has not been created yet for the component %s/%s\n", testNamespace, componentName) 1388 return err 1389 } 1390 if !pr.HasStarted() { 1391 return fmt.Errorf("pipelinerun %s/%s hasn't started yet", pr.GetNamespace(), pr.GetName()) 1392 } 1393 return nil 1394 }, timeout, constants.PipelineRunPollingInterval).Should(Succeed(), fmt.Sprintf("timed out when waiting for the PipelineRun to start for the component %s/%s", testNamespace, componentName)) 1395 1396 pr, err = f.AsKubeAdmin.HasController.GetComponentPipelineRun(componentName, applicationName, testNamespace, "") 1397 Expect(err).ShouldNot(HaveOccurred()) 1398 Expect(pr.Spec.PipelineRef.Params).To(ContainElement(pipeline.Param{ 1399 Name: "bundle", 1400 Value: pipeline.ParamValue{StringVal: dummyPipelineBundleRef, Type: "string"}}, 1401 )) 1402 Expect(pr.Spec.Params).To(ContainElement(pipeline.Param{ 1403 Name: expectedAdditionalPipelineParam.Name, 1404 Value: pipeline.ParamValue{StringVal: expectedAdditionalPipelineParam.Value, Type: "string"}}, 1405 )) 1406 }) 1407 1408 It("default Pipeline bundle should be used and no additional Pipeline params should be added to the PipelineRun if one of the WhenConditions does not match", func() { 1409 notMatchingComponentName := componentName + util.GenerateRandomString(6) 1410 // using cdq since git ref is not known 1411 cdq, err := f.AsKubeAdmin.HasController.CreateComponentDetectionQuery(notMatchingComponentName, testNamespace, helloWorldComponentGitSourceURL, "", "", "", false) 1412 Expect(err).NotTo(HaveOccurred()) 1413 Expect(cdq.Status.ComponentDetected).To(HaveLen(1), "Expected length of the detected Components was not 1") 1414 1415 for _, compDetected := range cdq.Status.ComponentDetected { 1416 c, err := f.AsKubeAdmin.HasController.CreateComponent(compDetected.ComponentStub, testNamespace, "", "", applicationName, true, map[string]string{}) 1417 Expect(err).NotTo(HaveOccurred()) 1418 notMatchingComponentName = c.Name 1419 } 1420 1421 Eventually(func() error { 1422 pr, err = f.AsKubeAdmin.HasController.GetComponentPipelineRun(notMatchingComponentName, applicationName, testNamespace, "") 1423 if err != nil { 1424 GinkgoWriter.Printf("PipelineRun has not been created yet for the component %s/%s\n", testNamespace, notMatchingComponentName) 1425 return err 1426 } 1427 if !pr.HasStarted() { 1428 return fmt.Errorf("pipelinerun %s/%s hasn't started yet", pr.GetNamespace(), pr.GetName()) 1429 } 1430 return err 1431 }, timeout, constants.PipelineRunPollingInterval).Should(Succeed(), fmt.Sprintf("timed out when waiting for the PipelineRun to start for the component %s/%s", testNamespace, notMatchingComponentName)) 1432 1433 pr, err = f.AsKubeAdmin.HasController.GetComponentPipelineRun(notMatchingComponentName, applicationName, testNamespace, "") 1434 Expect(err).ShouldNot(HaveOccurred()) 1435 Expect(tekton.GetBundleRef(pr.Spec.PipelineRef)).ToNot(Equal(dummyPipelineBundleRef)) //nolint:all 1436 Expect(pr.Spec.Params).ToNot(ContainElement(pipeline.Param{ 1437 Name: expectedAdditionalPipelineParam.Name, 1438 Value: pipeline.ParamValue{StringVal: expectedAdditionalPipelineParam.Value, Type: "string"}}, 1439 )) 1440 }) 1441 }) 1442 1443 Describe("A secret with dummy quay.io credentials is created in the testing namespace", Ordered, func() { 1444 1445 var applicationName, componentName, testNamespace string 1446 var timeout time.Duration 1447 var err error 1448 var pr *pipeline.PipelineRun 1449 1450 BeforeAll(func() { 1451 1452 f, err = framework.NewFramework(utils.GetGeneratedNamespace("build-e2e")) 1453 Expect(err).NotTo(HaveOccurred()) 1454 testNamespace = f.UserNamespace 1455 1456 if err = f.AsKubeAdmin.CommonController.UnlinkSecretFromServiceAccount(testNamespace, constants.RegistryAuthSecretName, constants.DefaultPipelineServiceAccount, true); err != nil { 1457 GinkgoWriter.Println(fmt.Sprintf("Failed to unlink registry auth secret from service account: %v\n", err)) 1458 } 1459 1460 if err = f.AsKubeAdmin.CommonController.DeleteSecret(testNamespace, constants.RegistryAuthSecretName); err != nil { 1461 GinkgoWriter.Println(fmt.Sprintf("Failed to delete regitry auth secret from namespace: %s\n", err)) 1462 } 1463 1464 _, err := f.AsKubeAdmin.CommonController.GetSecret(testNamespace, constants.RegistryAuthSecretName) 1465 if err != nil { 1466 // If we have an error when getting RegistryAuthSecretName, it should be IsNotFound err 1467 Expect(k8sErrors.IsNotFound(err)).To(BeTrue()) 1468 } else { 1469 Skip("a registry auth secret is already created in testing namespace - skipping....") 1470 } 1471 1472 applicationName = fmt.Sprintf("test-app-%s", util.GenerateRandomString(4)) 1473 1474 _, err = f.AsKubeAdmin.HasController.CreateApplication(applicationName, testNamespace) 1475 Expect(err).NotTo(HaveOccurred()) 1476 1477 timeout = time.Minute * 5 1478 1479 dummySecret := &v1.Secret{ 1480 ObjectMeta: metav1.ObjectMeta{Name: constants.RegistryAuthSecretName}, 1481 Type: v1.SecretTypeDockerConfigJson, 1482 Data: map[string][]byte{".dockerconfigjson": []byte("{\"auths\":{\"quay.io\":{\"username\":\"test\",\"password\":\"test\",\"auth\":\"dGVzdDp0ZXN0\",\"email\":\"\"}}}")}, 1483 } 1484 1485 _, err = f.AsKubeAdmin.CommonController.CreateSecret(testNamespace, dummySecret) 1486 Expect(err).ToNot(HaveOccurred()) 1487 err = f.AsKubeAdmin.CommonController.LinkSecretToServiceAccount(testNamespace, dummySecret.Name, constants.DefaultPipelineServiceAccount, false) 1488 Expect(err).ToNot(HaveOccurred()) 1489 1490 componentName = "build-suite-test-secret-overriding" 1491 // using cdq since git ref is not known 1492 cdq, err := f.AsKubeAdmin.HasController.CreateComponentDetectionQuery(componentName, testNamespace, helloWorldComponentGitSourceURL, "", "", "", false) 1493 Expect(err).NotTo(HaveOccurred()) 1494 Expect(cdq.Status.ComponentDetected).To(HaveLen(1), "Expected length of the detected Components was not 1") 1495 1496 for _, compDetected := range cdq.Status.ComponentDetected { 1497 c, err := f.AsKubeAdmin.HasController.CreateComponent(compDetected.ComponentStub, testNamespace, "", "", applicationName, true, map[string]string{}) 1498 Expect(err).NotTo(HaveOccurred()) 1499 componentName = c.Name 1500 } 1501 1502 // collect Build ResourceQuota metrics (temporary) 1503 err = f.AsKubeAdmin.CommonController.GetResourceQuotaInfo("build", testNamespace, appstudioCrdsBuild) 1504 Expect(err).NotTo(HaveOccurred()) 1505 err = f.AsKubeAdmin.CommonController.GetResourceQuotaInfo("build", testNamespace, computeBuild) 1506 Expect(err).NotTo(HaveOccurred()) 1507 }) 1508 1509 AfterAll(func() { 1510 // collect Build ResourceQuota metrics (temporary) 1511 err = f.AsKubeAdmin.CommonController.GetResourceQuotaInfo("build", testNamespace, appstudioCrdsBuild) 1512 Expect(err).NotTo(HaveOccurred()) 1513 err = f.AsKubeAdmin.CommonController.GetResourceQuotaInfo("build", testNamespace, computeBuild) 1514 Expect(err).NotTo(HaveOccurred()) 1515 1516 if !CurrentSpecReport().Failed() { 1517 Expect(f.AsKubeAdmin.HasController.DeleteApplication(applicationName, testNamespace, false)).To(Succeed()) 1518 Expect(f.AsKubeAdmin.HasController.DeleteComponent(componentName, testNamespace, false)).To(Succeed()) 1519 Expect(f.AsKubeAdmin.TektonController.DeleteAllPipelineRunsInASpecificNamespace(testNamespace)).To(Succeed()) 1520 Expect(f.SandboxController.DeleteUserSignup(f.UserName)).To(BeTrue()) 1521 } 1522 }) 1523 1524 It("should override the shared secret", func() { 1525 Eventually(func() error { 1526 pr, err = f.AsKubeAdmin.HasController.GetComponentPipelineRun(componentName, applicationName, testNamespace, "") 1527 if err != nil { 1528 GinkgoWriter.Printf("PipelineRun has not been created yet for the component %s/%s\n", testNamespace, componentName) 1529 return err 1530 } 1531 if !pr.HasStarted() { 1532 return fmt.Errorf("pipelinerun %s/%s hasn't started yet", pr.GetNamespace(), pr.GetName()) 1533 } 1534 return nil 1535 }, timeout, constants.PipelineRunPollingInterval).Should(Succeed(), fmt.Sprintf("timed out when waiting for the PipelineRun to start for the component %s/%s", testNamespace, componentName)) 1536 1537 pr, err = f.AsKubeAdmin.HasController.GetComponentPipelineRun(componentName, applicationName, testNamespace, "") 1538 Expect(err).ShouldNot(HaveOccurred()) 1539 Expect(pr.Spec.Workspaces).To(HaveLen(1)) 1540 }) 1541 1542 It("should not be possible to push to quay.io repo (PipelineRun should fail)", func() { 1543 pipelineRunTimeout := int(time.Duration(20) * time.Minute) 1544 1545 Expect(f.AsKubeAdmin.TektonController.WatchPipelineRun(pr.Name, testNamespace, pipelineRunTimeout)).To(Succeed()) 1546 pr, err = f.AsKubeAdmin.TektonController.GetPipelineRun(pr.GetName(), pr.GetNamespace()) 1547 Expect(err).NotTo(HaveOccurred()) 1548 tr, err := f.AsKubeAdmin.TektonController.GetTaskRunStatus(f.AsKubeAdmin.CommonController.KubeRest(), pr, constants.BuildTaskRunName) 1549 Expect(err).NotTo(HaveOccurred()) 1550 Expect(tekton.DidTaskRunSucceed(tr)).To(BeFalse()) 1551 }) 1552 }) 1553 1554 Describe("test of component update with renovate", Ordered, Label("renovate", "multi-component"), func() { 1555 type multiComponent struct { 1556 repoName string 1557 baseBranch string 1558 componentBranch string 1559 baseRevision string 1560 componentName string 1561 gitRepo string 1562 pacBranchName string 1563 component *appservice.Component 1564 } 1565 1566 ChildComponentDef := multiComponent{repoName: componentDependenciesChildRepoName, baseRevision: componentDependenciesChildGitRevision, baseBranch: componentDependenciesChildDefaultBranch} 1567 ParentComponentDef := multiComponent{repoName: componentDependenciesParentRepoName, baseRevision: componentDependenciesParentGitRevision, baseBranch: componentDependenciesParentDefaultBranch} 1568 components := []*multiComponent{&ChildComponentDef, &ParentComponentDef} 1569 var applicationName, testNamespace, mergeResultSha string 1570 var prNumber int 1571 var mergeResult *github.PullRequestMergeResult 1572 var timeout time.Duration 1573 var parentFirstDigest string 1574 var parentPostPacMergeDigest string 1575 var parentImageNameWithNoDigest string 1576 const distributionRepository = "quay.io/redhat-appstudio-qe/release-repository" 1577 quayOrg := utils.GetEnv("DEFAULT_QUAY_ORG", "") 1578 1579 var managedNamespace string 1580 BeforeAll(func() { 1581 f, err = framework.NewFramework(utils.GetGeneratedNamespace("build-e2e")) 1582 Expect(err).NotTo(HaveOccurred()) 1583 testNamespace = f.UserNamespace 1584 1585 applicationName = fmt.Sprintf("build-suite-component-update-%s", util.GenerateRandomString(4)) 1586 _, err = f.AsKubeAdmin.HasController.CreateApplication(applicationName, testNamespace) 1587 Expect(err).NotTo(HaveOccurred()) 1588 branchString := util.GenerateRandomString(4) 1589 ParentComponentDef.componentBranch = fmt.Sprintf("multi-component-parent-base-%s", branchString) 1590 ChildComponentDef.componentBranch = fmt.Sprintf("multi-component-child-base-%s", branchString) 1591 ParentComponentDef.gitRepo = fmt.Sprintf(githubUrlFormat, gihubOrg, ParentComponentDef.repoName) 1592 ChildComponentDef.gitRepo = fmt.Sprintf(githubUrlFormat, gihubOrg, ChildComponentDef.repoName) 1593 ParentComponentDef.componentName = fmt.Sprintf("multi-component-parent-%s", branchString) 1594 ChildComponentDef.componentName = fmt.Sprintf("multi-component-child-%s", branchString) 1595 ParentComponentDef.pacBranchName = constants.PaCPullRequestBranchPrefix + ParentComponentDef.componentName 1596 ChildComponentDef.pacBranchName = constants.PaCPullRequestBranchPrefix + ChildComponentDef.componentName 1597 1598 for _, i := range components { 1599 println("creating branch " + i.componentBranch) 1600 err = f.AsKubeAdmin.CommonController.Github.CreateRef(i.repoName, i.baseBranch, i.baseRevision, i.componentBranch) 1601 Expect(err).ShouldNot(HaveOccurred()) 1602 } 1603 // Also setup a release namespace so we can test nudging of distribution repository images 1604 managedNamespace = testNamespace + "-managed" 1605 _, err = f.AsKubeAdmin.CommonController.CreateTestNamespace(managedNamespace) 1606 Expect(err).ShouldNot(HaveOccurred()) 1607 1608 // We just need the ReleaseAdmissionPlan to contain a mapping between component and distribution repositories 1609 data := struct { 1610 Mapping struct { 1611 Components []struct { 1612 Name string 1613 Repository string 1614 } 1615 } 1616 }{} 1617 data.Mapping.Components = append(data.Mapping.Components, struct { 1618 Name string 1619 Repository string 1620 }{Name: ParentComponentDef.componentName, Repository: distributionRepository}) 1621 rawData, err := json.Marshal(&data) 1622 1623 GinkgoWriter.Printf("ReleaseAdmissionPlan data: %s", string(rawData)) 1624 Expect(err).NotTo(HaveOccurred()) 1625 _, err = f.AsKubeAdmin.ReleaseController.CreateReleasePlanAdmission("demo", managedNamespace, "", f.UserNamespace, "demo", constants.DefaultPipelineServiceAccount, []string{applicationName}, false, &tektonutils.PipelineRef{ 1626 Resolver: "git", 1627 Params: []tektonutils.Param{ 1628 {Name: "url", Value: releasecommon.RelSvcCatalogURL}, 1629 {Name: "revision", Value: releasecommon.RelSvcCatalogRevision}, 1630 {Name: "pathInRepo", Value: "pipelines/e2e/e2e.yaml"}, 1631 }}, &runtime.RawExtension{Raw: rawData}) 1632 Expect(err).NotTo(HaveOccurred()) 1633 1634 }) 1635 1636 AfterAll(func() { 1637 if !CurrentSpecReport().Failed() { 1638 Expect(f.AsKubeAdmin.HasController.DeleteApplication(applicationName, testNamespace, false)).To(Succeed()) 1639 Expect(f.SandboxController.DeleteUserSignup(f.UserName)).To(BeTrue()) 1640 } 1641 Expect(f.AsKubeAdmin.CommonController.DeleteNamespace(managedNamespace)).ShouldNot(HaveOccurred()) 1642 1643 // Delete new branches created by renovate and a testing branch used as a component's base branch 1644 for _, c := range components { 1645 println("deleting branch " + c.componentBranch) 1646 err = f.AsKubeAdmin.CommonController.Github.DeleteRef(c.repoName, c.componentBranch) 1647 if err != nil { 1648 Expect(err.Error()).To(ContainSubstring("Reference does not exist")) 1649 } 1650 err = f.AsKubeAdmin.CommonController.Github.DeleteRef(c.repoName, c.pacBranchName) 1651 if err != nil { 1652 Expect(err.Error()).To(ContainSubstring("Reference does not exist")) 1653 } 1654 } 1655 }) 1656 1657 When("components are created in same namespace", func() { 1658 1659 It("creates component with nudges", func() { 1660 for _, comp := range components { 1661 componentObj := appservice.ComponentSpec{ 1662 ComponentName: comp.componentName, 1663 Application: applicationName, 1664 Source: appservice.ComponentSource{ 1665 ComponentSourceUnion: appservice.ComponentSourceUnion{ 1666 GitSource: &appservice.GitSource{ 1667 URL: comp.gitRepo, 1668 Revision: comp.componentBranch, 1669 DockerfileURL: "Dockerfile", 1670 }, 1671 }, 1672 }, 1673 } 1674 //make the parent repo nudge the child repo 1675 if comp.repoName == componentDependenciesParentRepoName { 1676 componentObj.BuildNudgesRef = []string{ChildComponentDef.componentName} 1677 comp.component, err = f.AsKubeAdmin.HasController.CreateComponent(componentObj, testNamespace, "", "", applicationName, true, utils.MergeMaps(constants.ComponentPaCRequestAnnotation, constants.ImageControllerAnnotationRequestPublicRepo)) 1678 } else { 1679 comp.component, err = f.AsKubeAdmin.HasController.CreateComponent(componentObj, testNamespace, "", "", applicationName, true, constants.ImageControllerAnnotationRequestPublicRepo) 1680 } 1681 Expect(err).ShouldNot(HaveOccurred()) 1682 } 1683 }) 1684 // Initial pipeline run, we need this so we have an initial image that we can then update 1685 It(fmt.Sprintf("triggers a PipelineRun for parent component %s", ParentComponentDef.componentName), func() { 1686 timeout = time.Minute * 5 1687 1688 Eventually(func() error { 1689 pr, err := f.AsKubeAdmin.HasController.GetComponentPipelineRun(ParentComponentDef.componentName, applicationName, testNamespace, "") 1690 if err != nil { 1691 GinkgoWriter.Printf("PipelineRun has not been created yet for the component %s/%s\n", testNamespace, ParentComponentDef.componentName) 1692 return err 1693 } 1694 if !pr.HasStarted() { 1695 return fmt.Errorf("pipelinerun %s/%s hasn't started yet", pr.GetNamespace(), pr.GetName()) 1696 } 1697 return nil 1698 }, timeout, constants.PipelineRunPollingInterval).Should(Succeed(), fmt.Sprintf("timed out when waiting for the PipelineRun to start for the component %s/%s", ParentComponentDef.componentName, testNamespace)) 1699 }) 1700 It(fmt.Sprintf("the PipelineRun should eventually finish successfully for parent component %s", ParentComponentDef.componentName), func() { 1701 Expect(f.AsKubeAdmin.HasController.WaitForComponentPipelineToBeFinished(ParentComponentDef.component, "", f.AsKubeAdmin.TektonController, &has.RetryOptions{Always: true, Retries: 2}, nil)).To(Succeed()) 1702 pr, err := f.AsKubeAdmin.HasController.GetComponentPipelineRun(ParentComponentDef.component.GetName(), ParentComponentDef.component.Spec.Application, ParentComponentDef.component.GetNamespace(), "") 1703 Expect(err).ShouldNot(HaveOccurred()) 1704 for _, result := range pr.Status.PipelineRunStatusFields.Results { 1705 if result.Name == "IMAGE_DIGEST" { 1706 parentFirstDigest = result.Value.StringVal 1707 } 1708 } 1709 Expect(parentFirstDigest).ShouldNot(BeEmpty()) 1710 }) 1711 // Now we have an initial image we create a dockerfile in the child that references this new image 1712 // This is the file that will be updated by the nudge 1713 It("create dockerfile and yaml manifest that references build and distribution repositorys", func() { 1714 1715 component, err := f.AsKubeAdmin.HasController.GetComponent(ParentComponentDef.componentName, testNamespace) 1716 Expect(err).ShouldNot(HaveOccurred(), "could not get component %s in the %s namespace", ParentComponentDef.componentName, testNamespace) 1717 1718 annotations := component.GetAnnotations() 1719 imageRepoName, err := build.GetQuayImageName(annotations) 1720 Expect(err).ShouldNot(HaveOccurred()) 1721 err = f.AsKubeAdmin.CommonController.Github.CreateRef(ChildComponentDef.repoName, ChildComponentDef.baseBranch, ChildComponentDef.baseRevision, ChildComponentDef.pacBranchName) 1722 Expect(err).ShouldNot(HaveOccurred()) 1723 parentImageNameWithNoDigest = "quay.io/" + quayOrg + "/" + imageRepoName 1724 _, err = f.AsKubeAdmin.CommonController.Github.CreateFile(ChildComponentDef.repoName, "Dockerfile.tmp", "FROM "+parentImageNameWithNoDigest+"@"+parentFirstDigest+"\nRUN echo hello\n", ChildComponentDef.pacBranchName) 1725 Expect(err).ShouldNot(HaveOccurred()) 1726 1727 _, err = f.AsKubeAdmin.CommonController.Github.CreateFile(ChildComponentDef.repoName, "manifest.yaml", "image: "+distributionRepository+"@"+parentFirstDigest, ChildComponentDef.pacBranchName) 1728 Expect(err).ShouldNot(HaveOccurred()) 1729 1730 _, err = f.AsKubeAdmin.CommonController.Github.CreatePullRequest(ChildComponentDef.repoName, "update to build repo image", "update to build repo image", ChildComponentDef.pacBranchName, ChildComponentDef.componentBranch) 1731 Expect(err).ShouldNot(HaveOccurred()) 1732 prs, err := f.AsKubeAdmin.CommonController.Github.ListPullRequests(ChildComponentDef.repoName) 1733 Expect(err).ShouldNot(HaveOccurred()) 1734 1735 prno := -1 1736 for _, pr := range prs { 1737 if pr.Head.GetRef() == ChildComponentDef.pacBranchName { 1738 prno = pr.GetNumber() 1739 } 1740 } 1741 Expect(prno).ShouldNot(Equal(-1)) 1742 _, err = f.AsKubeAdmin.CommonController.Github.MergePullRequest(ChildComponentDef.repoName, prno) 1743 Expect(err).ShouldNot(HaveOccurred()) 1744 1745 }) 1746 // This actually happens immediately, but we only need the PR number now 1747 It(fmt.Sprintf("should lead to a PaC PR creation for parent component %s", ParentComponentDef.componentName), func() { 1748 timeout = time.Second * 300 1749 interval := time.Second * 1 1750 1751 Eventually(func() bool { 1752 prs, err := f.AsKubeAdmin.CommonController.Github.ListPullRequests(ParentComponentDef.repoName) 1753 Expect(err).ShouldNot(HaveOccurred()) 1754 1755 for _, pr := range prs { 1756 if pr.Head.GetRef() == ParentComponentDef.pacBranchName { 1757 prNumber = pr.GetNumber() 1758 return true 1759 } 1760 } 1761 return false 1762 }, timeout, interval).Should(BeTrue(), fmt.Sprintf("timed out when waiting for PaC PR (branch name '%s') to be created in %s repository", ParentComponentDef.pacBranchName, ParentComponentDef.repoName)) 1763 }) 1764 It(fmt.Sprintf("Merging the PaC PR should be successful for parent component %s", ParentComponentDef.componentName), func() { 1765 Eventually(func() error { 1766 mergeResult, err = f.AsKubeAdmin.CommonController.Github.MergePullRequest(ParentComponentDef.repoName, prNumber) 1767 return err 1768 }, time.Minute).Should(BeNil(), fmt.Sprintf("error when merging PaC pull request #%d in repo %s", prNumber, ParentComponentDef.repoName)) 1769 1770 mergeResultSha = mergeResult.GetSHA() 1771 GinkgoWriter.Printf("merged result sha: %s for PR #%d\n", mergeResultSha, prNumber) 1772 1773 }) 1774 // Now the PR is merged this will kick off another build. The result of this build is what we want to update in dockerfile we created 1775 It(fmt.Sprintf("PR merge triggers PAC PipelineRun for parent component %s", ParentComponentDef.componentName), func() { 1776 timeout = time.Minute * 5 1777 1778 Eventually(func() error { 1779 pipelineRun, err := f.AsKubeAdmin.HasController.GetComponentPipelineRun(ParentComponentDef.componentName, applicationName, testNamespace, mergeResultSha) 1780 if err != nil { 1781 GinkgoWriter.Printf("Push PipelineRun has not been created yet for the component %s/%s\n", testNamespace, ParentComponentDef.componentName) 1782 return err 1783 } 1784 if !pipelineRun.HasStarted() { 1785 return fmt.Errorf("push pipelinerun %s/%s hasn't started yet", pipelineRun.GetNamespace(), pipelineRun.GetName()) 1786 } 1787 return nil 1788 }, timeout, constants.PipelineRunPollingInterval).Should(Succeed(), fmt.Sprintf("timed out when waiting for the PipelineRun to start for the component %s/%s", testNamespace, ParentComponentDef.componentName)) 1789 }) 1790 // Wait for this PR to be done and store the digest, we will need it to verify that the nudge was correct 1791 It(fmt.Sprintf("PAC PipelineRun for parent component %s is successful", ParentComponentDef.componentName), func() { 1792 pr := &pipeline.PipelineRun{} 1793 Expect(f.AsKubeAdmin.HasController.WaitForComponentPipelineToBeFinished(ParentComponentDef.component, mergeResultSha, f.AsKubeAdmin.TektonController, &has.RetryOptions{Always: true, Retries: 2}, pr)).To(Succeed()) 1794 1795 for _, result := range pr.Status.PipelineRunStatusFields.Results { 1796 if result.Name == "IMAGE_DIGEST" { 1797 parentPostPacMergeDigest = result.Value.StringVal 1798 } 1799 } 1800 Expect(parentPostPacMergeDigest).ShouldNot(BeEmpty()) 1801 }) 1802 It(fmt.Sprintf("should lead to a nudge PR creation for child component %s", ChildComponentDef.componentName), func() { 1803 timeout = time.Minute * 20 1804 interval := time.Second * 1 1805 1806 Eventually(func() bool { 1807 prs, err := f.AsKubeAdmin.CommonController.Github.ListPullRequests(componentDependenciesChildRepoName) 1808 Expect(err).ShouldNot(HaveOccurred()) 1809 1810 for _, pr := range prs { 1811 if strings.Contains(pr.Head.GetRef(), ParentComponentDef.componentName) { 1812 prNumber = pr.GetNumber() 1813 return true 1814 } 1815 } 1816 return false 1817 }, timeout, interval).Should(BeTrue(), fmt.Sprintf("timed out when waiting for component nudge PR to be created in %s repository", componentDependenciesChildRepoName)) 1818 }) 1819 It(fmt.Sprintf("merging the PR should be successful for child component %s", ChildComponentDef.componentName), func() { 1820 Eventually(func() error { 1821 mergeResult, err = f.AsKubeAdmin.CommonController.Github.MergePullRequest(componentDependenciesChildRepoName, prNumber) 1822 return err 1823 }, time.Minute).Should(BeNil(), fmt.Sprintf("error when merging nudge pull request #%d in repo %s", prNumber, componentDependenciesChildRepoName)) 1824 1825 mergeResultSha = mergeResult.GetSHA() 1826 GinkgoWriter.Printf("merged result sha: %s for PR #%d\n", mergeResultSha, prNumber) 1827 1828 }) 1829 // Now the nudge has been merged we verify the dockerfile is what we expected 1830 It("Verify the nudge updated the contents", func() { 1831 1832 GinkgoWriter.Printf("Verifying Dockerfile.tmp updated to sha %s", parentPostPacMergeDigest) 1833 component, err := f.AsKubeAdmin.HasController.GetComponent(ParentComponentDef.componentName, testNamespace) 1834 Expect(err).ShouldNot(HaveOccurred(), "could not get component %s in the %s namespace", ParentComponentDef.componentName, testNamespace) 1835 1836 annotations := component.GetAnnotations() 1837 imageRepoName, err := build.GetQuayImageName(annotations) 1838 Expect(err).ShouldNot(HaveOccurred()) 1839 contents, err := f.AsKubeAdmin.CommonController.Github.GetFile(ChildComponentDef.repoName, "Dockerfile.tmp", ChildComponentDef.componentBranch) 1840 Expect(err).ShouldNot(HaveOccurred()) 1841 content, err := contents.GetContent() 1842 Expect(err).ShouldNot(HaveOccurred()) 1843 Expect(content).Should(Equal("FROM quay.io/" + quayOrg + "/" + imageRepoName + "@" + parentPostPacMergeDigest + "\nRUN echo hello\n")) 1844 1845 contents, err = f.AsKubeAdmin.CommonController.Github.GetFile(ChildComponentDef.repoName, "manifest.yaml", ChildComponentDef.componentBranch) 1846 Expect(err).ShouldNot(HaveOccurred()) 1847 content, err = contents.GetContent() 1848 Expect(err).ShouldNot(HaveOccurred()) 1849 Expect(content).Should(Equal("image: " + distributionRepository + "@" + parentPostPacMergeDigest)) 1850 1851 }) 1852 }) 1853 1854 }) 1855 1856 }) 1857 1858 func createBuildSecret(f *framework.Framework, secretName string, annotations map[string]string, token string) error { 1859 buildSecret := v1.Secret{} 1860 buildSecret.Name = secretName 1861 buildSecret.Labels = map[string]string{ 1862 "appstudio.redhat.com/credentials": "scm", 1863 "appstudio.redhat.com/scm.host": "github.com", 1864 } 1865 if annotations != nil { 1866 buildSecret.Annotations = annotations 1867 } 1868 buildSecret.Type = "kubernetes.io/basic-auth" 1869 buildSecret.StringData = map[string]string{ 1870 "password": token, 1871 } 1872 _, err := f.AsKubeAdmin.CommonController.CreateSecret(f.UserNamespace, &buildSecret) 1873 if err != nil { 1874 return fmt.Errorf("error creating build secret: %v", err) 1875 } 1876 return nil 1877 } 1878 1879 func cleanupWebhooks(f *framework.Framework, repoName string) { 1880 hooks, err := f.AsKubeAdmin.CommonController.Github.ListRepoWebhooks(repoName) 1881 Expect(err).NotTo(HaveOccurred()) 1882 for _, h := range hooks { 1883 hookUrl := h.Config["url"].(string) 1884 if strings.Contains(hookUrl, f.ClusterAppDomain) { 1885 GinkgoWriter.Printf("removing webhook URL: %s\n", hookUrl) 1886 Expect(f.AsKubeAdmin.CommonController.Github.DeleteWebhook(repoName, h.GetID())).To(Succeed()) 1887 break 1888 } 1889 } 1890 }