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  }