github.com/redhat-appstudio/e2e-tests@v0.0.0-20240520140907-9709f6f59323/tests/integration-service/status-reporting-to-pullrequest.go (about) 1 package integration 2 3 import ( 4 "fmt" 5 "os" 6 "strings" 7 "time" 8 9 "github.com/devfile/library/v2/pkg/util" 10 "github.com/google/go-github/v44/github" 11 "github.com/redhat-appstudio/e2e-tests/pkg/clients/has" 12 "github.com/redhat-appstudio/e2e-tests/pkg/constants" 13 "github.com/redhat-appstudio/e2e-tests/pkg/framework" 14 "github.com/redhat-appstudio/e2e-tests/pkg/utils" 15 16 integrationv1beta1 "github.com/konflux-ci/integration-service/api/v1beta1" 17 . "github.com/onsi/ginkgo/v2" 18 . "github.com/onsi/gomega" 19 appstudioApi "github.com/redhat-appstudio/application-api/api/v1alpha1" 20 pipeline "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1" 21 ) 22 23 var _ = framework.IntegrationServiceSuiteDescribe("Status Reporting of Integration tests", Label("integration-service", "HACBS", "status-reporting"), func() { 24 defer GinkgoRecover() 25 26 var f *framework.Framework 27 var err error 28 29 var prNumber int 30 var timeout, interval time.Duration 31 var prHeadSha string 32 var snapshot *appstudioApi.Snapshot 33 var component *appstudioApi.Component 34 var pipelineRun, testPipelinerun *pipeline.PipelineRun 35 var integrationTestScenarioPass, integrationTestScenarioFail *integrationv1beta1.IntegrationTestScenario 36 var applicationName, componentName, componentBaseBranchName, pacBranchName, testNamespace string 37 38 AfterEach(framework.ReportFailure(&f)) 39 40 Describe("with status reporting of Integration tests in CheckRuns", Ordered, func() { 41 BeforeAll(func() { 42 if os.Getenv(constants.SKIP_PAC_TESTS_ENV) == "true" { 43 Skip("Skipping this test due to configuration issue with Spray proxy") 44 } 45 46 f, err = framework.NewFramework(utils.GetGeneratedNamespace("stat-rep")) 47 Expect(err).NotTo(HaveOccurred()) 48 testNamespace = f.UserNamespace 49 50 if utils.IsPrivateHostname(f.OpenshiftConsoleHost) { 51 Skip("Using private cluster (not reachable from Github), skipping...") 52 } 53 54 applicationName = createApp(*f, testNamespace) 55 56 integrationTestScenarioPass, err = f.AsKubeAdmin.IntegrationController.CreateIntegrationTestScenario("", applicationName, testNamespace, gitURL, revision, pathInRepoPass) 57 Expect(err).ShouldNot(HaveOccurred()) 58 59 integrationTestScenarioFail, err = f.AsKubeAdmin.IntegrationController.CreateIntegrationTestScenario("", applicationName, testNamespace, gitURL, revision, pathInRepoFail) 60 Expect(err).ShouldNot(HaveOccurred()) 61 62 componentName = fmt.Sprintf("%s-%s", "test-component-pac", util.GenerateRandomString(6)) 63 pacBranchName = constants.PaCPullRequestBranchPrefix + componentName 64 componentBaseBranchName = fmt.Sprintf("base-%s", util.GenerateRandomString(6)) 65 66 err = f.AsKubeAdmin.CommonController.Github.CreateRef(componentRepoNameForStatusReporting, componentDefaultBranch, componentRevision, componentBaseBranchName) 67 Expect(err).ShouldNot(HaveOccurred()) 68 }) 69 70 AfterAll(func() { 71 if !CurrentSpecReport().Failed() { 72 cleanup(*f, testNamespace, applicationName, componentName) 73 } 74 75 // Delete new branches created by PaC and a testing branch used as a component's base branch 76 err = f.AsKubeAdmin.CommonController.Github.DeleteRef(componentRepoNameForStatusReporting, pacBranchName) 77 if err != nil { 78 Expect(err.Error()).To(ContainSubstring(referenceDoesntExist)) 79 } 80 err = f.AsKubeAdmin.CommonController.Github.DeleteRef(componentRepoNameForStatusReporting, componentBaseBranchName) 81 if err != nil { 82 Expect(err.Error()).To(ContainSubstring(referenceDoesntExist)) 83 } 84 }) 85 86 When("a new Component with specified custom branch is created", Label("custom-branch"), func() { 87 BeforeAll(func() { 88 componentObj := appstudioApi.ComponentSpec{ 89 ComponentName: componentName, 90 Application: applicationName, 91 Source: appstudioApi.ComponentSource{ 92 ComponentSourceUnion: appstudioApi.ComponentSourceUnion{ 93 GitSource: &appstudioApi.GitSource{ 94 URL: componentGitSourceURLForStatusReporting, 95 Revision: componentBaseBranchName, 96 }, 97 }, 98 }, 99 } 100 // Create a component with Git Source URL, a specified git branch 101 component, err = f.AsKubeAdmin.HasController.CreateComponent(componentObj, testNamespace, "", "", applicationName, false, utils.MergeMaps(constants.ComponentPaCRequestAnnotation, constants.ImageControllerAnnotationRequestPublicRepo)) 102 Expect(err).ShouldNot(HaveOccurred()) 103 }) 104 It("triggers a Build PipelineRun", func() { 105 timeout = time.Second * 600 106 interval = time.Second * 1 107 Eventually(func() error { 108 pipelineRun, err = f.AsKubeAdmin.HasController.GetComponentPipelineRun(componentName, applicationName, testNamespace, "") 109 if err != nil { 110 GinkgoWriter.Printf("Build PipelineRun has not been created yet for the component %s/%s\n", testNamespace, componentName) 111 return err 112 } 113 if !pipelineRun.HasStarted() { 114 return fmt.Errorf("build pipelinerun %s/%s hasn't started yet", pipelineRun.GetNamespace(), pipelineRun.GetName()) 115 } 116 return nil 117 }, timeout, constants.PipelineRunPollingInterval).Should(Succeed(), fmt.Sprintf("timed out when waiting for the build PipelineRun to start for the component %s/%s", testNamespace, componentName)) 118 }) 119 It("does not contain an annotation with a Snapshot Name", func() { 120 Expect(pipelineRun.Annotations[snapshotAnnotation]).To(Equal("")) 121 }) 122 It("should lead to build PipelineRun finishing successfully", func() { 123 Expect(f.AsKubeAdmin.HasController.WaitForComponentPipelineToBeFinished(component, 124 "", f.AsKubeAdmin.TektonController, &has.RetryOptions{Retries: 2, Always: true}, pipelineRun)).To(Succeed()) 125 }) 126 It("should have a related PaC init PR created", func() { 127 timeout = time.Second * 300 128 interval = time.Second * 1 129 130 Eventually(func() bool { 131 prs, err := f.AsKubeAdmin.CommonController.Github.ListPullRequests(componentRepoNameForStatusReporting) 132 Expect(err).ShouldNot(HaveOccurred()) 133 134 for _, pr := range prs { 135 if pr.Head.GetRef() == pacBranchName { 136 prNumber = pr.GetNumber() 137 prHeadSha = pr.Head.GetSHA() 138 return true 139 } 140 } 141 return false 142 }, timeout, interval).Should(BeTrue(), fmt.Sprintf("timed out when waiting for init PaC PR (branch name '%s') to be created in %s repository", pacBranchName, componentRepoNameForStatusReporting)) 143 144 // in case the first pipelineRun attempt has failed and was retried, we need to update the value of pipelineRun variable 145 pipelineRun, err = f.AsKubeAdmin.HasController.GetComponentPipelineRun(componentName, applicationName, testNamespace, prHeadSha) 146 Expect(err).ShouldNot(HaveOccurred()) 147 }) 148 149 It("eventually leads to the build PipelineRun's status reported at Checks tab", func() { 150 expectedCheckRunName := fmt.Sprintf("%s-%s", componentName, "on-pull-request") 151 validateCheckRun(*f, expectedCheckRunName, checkrunConclusionSuccess, componentRepoNameForStatusReporting, prHeadSha, prNumber) 152 }) 153 }) 154 155 When("the PaC build pipelineRun run succeeded", func() { 156 It("checks if the BuildPipelineRun have the annotation of chains signed", func() { 157 Expect(f.AsKubeDeveloper.IntegrationController.WaitForBuildPipelineRunToGetAnnotated(testNamespace, applicationName, componentName, chainsSignedAnnotation)).To(Succeed()) 158 }) 159 160 It("checks if the Snapshot is created", func() { 161 snapshot, err = f.AsKubeDeveloper.IntegrationController.WaitForSnapshotToGetCreated("", "", componentName, testNamespace) 162 Expect(err).ToNot(HaveOccurred()) 163 }) 164 165 It("checks if the Build PipelineRun got annotated with Snapshot name", func() { 166 Expect(f.AsKubeDeveloper.IntegrationController.WaitForBuildPipelineRunToGetAnnotated(testNamespace, applicationName, componentName, snapshotAnnotation)).To(Succeed()) 167 }) 168 }) 169 170 When("the Snapshot was created", func() { 171 It("should find both the related Integration PipelineRuns", func() { 172 testPipelinerun, err = f.AsKubeDeveloper.IntegrationController.WaitForIntegrationPipelineToGetStarted(integrationTestScenarioPass.Name, snapshot.Name, testNamespace) 173 Expect(err).ToNot(HaveOccurred()) 174 Expect(testPipelinerun.Labels[snapshotAnnotation]).To(ContainSubstring(snapshot.Name)) 175 Expect(testPipelinerun.Labels[scenarioAnnotation]).To(ContainSubstring(integrationTestScenarioPass.Name)) 176 177 testPipelinerun, err = f.AsKubeDeveloper.IntegrationController.WaitForIntegrationPipelineToGetStarted(integrationTestScenarioFail.Name, snapshot.Name, testNamespace) 178 Expect(err).ToNot(HaveOccurred()) 179 Expect(testPipelinerun.Labels[snapshotAnnotation]).To(ContainSubstring(snapshot.Name)) 180 Expect(testPipelinerun.Labels[scenarioAnnotation]).To(ContainSubstring(integrationTestScenarioFail.Name)) 181 }) 182 }) 183 184 When("Integration PipelineRuns are created", func() { 185 It("should eventually complete successfully", func() { 186 Expect(f.AsKubeAdmin.IntegrationController.WaitForIntegrationPipelineToBeFinished(integrationTestScenarioPass, snapshot, testNamespace)).To(Succeed(), fmt.Sprintf("Error when waiting for an integration pipelinerun for snapshot %s/%s to finish", testNamespace, snapshot.GetName())) 187 Expect(f.AsKubeAdmin.IntegrationController.WaitForIntegrationPipelineToBeFinished(integrationTestScenarioFail, snapshot, testNamespace)).To(Succeed(), fmt.Sprintf("Error when waiting for an integration pipelinerun for snapshot %s/%s to finish", testNamespace, snapshot.GetName())) 188 }) 189 }) 190 191 When("Integration PipelineRuns completes successfully", func() { 192 It("should lead to Snapshot CR being marked as failed", FlakeAttempts(3), func() { 193 // Snapshot marked as Failed because one of its Integration test failed (as expected) 194 Eventually(func() bool { 195 snapshot, err = f.AsKubeAdmin.IntegrationController.GetSnapshot("", pipelineRun.Name, "", testNamespace) 196 return err == nil && !f.AsKubeAdmin.CommonController.HaveTestsSucceeded(snapshot) 197 }, time.Minute*3, time.Second*5).Should(BeTrue(), fmt.Sprintf("Timed out waiting for Snapshot to be marked as failed %s/%s", snapshot.GetNamespace(), snapshot.GetName())) 198 }) 199 It("eventually leads to the status reported at Checks tab for the successful Integration PipelineRun", func() { 200 validateCheckRun(*f, integrationTestScenarioPass.Name, checkrunConclusionSuccess, componentRepoNameForStatusReporting, prHeadSha, prNumber) 201 }) 202 It("eventually leads to the status reported at Checks tab for the failed Integration PipelineRun", func() { 203 validateCheckRun(*f, integrationTestScenarioFail.Name, checkrunConclusionFailure, componentRepoNameForStatusReporting, prHeadSha, prNumber) 204 }) 205 }) 206 }) 207 }) 208 209 // validateCheckRun fetches a specific CheckRun within a given repo 210 // by matching the CheckRun's name with the given checkRunName, and 211 // then validates that it got completed and its conclusion is as expected 212 func validateCheckRun(f framework.Framework, checkRunName, conclusion, repoName, prHeadSha string, prNumber int) { 213 var checkRun *github.CheckRun 214 var timeout, interval time.Duration 215 var err error 216 217 timeout = time.Minute * 10 218 interval = time.Second * 2 219 220 Eventually(func() *github.CheckRun { 221 checkRuns, err := f.AsKubeAdmin.CommonController.Github.ListCheckRuns(repoName, prHeadSha) 222 Expect(err).ShouldNot(HaveOccurred()) 223 for _, cr := range checkRuns { 224 if strings.Contains(cr.GetName(), checkRunName) { 225 checkRun = cr 226 return cr 227 } 228 } 229 return nil 230 }, timeout, interval).ShouldNot(BeNil(), fmt.Sprintf("timed out when waiting for the PaC CheckRun, with `Name` field containing the substring %s, to appear in the PR #%d of the Component repo %s", checkRunName, prNumber, repoName)) 231 232 Eventually(func() string { 233 checkRun, err = f.AsKubeAdmin.CommonController.Github.GetCheckRun(repoName, checkRun.GetID()) 234 Expect(err).ShouldNot(HaveOccurred()) 235 return checkRun.GetStatus() 236 }, timeout, interval).Should(Equal(checkrunStatusCompleted), fmt.Sprintf("timed out when waiting for the PaC Check suite status to be 'completed' in the Component repo %s in PR #%d", repoName, prNumber)) 237 Expect(checkRun.GetConclusion()).To(Equal(conclusion), fmt.Sprintf("the PR %d in %s repo doesn't contain the expected conclusion (%s) of the CheckRun", prNumber, repoName, conclusion)) 238 }