github.com/redhat-appstudio/e2e-tests@v0.0.0-20240520140907-9709f6f59323/tests/release/pipelines/rh_push_to_redhat_io.go (about) 1 package pipelines 2 3 import ( 4 "encoding/base64" 5 "encoding/json" 6 "fmt" 7 "os" 8 "regexp" 9 "time" 10 11 "github.com/devfile/library/v2/pkg/util" 12 ecp "github.com/enterprise-contract/enterprise-contract-controller/api/v1alpha1" 13 . "github.com/onsi/ginkgo/v2" 14 . "github.com/onsi/gomega" 15 appservice "github.com/redhat-appstudio/application-api/api/v1alpha1" 16 "github.com/redhat-appstudio/e2e-tests/pkg/clients/has" 17 "github.com/redhat-appstudio/e2e-tests/pkg/constants" 18 "github.com/redhat-appstudio/e2e-tests/pkg/framework" 19 "github.com/redhat-appstudio/e2e-tests/pkg/utils" 20 "github.com/redhat-appstudio/e2e-tests/pkg/utils/tekton" 21 tektonv1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1" 22 releaseapi "github.com/redhat-appstudio/release-service/api/v1alpha1" 23 releasecommon "github.com/redhat-appstudio/e2e-tests/tests/release" 24 tektonutils "github.com/redhat-appstudio/release-service/tekton/utils" 25 "k8s.io/apimachinery/pkg/runtime" 26 corev1 "k8s.io/api/core/v1" 27 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 28 ) 29 30 const ( 31 rhioServiceAccountName = "release-service-account" 32 rhioCatalogPathInRepo = "pipelines/rh-push-to-registry-redhat-io/rh-push-to-registry-redhat-io.yaml" 33 ) 34 35 var testComponent *appservice.Component 36 37 var _ = framework.ReleasePipelinesSuiteDescribe("e2e tests for rh-push-to-redhat-io pipeline", Label("release-pipelines", "rh-push-to-redhat-io"), func() { 38 defer GinkgoRecover() 39 var pyxisKeyDecoded, pyxisCertDecoded []byte 40 41 var devWorkspace = utils.GetEnv(constants.RELEASE_DEV_WORKSPACE_ENV, constants.DevReleaseTeam) 42 var managedWorkspace = utils.GetEnv(constants.RELEASE_MANAGED_WORKSPACE_ENV, constants.ManagedReleaseTeam) 43 44 var devNamespace = devWorkspace + "-tenant" 45 var managedNamespace = managedWorkspace + "-tenant" 46 47 var err error 48 var devFw *framework.Framework 49 var managedFw *framework.Framework 50 var rhioApplicationName = "rhio-app-" + util.GenerateRandomString(4) 51 var rhioComponentName = "rhio-comp-" + util.GenerateRandomString(4) 52 var rhioReleasePlanName = "rhio-rp-" + util.GenerateRandomString(4) 53 var rhioReleasePlanAdmissionName = "rhio-rpa-" + util.GenerateRandomString(4) 54 var rhioEnterpriseContractPolicyName = "rhio-policy-" + util.GenerateRandomString(4) 55 56 var snapshot *appservice.Snapshot 57 var releaseCR *releaseapi.Release 58 var releasePR, buildPR *tektonv1.PipelineRun 59 60 AfterEach(framework.ReportFailure(&devFw)) 61 62 Describe("Rh-push-to-redhat-io happy path", Label("PushToRedhatIO"), func() { 63 BeforeAll(func() { 64 devFw = releasecommon.NewFramework(devWorkspace) 65 managedFw = releasecommon.NewFramework(managedWorkspace) 66 managedNamespace = managedFw.UserNamespace 67 68 keyPyxisStage := os.Getenv(constants.PYXIS_STAGE_KEY_ENV) 69 Expect(keyPyxisStage).ToNot(BeEmpty()) 70 71 certPyxisStage := os.Getenv(constants.PYXIS_STAGE_CERT_ENV) 72 Expect(certPyxisStage).ToNot(BeEmpty()) 73 74 // Creating k8s secret to access Pyxis stage based on base64 decoded of key and cert 75 pyxisKeyDecoded, err = base64.StdEncoding.DecodeString(string(keyPyxisStage)) 76 Expect(err).ToNot(HaveOccurred()) 77 78 pyxisCertDecoded, err = base64.StdEncoding.DecodeString(string(certPyxisStage)) 79 Expect(err).ToNot(HaveOccurred()) 80 81 secret := &corev1.Secret{ 82 ObjectMeta: metav1.ObjectMeta{ 83 Name: "pyxis", 84 Namespace: managedNamespace, 85 }, 86 Type: corev1.SecretTypeOpaque, 87 Data: map[string][]byte{ 88 "cert": pyxisCertDecoded, 89 "key": pyxisKeyDecoded, 90 }, 91 } 92 93 // Delete the secret if it exists in case it is not correct 94 _ = managedFw.AsKubeAdmin.CommonController.DeleteSecret(managedNamespace, "pyxis") 95 _, err = managedFw.AsKubeAdmin.CommonController.CreateSecret(managedNamespace, secret) 96 Expect(err).ToNot(HaveOccurred()) 97 98 err = managedFw.AsKubeAdmin.CommonController.LinkSecretToServiceAccount(managedNamespace, releasecommon.RedhatAppstudioUserSecret, constants.DefaultPipelineServiceAccount, true) 99 Expect(err).ToNot(HaveOccurred()) 100 101 _, err = devFw.AsKubeDeveloper.HasController.CreateApplication(rhioApplicationName, devNamespace) 102 Expect(err).NotTo(HaveOccurred()) 103 104 _, err = devFw.AsKubeDeveloper.ReleaseController.CreateReleasePlan(rhioReleasePlanName, devNamespace, rhioApplicationName, managedNamespace, "true", nil) 105 Expect(err).NotTo(HaveOccurred()) 106 107 testComponent = releasecommon.CreateComponentByCDQ(*devFw, devNamespace, managedNamespace, rhioApplicationName, rhioComponentName, releasecommon.AdditionalGitSourceComponentUrl) 108 createRHIOReleasePlanAdmission(rhioReleasePlanAdmissionName, *managedFw, devNamespace, managedNamespace, rhioApplicationName, rhioEnterpriseContractPolicyName, rhioCatalogPathInRepo) 109 110 createRHIOEnterpriseContractPolicy(rhioEnterpriseContractPolicyName, *managedFw, devNamespace, managedNamespace) 111 }) 112 113 AfterAll(func() { 114 devFw = releasecommon.NewFramework(devWorkspace) 115 managedFw = releasecommon.NewFramework(managedWorkspace) 116 Expect(devFw.AsKubeDeveloper.HasController.DeleteApplication(rhioApplicationName, devNamespace, false)).NotTo(HaveOccurred()) 117 Expect(managedFw.AsKubeDeveloper.TektonController.DeleteEnterpriseContractPolicy(rhioEnterpriseContractPolicyName, managedNamespace, false)).NotTo(HaveOccurred()) 118 Expect(managedFw.AsKubeDeveloper.ReleaseController.DeleteReleasePlanAdmission(rhioReleasePlanAdmissionName, managedNamespace, false)).NotTo(HaveOccurred()) 119 }) 120 121 var _ = Describe("Post-release verification", func() { 122 It("verifies that a build PipelineRun is created in dev namespace and succeeds", func() { 123 devFw = releasecommon.NewFramework(devWorkspace) 124 // Create a ticker that ticks every 3 minutes 125 ticker := time.NewTicker(3 * time.Minute) 126 // Schedule the stop of the ticker after 15 minutes 127 time.AfterFunc(10*time.Minute, func() { 128 ticker.Stop() 129 fmt.Println("Stopped executing every 3 minutes.") 130 }) 131 // Run a goroutine to handle the ticker ticks 132 go func() { 133 for range ticker.C { 134 devFw = releasecommon.NewFramework(devWorkspace) 135 } 136 }() 137 Eventually(func() error { 138 buildPR, err = devFw.AsKubeDeveloper.HasController.GetComponentPipelineRun(testComponent.Name, rhioApplicationName, devNamespace, "") 139 if err != nil { 140 return err 141 } 142 if !buildPR.IsDone() { 143 return fmt.Errorf("build pipelinerun %s in namespace %s did not finish yet", buildPR.Name, buildPR.Namespace) 144 } 145 Expect(tekton.HasPipelineRunSucceeded(buildPR)).To(BeTrue(), fmt.Sprintf("build pipelinerun %s/%s did not succeed", buildPR.GetNamespace(), buildPR.GetName())) 146 snapshot, err = devFw.AsKubeDeveloper.IntegrationController.GetSnapshot("", buildPR.Name, "", devNamespace) 147 if err != nil { 148 return err 149 } 150 return nil 151 }, releasecommon.BuildPipelineRunCompletionTimeout, releasecommon.DefaultInterval).Should(Succeed(), "timed out when waiting for build pipelinerun to be created") 152 Expect(devFw.AsKubeDeveloper.HasController.WaitForComponentPipelineToBeFinished(testComponent, "", devFw.AsKubeDeveloper.TektonController, &has.RetryOptions{Retries: 3, Always: true}, nil)).To(Succeed()) 153 }) 154 It("verifies the rhio release pipelinerun is running and succeeds", func() { 155 devFw = releasecommon.NewFramework(devWorkspace) 156 managedFw = releasecommon.NewFramework(managedWorkspace) 157 158 Eventually(func() error { 159 releaseCR, err = devFw.AsKubeDeveloper.ReleaseController.GetRelease("", snapshot.Name, devNamespace) 160 if err != nil { 161 return err 162 } 163 releasePR, err = managedFw.AsKubeAdmin.ReleaseController.GetPipelineRunInNamespace(managedFw.UserNamespace, releaseCR.GetName(), releaseCR.GetNamespace()) 164 if err != nil { 165 return err 166 } 167 GinkgoWriter.Println("Release PR: ", releasePR.Name) 168 if !releasePR.IsDone(){ 169 return fmt.Errorf("release pipelinerun %s in namespace %s did not finished yet", releasePR.Name, releasePR.Namespace) 170 } 171 return nil 172 }, releasecommon.ReleasePipelineRunCompletionTimeout, releasecommon.DefaultInterval).Should(Succeed(), "timed out when waiting for release pipelinerun to succeed") 173 Expect(tekton.HasPipelineRunSucceeded(releasePR)).To(BeTrue(), fmt.Sprintf("release pipelinerun %s/%s did not succeed", releasePR.GetNamespace(), releasePR.GetName())) 174 }) 175 176 It("verifies release CR completed and set succeeded.", func() { 177 devFw = releasecommon.NewFramework(devWorkspace) 178 Eventually(func() error { 179 releaseCr, err := devFw.AsKubeDeveloper.ReleaseController.GetRelease("", snapshot.Name, devNamespace) 180 if err != nil { 181 return err 182 } 183 GinkgoWriter.Println("Release CR: ", releaseCr.Name) 184 if !releaseCr.IsReleased() { 185 return fmt.Errorf("release %s/%s is not marked as finished yet", releaseCR.GetNamespace(), releaseCR.GetName()) 186 } 187 return nil 188 }, 10 * time.Minute, releasecommon.DefaultInterval).Should(Succeed()) 189 }) 190 191 It("verifies if the MR URL is valid", func() { 192 managedFw = releasecommon.NewFramework(managedWorkspace) 193 releasePR, err = managedFw.AsKubeAdmin.ReleaseController.GetPipelineRunInNamespace(managedFw.UserNamespace, releaseCR.GetName(), releaseCR.GetNamespace()) 194 Expect(err).NotTo(HaveOccurred()) 195 196 trReleaseLogs, err := managedFw.AsKubeAdmin.TektonController.GetTaskRunLogs(releasePR.GetName(), "run-file-updates", releasePR.GetNamespace()) 197 Expect(err).NotTo(HaveOccurred()) 198 199 var log, mrURL string 200 for _, tasklog := range trReleaseLogs { 201 log = tasklog 202 } 203 204 re := regexp.MustCompile(`(?:MR Created: )(.+)`) 205 mrURL = re.FindStringSubmatch(log)[1] 206 207 pattern := `https?://[^/\s]+/[^/\s]+/[^/\s]+/+\-\/merge_requests\/(\d+)` 208 re, err = regexp.Compile(pattern) 209 Expect(err).NotTo(HaveOccurred()) 210 Expect(re.MatchString(mrURL)).To(BeTrue(), fmt.Sprintf("MR URL %s is not valid", mrURL)) 211 }) 212 }) 213 }) 214 }) 215 216 func createRHIOEnterpriseContractPolicy(rhioECPName string, managedFw framework.Framework, devNamespace, managedNamespace string) { 217 defaultEcPolicySpec := ecp.EnterpriseContractPolicySpec{ 218 Description: "Red Hat's enterprise requirements", 219 PublicKey: "k8s://openshift-pipelines/public-key", 220 Sources: []ecp.Source{{ 221 Name: "Default", 222 Policy: []string{releasecommon.EcPolicyLibPath, releasecommon.EcPolicyReleasePath}, 223 Data: []string{releasecommon.EcPolicyDataBundle, releasecommon.EcPolicyDataPath}, 224 }}, 225 Configuration: &ecp.EnterpriseContractPolicyConfiguration{ 226 Exclude: []string{"cve", "step_image_registries", "tasks.required_tasks_found:prefetch-dependencies"}, 227 Include: []string{"minimal"}, 228 }, 229 } 230 231 _, err := managedFw.AsKubeDeveloper.TektonController.CreateEnterpriseContractPolicy(rhioECPName, managedNamespace, defaultEcPolicySpec) 232 Expect(err).NotTo(HaveOccurred()) 233 234 } 235 236 func createRHIOReleasePlanAdmission(rhioRPAName string, managedFw framework.Framework, devNamespace, managedNamespace, rhioAppName, rhioECPName, pathInRepoValue string) { 237 var err error 238 239 data, err := json.Marshal(map[string]interface{}{ 240 "mapping": map[string]interface{}{ 241 "components": []map[string]interface{}{ 242 { 243 "name" : testComponent.GetName(), 244 "repository" : "quay.io/redhat-pending/rhtap----konflux-release-e2e", 245 }, 246 }, 247 }, 248 "pyxis": map[string]interface{}{ 249 "server": "stage", 250 "secret": "pyxis", 251 }, 252 "images": map[string]interface{}{ 253 "defaultTag": "latest", 254 "addGitShaTag": false, 255 "addTimestampTag": false, 256 "addSourceShaTag": false, 257 "floatingTags": []string{"testtag", "testtag2"}, 258 }, 259 "fileUpdates": []map[string]interface{}{ 260 { 261 "repo": releasecommon.GitLabRunFileUpdatesTestRepo, 262 "upstream_repo": releasecommon.GitLabRunFileUpdatesTestRepo, 263 "ref": "master", 264 "paths": []map[string]interface{}{ 265 { 266 "path": "data/app-interface/app-interface-settings.yml", 267 "replacements": []map[string]interface{}{ 268 { 269 "key": ".description", 270 // description: App Interface settings 271 "replacement": "|description:.*|description: {{ .components[0].containerImage }}|", 272 }, 273 }, 274 }, 275 }, 276 }, 277 }, 278 "sign": map[string]interface{}{ 279 "configMapName": "hacbs-signing-pipeline-config-redhatbeta2", 280 }, 281 }) 282 Expect(err).NotTo(HaveOccurred()) 283 284 _, err = managedFw.AsKubeAdmin.ReleaseController.CreateReleasePlanAdmission(rhioRPAName, managedNamespace, "", devNamespace, rhioECPName, rhioServiceAccountName, []string{rhioAppName}, true, &tektonutils.PipelineRef{ 285 Resolver: "git", 286 Params: []tektonutils.Param{ 287 {Name: "url", Value: releasecommon.RelSvcCatalogURL}, 288 {Name: "revision", Value: releasecommon.RelSvcCatalogRevision}, 289 {Name: "pathInRepo", Value: pathInRepoValue}, 290 }, 291 }, &runtime.RawExtension{ 292 Raw: data, 293 }) 294 Expect(err).NotTo(HaveOccurred()) 295 }