github.com/redhat-appstudio/e2e-tests@v0.0.0-20240520140907-9709f6f59323/tests/release/pipelines/release_to_github.go (about) 1 package pipelines 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "strings" 7 "time" 8 9 "github.com/devfile/library/v2/pkg/util" 10 ecp "github.com/enterprise-contract/enterprise-contract-controller/api/v1alpha1" 11 . "github.com/onsi/ginkgo/v2" 12 . "github.com/onsi/gomega" 13 appservice "github.com/redhat-appstudio/application-api/api/v1alpha1" 14 "github.com/redhat-appstudio/e2e-tests/pkg/clients/github" 15 "github.com/redhat-appstudio/e2e-tests/pkg/clients/has" 16 "github.com/redhat-appstudio/e2e-tests/pkg/constants" 17 "github.com/redhat-appstudio/e2e-tests/pkg/framework" 18 "github.com/redhat-appstudio/e2e-tests/pkg/utils" 19 "github.com/redhat-appstudio/e2e-tests/pkg/utils/tekton" 20 releasecommon "github.com/redhat-appstudio/e2e-tests/tests/release" 21 releaseapi "github.com/redhat-appstudio/release-service/api/v1alpha1" 22 tektonutils "github.com/redhat-appstudio/release-service/tekton/utils" 23 tektonv1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1" 24 corev1 "k8s.io/api/core/v1" 25 "k8s.io/apimachinery/pkg/api/errors" 26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 "k8s.io/apimachinery/pkg/runtime" 28 ) 29 30 const ( 31 sampServiceAccountName = "release-service-account" 32 sampSourceGitURL = "https://github.com/redhat-appstudio-qe/devfile-sample-go-basic" 33 sampReleaseURL = "https://github.com/redhat-appstudio-qe/devfile-sample-go-basic/releases/tag/v2.1" 34 sampRepoOwner = "redhat-appstudio-qe" 35 sampRepo = "devfile-sample-go-basic" 36 sampCatalogPathInRepo = "pipelines/release-to-github/release-to-github.yaml" 37 ) 38 39 var _ = framework.ReleasePipelinesSuiteDescribe("e2e tests for release-to-github pipeline", Label("release-pipelines", "release-to-github"), func() { 40 defer GinkgoRecover() 41 42 var devWorkspace = utils.GetEnv(constants.RELEASE_DEV_WORKSPACE_ENV, constants.DevReleaseTeam) 43 var managedWorkspace = utils.GetEnv(constants.RELEASE_MANAGED_WORKSPACE_ENV, constants.ManagedReleaseTeam) 44 45 var devNamespace = devWorkspace + "-tenant" 46 var managedNamespace = managedWorkspace + "-tenant" 47 48 var err error 49 var devFw *framework.Framework 50 var managedFw *framework.Framework 51 var sampApplicationName = "samp-app-" + util.GenerateRandomString(4) 52 var sampComponentName = "samp-comp-" + util.GenerateRandomString(4) 53 var sampReleasePlanName = "samp-rp-" + util.GenerateRandomString(4) 54 var sampReleasePlanAdmissionName = "samp-rpa-" + util.GenerateRandomString(4) 55 var sampEnterpriseContractPolicyName = "samp-policy-" + util.GenerateRandomString(4) 56 57 var snapshot *appservice.Snapshot 58 var releaseCR *releaseapi.Release 59 var releasePR, buildPR *tektonv1.PipelineRun 60 var gh *github.Github 61 62 AfterEach(framework.ReportFailure(&devFw)) 63 64 Describe("Release-to-github happy path", Label("releaseToGithub"), func() { 65 var component *appservice.Component 66 BeforeAll(func() { 67 devFw = releasecommon.NewFramework(devWorkspace) 68 managedFw = releasecommon.NewFramework(managedWorkspace) 69 70 managedNamespace = managedFw.UserNamespace 71 72 // Linking the build secret to the pipeline service account in dev namespace. 73 err = devFw.AsKubeAdmin.CommonController.LinkSecretToServiceAccount(devNamespace, releasecommon.HacbsReleaseTestsTokenSecret, constants.DefaultPipelineServiceAccount, true) 74 Expect(err).ToNot(HaveOccurred()) 75 76 githubUser := utils.GetEnv("GITHUB_USER", "redhat-appstudio-qe-bot") 77 githubToken := utils.GetEnv(constants.GITHUB_TOKEN_ENV, "") 78 gh, err = github.NewGithubClient(githubToken, githubUser) 79 Expect(githubToken).ToNot(BeEmpty()) 80 81 // Remove the release if the release exists 82 if gh.CheckIfReleaseExist(sampRepoOwner, sampRepo, sampReleaseURL) { 83 gh.DeleteRelease(sampRepoOwner, sampRepo, sampReleaseURL) 84 } 85 86 _, err = managedFw.AsKubeAdmin.CommonController.GetSecret(managedNamespace, releasecommon.RedhatAppstudioQESecret) 87 if errors.IsNotFound(err) { 88 githubSecret := &corev1.Secret{ 89 ObjectMeta: metav1.ObjectMeta{ 90 Name: releasecommon.RedhatAppstudioQESecret, 91 Namespace: managedNamespace, 92 }, 93 Type: corev1.SecretTypeOpaque, 94 Data: map[string][]byte{ 95 "token": []byte(githubToken), 96 }, 97 } 98 _, err = managedFw.AsKubeAdmin.CommonController.CreateSecret(managedNamespace, githubSecret) 99 Expect(err).ToNot(HaveOccurred()) 100 } 101 Expect(err).ToNot(HaveOccurred()) 102 103 err = managedFw.AsKubeAdmin.CommonController.LinkSecretToServiceAccount(managedNamespace, releasecommon.RedhatAppstudioQESecret, constants.DefaultPipelineServiceAccount, true) 104 Expect(err).ToNot(HaveOccurred()) 105 106 _, err = devFw.AsKubeDeveloper.HasController.CreateApplication(sampApplicationName, devNamespace) 107 Expect(err).NotTo(HaveOccurred()) 108 109 _, err = devFw.AsKubeDeveloper.ReleaseController.CreateReleasePlan(sampReleasePlanName, devNamespace, sampApplicationName, managedNamespace, "true", nil) 110 Expect(err).NotTo(HaveOccurred()) 111 112 createGHReleasePlanAdmission(sampReleasePlanAdmissionName, *managedFw, devNamespace, managedNamespace, sampApplicationName, sampEnterpriseContractPolicyName, sampCatalogPathInRepo, "false", "", "", "", "") 113 component = releasecommon.CreateComponentByCDQ(*devFw, devNamespace, managedNamespace, sampApplicationName, sampComponentName, sampSourceGitURL) 114 createGHEnterpriseContractPolicy(sampEnterpriseContractPolicyName, *managedFw, devNamespace, managedNamespace) 115 }) 116 117 AfterAll(func() { 118 devFw = releasecommon.NewFramework(devWorkspace) 119 managedFw = releasecommon.NewFramework(managedWorkspace) 120 Expect(devFw.AsKubeDeveloper.HasController.DeleteApplication(sampApplicationName, devNamespace, false)).NotTo(HaveOccurred()) 121 Expect(managedFw.AsKubeDeveloper.TektonController.DeleteEnterpriseContractPolicy(sampEnterpriseContractPolicyName, managedNamespace, false)).NotTo(HaveOccurred()) 122 Expect(managedFw.AsKubeDeveloper.ReleaseController.DeleteReleasePlanAdmission(sampReleasePlanAdmissionName, managedNamespace, false)).NotTo(HaveOccurred()) 123 }) 124 125 var _ = Describe("Post-release verification", func() { 126 It("verifies that a build PipelineRun is created in dev namespace and succeeds", func() { 127 devFw = releasecommon.NewFramework(devWorkspace) 128 managedFw = releasecommon.NewFramework(managedWorkspace) 129 // Create a ticker that ticks every 3 minutes 130 ticker := time.NewTicker(3 * time.Minute) 131 // Schedule the stop of the ticker after 15 minutes 132 time.AfterFunc(15*time.Minute, func() { 133 ticker.Stop() 134 fmt.Println("Stopped executing every 3 minutes.") 135 }) 136 // Run a goroutine to handle the ticker ticks 137 go func() { 138 for range ticker.C { 139 devFw = releasecommon.NewFramework(devWorkspace) 140 managedFw = releasecommon.NewFramework(managedWorkspace) 141 } 142 }() 143 Eventually(func() error { 144 buildPR, err = devFw.AsKubeDeveloper.HasController.GetComponentPipelineRun(component.Name, sampApplicationName, devNamespace, "") 145 if err != nil { 146 return err 147 } 148 if !buildPR.IsDone() { 149 return fmt.Errorf("build pipelinerun %s in namespace %s did not finish yet", buildPR.Name, buildPR.Namespace) 150 } 151 Expect(tekton.HasPipelineRunSucceeded(buildPR)).To(BeTrue(), fmt.Sprintf("build pipelinerun %s/%s did not succeed", buildPR.GetNamespace(), buildPR.GetName())) 152 snapshot, err = devFw.AsKubeDeveloper.IntegrationController.GetSnapshot("", buildPR.Name, "", devNamespace) 153 if err != nil { 154 return err 155 } 156 return nil 157 }, releasecommon.BuildPipelineRunCompletionTimeout, releasecommon.DefaultInterval).Should(Succeed(), "timed out when waiting for build pipelinerun to be created") 158 Expect(devFw.AsKubeDeveloper.HasController.WaitForComponentPipelineToBeFinished(component, "", devFw.AsKubeDeveloper.TektonController, &has.RetryOptions{Retries: 3, Always: true}, nil)).To(Succeed()) 159 }) 160 It("verifies release pipelinerun is running and succeeds", func() { 161 devFw = releasecommon.NewFramework(devWorkspace) 162 managedFw = releasecommon.NewFramework(managedWorkspace) 163 164 releaseCR, err = devFw.AsKubeDeveloper.ReleaseController.GetRelease("", snapshot.Name, devNamespace) 165 Expect(err).ShouldNot(HaveOccurred()) 166 Eventually(func() error { 167 releasePR, err = managedFw.AsKubeAdmin.ReleaseController.GetPipelineRunInNamespace(managedFw.UserNamespace, releaseCR.GetName(), releaseCR.GetNamespace()) 168 if err != nil { 169 return err 170 } 171 GinkgoWriter.Println("Release PR: ", releasePR.Name) 172 if !releasePR.IsDone() { 173 return fmt.Errorf("release pipelinerun %s in namespace %s did not finished yet", releasePR.Name, releasePR.Namespace) 174 } 175 return nil 176 }, releasecommon.ReleasePipelineRunCompletionTimeout, releasecommon.DefaultInterval).Should(Succeed(), "timed out when waiting for release pipelinerun to succeed") 177 Expect(tekton.HasPipelineRunSucceeded(releasePR)).To(BeTrue(), fmt.Sprintf("release pipelinerun %s/%s did not succeed", releasePR.GetNamespace(), releasePR.GetName())) 178 }) 179 180 It("verifies release CR completed and set succeeded.", func() { 181 devFw = releasecommon.NewFramework(devWorkspace) 182 Eventually(func() error { 183 releaseCr, err := devFw.AsKubeDeveloper.ReleaseController.GetRelease("", snapshot.Name, devNamespace) 184 if err != nil { 185 return err 186 } 187 GinkgoWriter.Println("Release CR: ", releaseCr.Name) 188 if !releaseCr.IsReleased() { 189 return fmt.Errorf("release %s/%s is not marked as finished yet", releaseCR.GetNamespace(), releaseCR.GetName()) 190 } 191 return nil 192 }, 10*time.Minute, releasecommon.DefaultInterval).Should(Succeed()) 193 }) 194 195 It("verifies if the Release exists in github repo", func() { 196 managedFw = releasecommon.NewFramework(managedWorkspace) 197 trReleasePr, err := managedFw.AsKubeAdmin.TektonController.GetTaskRunStatus(managedFw.AsKubeAdmin.CommonController.KubeRest(), releasePR, "create-github-release") 198 Expect(err).NotTo(HaveOccurred()) 199 trReleaseURL := trReleasePr.Status.TaskRunStatusFields.Results[0].Value.StringVal 200 releaseURL := strings.Replace(trReleaseURL, "\n", "", -1) 201 Expect(gh.CheckIfReleaseExist(sampRepoOwner, sampRepo, releaseURL)).To(BeTrue(), fmt.Sprintf("release %s doesn't exist", releaseURL)) 202 }) 203 }) 204 }) 205 }) 206 207 func createGHEnterpriseContractPolicy(sampECPName string, managedFw framework.Framework, devNamespace, managedNamespace string) { 208 defaultEcPolicySpec := ecp.EnterpriseContractPolicySpec{ 209 Description: "Red Hat's enterprise requirements", 210 PublicKey: "k8s://openshift-pipelines/public-key", 211 Sources: []ecp.Source{{ 212 Name: "Default", 213 Policy: []string{releasecommon.EcPolicyLibPath, releasecommon.EcPolicyReleasePath}, 214 Data: []string{releasecommon.EcPolicyDataBundle, releasecommon.EcPolicyDataPath}, 215 }}, 216 Configuration: &ecp.EnterpriseContractPolicyConfiguration{ 217 Exclude: []string{"cve", "step_image_registries", "tasks.required_tasks_found:prefetch-dependencies"}, 218 Include: []string{"minimal", "slsa3"}, 219 }, 220 } 221 222 _, err := managedFw.AsKubeDeveloper.TektonController.CreateEnterpriseContractPolicy(sampECPName, managedNamespace, defaultEcPolicySpec) 223 Expect(err).NotTo(HaveOccurred()) 224 225 } 226 227 func createGHReleasePlanAdmission(sampRPAName string, managedFw framework.Framework, devNamespace, managedNamespace, sampAppName, sampECPName, pathInRepoValue, hotfix, issueId, preGA, productName, productVersion string) { 228 var err error 229 230 data, err := json.Marshal(map[string]interface{}{ 231 "github": map[string]interface{}{ 232 "githubSecret": releasecommon.RedhatAppstudioQESecret, 233 }, 234 "sign": map[string]interface{}{ 235 "configMapName": "hacbs-signing-pipeline-config-redhatbeta2", 236 }, 237 }) 238 Expect(err).NotTo(HaveOccurred()) 239 240 _, err = managedFw.AsKubeAdmin.ReleaseController.CreateReleasePlanAdmission(sampRPAName, managedNamespace, "", devNamespace, sampECPName, sampServiceAccountName, []string{sampAppName}, true, &tektonutils.PipelineRef{ 241 Resolver: "git", 242 Params: []tektonutils.Param{ 243 {Name: "url", Value: releasecommon.RelSvcCatalogURL}, 244 {Name: "revision", Value: releasecommon.RelSvcCatalogRevision}, 245 {Name: "pathInRepo", Value: pathInRepoValue}, 246 }, 247 }, &runtime.RawExtension{ 248 Raw: data, 249 }) 250 Expect(err).NotTo(HaveOccurred()) 251 }