github.com/devtron-labs/ci-runner@v0.0.0-20240518055909-b2672f3349d7/executor/stage/cdStages.go (about) 1 /* 2 * Copyright 2020 Devtron Labs 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 */ 17 18 package stage 19 20 import ( 21 "github.com/devtron-labs/ci-runner/executor" 22 util2 "github.com/devtron-labs/ci-runner/executor/util" 23 "github.com/devtron-labs/ci-runner/helper" 24 "github.com/devtron-labs/ci-runner/util" 25 "log" 26 "os" 27 ) 28 29 type CdStage struct { 30 gitManager helper.GitManager 31 dockerHelper helper.DockerHelper 32 stageExecutorManager executor.StageExecutor 33 } 34 35 func NewCdStage(gitManager helper.GitManager, dockerHelper helper.DockerHelper, stageExecutor executor.StageExecutor) *CdStage { 36 return &CdStage{ 37 gitManager: gitManager, 38 dockerHelper: dockerHelper, 39 stageExecutorManager: stageExecutor, 40 } 41 } 42 43 func (impl *CdStage) HandleCDEvent(ciCdRequest *helper.CiCdTriggerEvent, exitCode *int) { 44 err := impl.runCDStages(ciCdRequest) 45 artifactUploadErr := collectAndUploadCDArtifacts(ciCdRequest.CommonWorkflowRequest) 46 if err != nil || artifactUploadErr != nil { 47 log.Println(err) 48 *exitCode = util.DefaultErrorCode 49 } 50 51 } 52 53 func collectAndUploadCDArtifacts(cdRequest *helper.CommonWorkflowRequest) error { 54 cloudHelperBaseConfig := cdRequest.GetCloudHelperBaseConfig(util.BlobStorageObjectTypeArtifact) 55 if cdRequest.PrePostDeploySteps != nil && len(cdRequest.PrePostDeploySteps) > 0 { 56 _, err := helper.ZipAndUpload(cloudHelperBaseConfig, cdRequest.CiArtifactFileName) 57 return err 58 } 59 60 // to support stage YAML outputs 61 artifactFiles := make(map[string]string) 62 var allTasks []*helper.Task 63 if cdRequest.TaskYaml != nil { 64 for _, pc := range cdRequest.TaskYaml.CdPipelineConfig { 65 for _, t := range append(pc.BeforeTasks, pc.AfterTasks...) { 66 allTasks = append(allTasks, t) 67 } 68 } 69 } 70 for _, task := range allTasks { 71 if task.RunStatus { 72 if _, err := os.Stat(task.OutputLocation); os.IsNotExist(err) { // Ignore if no file/folder 73 log.Println(util.DEVTRON, "artifact not found ", err) 74 continue 75 } 76 artifactFiles[task.Name] = task.OutputLocation 77 } 78 } 79 log.Println(util.DEVTRON, " artifacts", artifactFiles) 80 return helper.UploadArtifact(cloudHelperBaseConfig, artifactFiles, cdRequest.CiArtifactFileName) 81 } 82 83 func (impl *CdStage) runCDStages(cicdRequest *helper.CiCdTriggerEvent) error { 84 err := os.Chdir("/") 85 if err != nil { 86 return err 87 } 88 89 if _, err := os.Stat(util.WORKINGDIR); os.IsNotExist(err) { 90 _ = os.Mkdir(util.WORKINGDIR, os.ModeDir) 91 } 92 err = os.Chdir(util.WORKINGDIR) 93 if err != nil { 94 return err 95 } 96 // git handling 97 // we are skipping clone and checkout in case of ci job type poll cr images plugin does not require it.(ci-job) 98 skipCheckout := cicdRequest.CommonWorkflowRequest.CiPipelineType == helper.CI_JOB 99 if !skipCheckout { 100 log.Println(util.DEVTRON, " git") 101 err = impl.gitManager.CloneAndCheckout(cicdRequest.CommonWorkflowRequest.CiProjectDetails) 102 if err != nil { 103 log.Println(util.DEVTRON, "clone err: ", err) 104 return err 105 } 106 } 107 log.Println(util.DEVTRON, " /git") 108 // Start docker daemon 109 log.Println(util.DEVTRON, " docker-start") 110 impl.dockerHelper.StartDockerDaemon(cicdRequest.CommonWorkflowRequest) 111 err = impl.dockerHelper.DockerLogin(&helper.DockerCredentials{ 112 DockerUsername: cicdRequest.CommonWorkflowRequest.DockerUsername, 113 DockerPassword: cicdRequest.CommonWorkflowRequest.DockerPassword, 114 AwsRegion: cicdRequest.CommonWorkflowRequest.AwsRegion, 115 AccessKey: cicdRequest.CommonWorkflowRequest.AccessKey, 116 SecretKey: cicdRequest.CommonWorkflowRequest.SecretKey, 117 DockerRegistryURL: cicdRequest.CommonWorkflowRequest.IntermediateDockerRegistryUrl, 118 DockerRegistryType: cicdRequest.CommonWorkflowRequest.DockerRegistryType, 119 }) 120 if err != nil { 121 return err 122 } 123 124 scriptEnvs, err := util2.GetGlobalEnvVariables(cicdRequest) 125 126 if len(cicdRequest.CommonWorkflowRequest.PrePostDeploySteps) > 0 { 127 refStageMap := make(map[int][]*helper.StepObject) 128 for _, ref := range cicdRequest.CommonWorkflowRequest.RefPlugins { 129 refStageMap[ref.Id] = ref.Steps 130 } 131 scriptEnvs["DEST"] = cicdRequest.CommonWorkflowRequest.CiArtifactDTO.Image 132 scriptEnvs["DIGEST"] = cicdRequest.CommonWorkflowRequest.CiArtifactDTO.ImageDigest 133 var stage = helper.StepType(cicdRequest.CommonWorkflowRequest.StageType) 134 _, _, err = impl.stageExecutorManager.RunCiCdSteps(stage, cicdRequest.CommonWorkflowRequest, cicdRequest.CommonWorkflowRequest.PrePostDeploySteps, refStageMap, scriptEnvs, nil) 135 if err != nil { 136 return err 137 } 138 } else { 139 140 // Get devtron-cd yaml 141 taskYaml, err := helper.ToTaskYaml([]byte(cicdRequest.CommonWorkflowRequest.StageYaml)) 142 if err != nil { 143 log.Println(err) 144 return err 145 } 146 cicdRequest.CommonWorkflowRequest.TaskYaml = taskYaml 147 148 // run post artifact processing 149 log.Println(util.DEVTRON, " stage yaml", taskYaml) 150 var tasks []*helper.Task 151 for _, t := range taskYaml.CdPipelineConfig { 152 tasks = append(tasks, t.BeforeTasks...) 153 tasks = append(tasks, t.AfterTasks...) 154 } 155 156 if err != nil { 157 return err 158 } 159 err = executor.RunCdStageTasks(tasks, scriptEnvs) 160 if err != nil { 161 return err 162 } 163 } 164 165 // dry run flag indicates that ci runner image is being run from external helm chart 166 if !cicdRequest.CommonWorkflowRequest.IsDryRun { 167 log.Println(util.DEVTRON, " event") 168 err = helper.SendCDEvent(cicdRequest.CommonWorkflowRequest) 169 if err != nil { 170 log.Println(err) 171 return err 172 } 173 log.Println(util.DEVTRON, " /event") 174 } 175 err = impl.dockerHelper.StopDocker() 176 if err != nil { 177 log.Println("error while stopping docker", err) 178 return err 179 } 180 return nil 181 }