Repository: devtron-labs/devtron
Pull request #3448 (2023-05-30 10:04:23)

refactoring: cd workflow manager refactoring
<!--
Type of change: Title of the PR should clearly mention which type of PR is this, you can select any of the below mentioned types:

- docs - The PR contains Documentation ONLY changes. 
- feat - The PR contains new feature/enhancements.
- fix - The PR contains a bug fix.
- chore - Development changes related to the build system (involving scripts, configurations or tools) and package dependencies.
- test - Development changes related to tests.
- perf - Changes related to performance improvements.

Example Title: 
docs: Webhook CI documentation changes
-->

# Description
<!--
Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change.
-->

Fixes #

## How Has This Been Tested?
Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration
<!--test-cases
- [ ] Test case A
- [ ] Test case B
-->

## Checklist:

* [ ] The title of the PR states what changed and the related issues number (used for the release note).
* [ ] Does this PR requires documentation updates?
* [ ] I've updated documentation as required by this PR.
* [ ] I have performed a self-review of my own code.
* [ ] I have commented my code, particularly in hard-to-understand areas.
* [ ] I have tested it for all user roles.
* [ ] I have added all the required unit/api test cases.

## Does this PR introduce a user-facing change?
<!--
If NO, leave the release-note block blank.
If YES, a release note is required:
Enter your extended release note in the block below. If the PR requires additional manual action from users switching to the new version, include the string "action-required".

-->
```release-note

```




Patch:
diff --git a/Wire.go b/Wire.go
index bfe7c5a0a..acde90a89 100644
--- a/Wire.go
+++ b/Wire.go
@@ -841,6 +841,8 @@ func InitializeApp() (*App, error) {
 		wire.Bind(new(appGroup2.AppGroupRepository), new(*appGroup2.AppGroupRepositoryImpl)),
 		appGroup2.NewAppGroupMappingRepositoryImpl,
 		wire.Bind(new(appGroup2.AppGroupMappingRepository), new(*appGroup2.AppGroupMappingRepositoryImpl)),
+		pipeline.NewArgoWorkflowExecutorImpl,
+		wire.Bind(new(pipeline.ArgoWorkflowExecutor), new(*pipeline.ArgoWorkflowExecutorImpl)),
 	)
 	return &App{}, nil
 }
diff --git a/api/bean/ConfigMapAndSecret.go b/api/bean/ConfigMapAndSecret.go
index 9b0de7b91..d35d58b82 100644
--- a/api/bean/ConfigMapAndSecret.go
+++ b/api/bean/ConfigMapAndSecret.go
@@ -25,16 +25,16 @@ type ConfigMapRootJson struct {
 	ConfigMapJson ConfigMapJson `json:"ConfigMaps"`
 }
 type ConfigMapJson struct {
-	Enabled bool  `json:"enabled"`
-	Maps    []Map `json:"maps"`
+	Enabled bool              `json:"enabled"`
+	Maps    []ConfigSecretMap `json:"maps"`
 }
 
 type ConfigSecretRootJson struct {
 	ConfigSecretJson ConfigSecretJson `json:"ConfigSecrets"`
 }
 type ConfigSecretJson struct {
-	Enabled bool   `json:"enabled"`
-	Secrets []*Map `json:"secrets"`
+	Enabled bool               `json:"enabled"`
+	Secrets []*ConfigSecretMap `json:"secrets"`
 }
 
 type ConfigMapAndSecretJson struct {
@@ -42,7 +42,7 @@ type ConfigMapAndSecretJson struct {
 	ConfigSecretJson ConfigSecretJson `json:"configSecretJson"`
 }
 
-type Map struct {
+type ConfigSecretMap struct {
 	Name           string          `json:"name"`
 	Type           string          `json:"type"`
 	External       bool            `json:"external"`
@@ -55,3 +55,9 @@ type Map struct {
 	SubPath        bool            `json:"subPath"`
 	FilePermission string          `json:"filePermission"`
 }
+
+func (configSecret ConfigSecretMap) GetDataMap() (map[string]string, error) {
+	var datamap map[string]string
+	err := json.Unmarshal(configSecret.Data, &datamap)
+	return datamap, err
+}
diff --git a/api/restHandler/GlobalCMCSRestHandler.go b/api/restHandler/GlobalCMCSRestHandler.go
index 90b0f3980..274f855cb 100644
--- a/api/restHandler/GlobalCMCSRestHandler.go
+++ b/api/restHandler/GlobalCMCSRestHandler.go
@@ -4,6 +4,7 @@ import (
 	"encoding/json"
 	"github.com/devtron-labs/devtron/api/restHandler/common"
 	"github.com/devtron-labs/devtron/pkg/pipeline"
+	pipelineBean "github.com/devtron-labs/devtron/pkg/pipeline/bean"
 	"github.com/devtron-labs/devtron/pkg/user"
 	"github.com/devtron-labs/devtron/pkg/user/casbin"
 	"github.com/gorilla/mux"
@@ -51,7 +52,7 @@ func (handler *GlobalCMCSRestHandlerImpl) CreateGlobalCMCSConfig(w http.Response
 		common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized)
 		return
 	}
-	var bean pipeline.GlobalCMCSDto
+	var bean pipelineBean.GlobalCMCSDto
 	err = decoder.Decode(&bean)
 	if err != nil {
 		handler.logger.Errorw("request err, CreateGlobalCMCSConfig", "err", err, "payload", bean)
diff --git a/internal/util/MergeUtil.go b/internal/util/MergeUtil.go
index ebdf9ca98..6c46cf63d 100644
--- a/internal/util/MergeUtil.go
+++ b/internal/util/MergeUtil.go
@@ -99,8 +99,8 @@ func (m MergeUtil) ConfigMapMerge(appLevelConfigMapJson string, envLevelConfigMa
 	appLevelConfigMap := bean.ConfigMapJson{}
 	envLevelConfigMap := bean.ConfigMapJson{}
 	configResponse := bean.ConfigMapJson{}
-	commonMaps := map[string]bean.Map{}
-	var finalMaps []bean.Map
+	commonMaps := map[string]bean.ConfigSecretMap{}
+	var finalMaps []bean.ConfigSecretMap
 	if appLevelConfigMapJson != "" {
 		err = json.Unmarshal([]byte(appLevelConfigMapJson), &appLevelConfigMap)
 		if err != nil {
@@ -142,8 +142,8 @@ func (m MergeUtil) ConfigSecretMerge(appLevelSecretJson string, envLevelSecretJs
 	appLevelSecret := bean.ConfigSecretJson{}
 	envLevelSecret := bean.ConfigSecretJson{}
 	secretResponse := bean.ConfigSecretJson{}
-	commonSecrets := map[string]*bean.Map{}
-	var finalMaps []*bean.Map
+	commonSecrets := map[string]*bean.ConfigSecretMap{}
+	var finalMaps []*bean.ConfigSecretMap
 	if appLevelSecretJson != "" {
 		err = json.Unmarshal([]byte(appLevelSecretJson), &appLevelSecret)
 		if err != nil {
diff --git a/pkg/cluster/repository/ClusterRepository.go b/pkg/cluster/repository/ClusterRepository.go
index 725c301ec..67d74fd35 100644
--- a/pkg/cluster/repository/ClusterRepository.go
+++ b/pkg/cluster/repository/ClusterRepository.go
@@ -21,6 +21,7 @@ import (
 	"github.com/devtron-labs/devtron/pkg/sql"
 	"github.com/go-pg/pg"
 	"go.uber.org/zap"
+	"k8s.io/client-go/rest"
 )
 
 type Cluster struct {
@@ -70,6 +71,19 @@ type ClusterRepositoryImpl struct {
 	logger       *zap.SugaredLogger
 }
 
+func (cluster Cluster) GetClusterConfig() *rest.Config {
+	configMap := cluster.Config
+	bearerToken := configMap["bearer_token"]
+	config := &rest.Config{
+		Host:        cluster.ServerUrl,
+		BearerToken: bearerToken,
+		TLSClientConfig: rest.TLSClientConfig{
+			Insecure: true,
+		},
+	}
+	return config
+}
+
 func (impl ClusterRepositoryImpl) Save(model *Cluster) error {
 	return impl.dbConnection.Insert(model)
 }
diff --git a/pkg/pipeline/ArgoWorkflowExecutor.go b/pkg/pipeline/ArgoWorkflowExecutor.go
new file mode 100644
index 000000000..fdf5ffdd1
--- /dev/null
+++ b/pkg/pipeline/ArgoWorkflowExecutor.go
@@ -0,0 +1,290 @@
+package pipeline
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"github.com/argoproj/argo-workflows/v3/pkg/apis/workflow/v1alpha1"
+	"github.com/argoproj/argo-workflows/v3/pkg/client/clientset/versioned"
+	v1alpha12 "github.com/argoproj/argo-workflows/v3/pkg/client/clientset/versioned/typed/workflow/v1alpha1"
+	bean2 "github.com/devtron-labs/devtron/api/bean"
+	"github.com/devtron-labs/devtron/pkg/pipeline/bean"
+	"go.uber.org/zap"
+	v12 "k8s.io/api/core/v1"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/util/intstr"
+	"k8s.io/client-go/rest"
+	"net/url"
+)
+
+const (
+	STEP_NAME_REGEX     = "create-env-%s-gb-%d"
+	TEMPLATE_NAME_REGEX = "%s-gb-%d"
+	WORKFLOW_MINIO_CRED = "workflow-minio-cred"
+	CRED_ACCESS_KEY     = "accessKey"
+	CRED_SECRET_KEY     = "secretKey"
+)
+
+type WorkflowExecutor interface {
+	ExecuteWorkflow(workflowTemplate bean.WorkflowTemplate) error
+}
+
+type ArgoWorkflowExecutor interface {
+	WorkflowExecutor
+}
+
+type ArgoWorkflowExecutorImpl struct {
+	logger *zap.SugaredLogger
+}
+
+func NewArgoWorkflowExecutorImpl(logger *zap.SugaredLogger) *ArgoWorkflowExecutorImpl {
+	return &ArgoWorkflowExecutorImpl{logger: logger}
+}
+
+func (impl *ArgoWorkflowExecutorImpl) ExecuteWorkflow(workflowTemplate bean.WorkflowTemplate) error {
+
+	entryPoint := CD_WORKFLOW_NAME
+	// get cm and cs argo step templates
+	templates, err := impl.getArgoTemplates(workflowTemplate.ConfigMaps, workflowTemplate.Secrets)
+	if err != nil {
+		impl.logger.Errorw("error occurred while fetching argo templates and steps", "err", err)
+		return err
+	}
+	if len(templates) > 0 {
+		entryPoint = CD_WORKFLOW_WITH_STAGES
+	}
+
+	wfContainer := workflowTemplate.Containers[0]
+	cdTemplate := v1alpha1.Template{
+		Name:      CD_WORKFLOW_NAME,
+		Container: &wfContainer,
+		ActiveDeadlineSeconds: &intstr.IntOrString{
+			IntVal: int32(*workflowTemplate.ActiveDeadlineSeconds),
+		},
+	}
+	impl.updateBlobStorageConfig(workflowTemplate, &cdTemplate)
+	templates = append(templates, cdTemplate)
+
+	var (
+		cdWorkflow = v1alpha1.Workflow{
+			ObjectMeta: v1.ObjectMeta{
+				GenerateName: workflowTemplate.WorkflowNamePrefix + "-",
+				Annotations:  map[string]string{"workflows.argoproj.io/controller-instanceid": workflowTemplate.WfControllerInstanceID},
+				Labels:       map[string]string{"devtron.ai/workflow-purpose": "cd"},
+			},
+			Spec: v1alpha1.WorkflowSpec{
+				ServiceAccountName: workflowTemplate.ServiceAccountName,
+				NodeSelector:       workflowTemplate.NodeSelector,
+				Tolerations:        workflowTemplate.Tolerations,
+				Entrypoint:         entryPoint,
+				TTLStrategy: &v1alpha1.TTLStrategy{
+					SecondsAfterCompletion: workflowTemplate.TTLValue,
+				},
+				Templates: templates,
+				Volumes:   workflowTemplate.Volumes,
+			},
+		}
+	)
+
+	wfTemplate, err := json.Marshal(cdWorkflow)
+	if err != nil {
+		impl.logger.Errorw("error occurred while marshalling json", "err", err)
+		return err
+	}
+	impl.logger.Debugw("workflow request to submit", "wf", string(wfTemplate))
+
+	wfClient, err := impl.getClientInstance(workflowTemplate.Namespace, workflowTemplate.ClusterConfig)
+	if err != nil {
+		impl.logger.Errorw("cannot build wf client", "err", err)
+		return err
+	}
+
+	createdWf, err := wfClient.Create(context.Background(), &cdWorkflow, v1.CreateOptions{})
+	if err != nil {
+		impl.logger.Errorw("error in wf trigger", "err", err)
+		return err
+	}
+	impl.logger.Debugw("workflow submitted: ", "name", createdWf.Name)
+	return nil
+}
+
+func (impl *ArgoWorkflowExecutorImpl) updateBlobStorageConfig(workflowTemplate bean.WorkflowTemplate, cdTemplate *v1alpha1.Template) {
+	cdTemplate.ArchiveLocation = &v1alpha1.ArtifactLocation{
+		ArchiveLogs: &workflowTemplate.BlobStorageConfigured,
+	}
+	if workflowTemplate.BlobStorageConfigured {
+		var s3Artifact *v1alpha1.S3Artifact
+		var gcsArtifact *v1alpha1.GCSArtifact
+		blobStorageS3Config := workflowTemplate.BlobStorageS3Config
+		gcpBlobConfig := workflowTemplate.GcpBlobConfig
+		cloudStorageKey := workflowTemplate.CloudStorageKey
+		if blobStorageS3Config != nil {
+			s3CompatibleEndpointUrl := blobStorageS3Config.EndpointUrl
+			if s3CompatibleEndpointUrl == "" {
+				s3CompatibleEndpointUrl = "s3.amazonaws.com"
+			} else {
+				parsedUrl, err := url.Parse(s3CompatibleEndpointUrl)
+				if err != nil {
+					impl.logger.Errorw("error occurred while parsing s3CompatibleEndpointUrl, ", "s3CompatibleEndpointUrl", s3CompatibleEndpointUrl, "err", err)
+				} else {
+					s3CompatibleEndpointUrl = parsedUrl.Host
+				}
+			}
+			isInsecure := blobStorageS3Config.IsInSecure
+			var accessKeySelector *v12.SecretKeySelector
+			var secretKeySelector *v12.SecretKeySelector
+			if blobStorageS3Config.AccessKey != "" {
+				accessKeySelector = &v12.SecretKeySelector{
+					Key: CRED_ACCESS_KEY,
+					LocalObjectReference: v12.LocalObjectReference{
+						Name: WORKFLOW_MINIO_CRED,
+					},
+				}
+				secretKeySelector = &v12.SecretKeySelector{
+					Key: CRED_SECRET_KEY,
+					LocalObjectReference: v12.LocalObjectReference{
+						Name: WORKFLOW_MINIO_CRED,
+					},
+				}
+			}
+			s3Artifact = &v1alpha1.S3Artifact{
+				Key: cloudStorageKey,
+				S3Bucket: v1alpha1.S3Bucket{
+					Endpoint:        s3CompatibleEndpointUrl,
+					AccessKeySecret: accessKeySelector,
+					SecretKeySecret: secretKeySelector,
+					Bucket:          blobStorageS3Config.CiLogBucketName,
+					Insecure:        &isInsecure,
+				},
+			}
+			if blobStorageS3Config.CiLogRegion != "" {
+				//TODO checking for Azure
+				s3Artifact.Region = blobStorageS3Config.CiLogRegion
+			}
+		} else if gcpBlobConfig != nil {
+			gcsArtifact = &v1alpha1.GCSArtifact{
+				Key: cloudStorageKey,
+				GCSBucket: v1alpha1.GCSBucket{
+					Bucket: gcpBlobConfig.LogBucketName,
+					ServiceAccountKeySecret: &v12.SecretKeySelector{
+						Key: CRED_SECRET_KEY,
+						LocalObjectReference: v12.LocalObjectReference{
+							Name: WORKFLOW_MINIO_CRED,
+						},
+					},
+				},
+			}
+		}
+
+		// set in ArchiveLocation
+		cdTemplate.ArchiveLocation.S3 = s3Artifact
+		cdTemplate.ArchiveLocation.GCS = gcsArtifact
+	}
+}
+
+func (impl *ArgoWorkflowExecutorImpl) getArgoTemplates(configMaps []bean2.ConfigSecretMap, secrets []bean2.ConfigSecretMap) ([]v1alpha1.Template, error) {
+	var templates []v1alpha1.Template
+	var steps []v1alpha1.ParallelSteps
+	cmIndex := 0
+	csIndex := 0
+	for _, configMap := range configMaps {
+		if configMap.External {
+			continue
+		}
+		parallelStep, argoTemplate, err := impl.appendCMCSToStepAndTemplate(false, configMap, cmIndex)
+		if err != nil {
+			return templates, err
+		}
+		steps = append(steps, parallelStep)
+		templates = append(templates, argoTemplate)
+		cmIndex++
+	}
+	for _, secret := range secrets {
+		if secret.External {
+			continue
+		}
+		parallelStep, argoTemplate, err := impl.appendCMCSToStepAndTemplate(true, secret, csIndex)
+		if err != nil {
+			return templates, err
+		}
+		steps = append(steps, parallelStep)
+		templates = append(templates, argoTemplate)
+		csIndex++
+	}
+
+	steps = append(steps, v1alpha1.ParallelSteps{
+		Steps: []v1alpha1.WorkflowStep{
+			{
+				Name:     "run-wf",
+				Template: CD_WORKFLOW_NAME,
+			},
+		},
+	})
+
+	templates = append(templates, v1alpha1.Template{
+		Name:  CD_WORKFLOW_WITH_STAGES,
+		Steps: steps,
+	})
+
+	return templates, nil
+}
+
+func (impl *ArgoWorkflowExecutorImpl) appendCMCSToStepAndTemplate(isSecret bool, configSecretMap bean2.ConfigSecretMap, cmSecretIndex int) (v1alpha1.ParallelSteps, v1alpha1.Template, error) {
+	var parallelStep v1alpha1.ParallelSteps
+	var argoTemplate v1alpha1.Template
+	configDataMap, err := configSecretMap.GetDataMap()
+	if err != nil {
+		impl.logger.Errorw("error occurred while extracting data map", "Data", configSecretMap.Data, "err", err)
+		return parallelStep, argoTemplate, err
+	}
+
+	var cmSecretJson string
+	configMapSecretDto := ConfigMapSecretDto{Name: configSecretMap.Name, Data: configDataMap, OwnerRef: ArgoWorkflowOwnerRef}
+	if isSecret {
+		cmSecretJson, err = GetSecretJson(configMapSecretDto)
+	} else {
+		cmSecretJson, err = GetConfigMapJson(configMapSecretDto)
+	}
+	if err != nil {
+		impl.logger.Errorw("error occurred while extracting cm/secret json", "configSecretName", configSecretMap.Name, "err", err)
+		return parallelStep, argoTemplate, err
+	}
+	parallelStep, argoTemplate = impl.createStepAndTemplate(isSecret, cmSecretIndex, cmSecretJson)
+	return parallelStep, argoTemplate, nil
+}
+
+func (impl *ArgoWorkflowExecutorImpl) createStepAndTemplate(isSecret bool, cmSecretIndex int, cmSecretJson string) (v1alpha1.ParallelSteps, v1alpha1.Template) {
+	stepName := fmt.Sprintf(STEP_NAME_REGEX, "cm", cmSecretIndex)
+	templateName := fmt.Sprintf(TEMPLATE_NAME_REGEX, "cm", cmSecretIndex)
+	if isSecret {
+		stepName = fmt.Sprintf(STEP_NAME_REGEX, "secret", cmSecretIndex)
+		templateName = fmt.Sprintf(TEMPLATE_NAME_REGEX, "secret", cmSecretIndex)
+	}
+	parallelStep := v1alpha1.ParallelSteps{
+		Steps: []v1alpha1.WorkflowStep{
+			{
+				Name:     stepName,
+				Template: templateName,
+			},
+		},
+	}
+	argoTemplate := v1alpha1.Template{
+		Name: templateName,
+		Resource: &v1alpha1.ResourceTemplate{
+			Action:            "create",
+			SetOwnerReference: true,
+			Manifest:          string(cmSecretJson),
+		},
+	}
+	return parallelStep, argoTemplate
+}
+
+func (impl *ArgoWorkflowExecutorImpl) getClientInstance(namespace string, clusterConfig *rest.Config) (v1alpha12.WorkflowInterface, error) {
+	clientSet, err := versioned.NewForConfig(clusterConfig)
+	if err != nil {
+		impl.logger.Errorw("error occurred while creating client from config", "err", err)
+		return nil, err
+	}
+	wfClient := clientSet.ArgoprojV1alpha1().Workflows(namespace) // create the workflow client
+	return wfClient, nil
+}
diff --git a/pkg/pipeline/CdConfig.go b/pkg/pipeline/CdConfig.go
index f50dcb9d1..e4c12d2a9 100644
--- a/pkg/pipeline/CdConfig.go
+++ b/pkg/pipeline/CdConfig.go
@@ -21,6 +21,7 @@ import (
 	"flag"
 	"fmt"
 	blob_storage "github.com/devtron-labs/common-lib/blob-storage"
+	"github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig"
 	"os/user"
 	"path/filepath"
 	"strings"
@@ -45,7 +46,7 @@ type CdConfig struct {
 	NodeLabelSelector                []string `env:"CD_NODE_LABEL_SELECTOR"`
 	CdArtifactLocationFormat         string   `env:"CD_ARTIFACT_LOCATION_FORMAT" envDefault:"%d/%d.zip"`
 	DefaultNamespace                 string   `env:"DEFAULT_CD_NAMESPACE"`
-	DefaultImage                     string   `env:"DEFAULT_CI_IMAGE" `
+	DefaultImage                     string   `env:"DEFAULT_CI_IMAGE"`
 	DefaultTimeout                   int64    `env:"DEFAULT_CD_TIMEOUT" envDefault:"3600"`
 	DefaultCdLogsBucketRegion        string   `env:"DEFAULT_CD_LOGS_BUCKET_REGION" `
 	WfControllerInstanceID           string   `env:"WF_CONTROLLER_INSTANCE_ID" envDefault:"devtron-runner"`
@@ -53,26 +54,27 @@ type CdConfig struct {
 	OrchestratorToken                string   `env:"ORCH_TOKEN" envDefault:""`
 	ClusterConfig                    *rest.Config
 	NodeLabel                        map[string]string
-	CloudProvider                    blob_storage.BlobStorageType `env:"BLOB_STORAGE_PROVIDER" envDefault:"S3"`
-	BlobStorageEnabled               bool                         `env:"BLOB_STORAGE_ENABLED" envDefault:"false"`
-	BlobStorageS3AccessKey           string                       `env:"BLOB_STORAGE_S3_ACCESS_KEY"`
-	BlobStorageS3SecretKey           string                       `env:"BLOB_STORAGE_S3_SECRET_KEY"`
-	BlobStorageS3Endpoint            string                       `env:"BLOB_STORAGE_S3_ENDPOINT"`
-	BlobStorageS3EndpointInsecure    bool                         `env:"BLOB_STORAGE_S3_ENDPOINT_INSECURE" envDefault:"false"`
-	BlobStorageS3BucketVersioned     bool                         `env:"BLOB_STORAGE_S3_BUCKET_VERSIONED" envDefault:"true"`
-	BlobStorageGcpCredentialJson     string                       `env:"BLOB_STORAGE_GCP_CREDENTIALS_JSON"`
-	AzureAccountName                 string                       `env:"AZURE_ACCOUNT_NAME"`
-	AzureGatewayUrl                  string                       `env:"AZURE_GATEWAY_URL" envDefault:"http://devtron-minio.devtroncd:9000"`
-	AzureGatewayConnectionInsecure   bool                         `env:"AZURE_GATEWAY_CONNECTION_INSECURE" envDefault:"true"`
-	AzureBlobContainerCiLog          string                       `env:"AZURE_BLOB_CONTAINER_CI_LOG"`
-	AzureBlobContainerCiCache        string                       `env:"AZURE_BLOB_CONTAINER_CI_CACHE"`
-	AzureAccountKey                  string                       `env:"AZURE_ACCOUNT_KEY"`
-	BuildLogTTLValue                 int                          `env:"BUILD_LOG_TTL_VALUE_IN_SECS" envDefault:"3600"`
-	DefaultAddressPoolBaseCidr       string                       `env:"CD_DEFAULT_ADDRESS_POOL_BASE_CIDR"`
-	DefaultAddressPoolSize           int                          `env:"CD_DEFAULT_ADDRESS_POOL_SIZE"`
-	ExposeCDMetrics                  bool                         `env:"EXPOSE_CD_METRICS" envDefault:"false"`
-	UseBlobStorageConfigInCdWorkflow bool                         `env:"USE_BLOB_STORAGE_CONFIG_IN_CD_WORKFLOW" envDefault:"true"`
-	BaseLogLocationPath              string                       `env:"BASE_LOG_LOCATION_PATH" envDefault:"/home/devtron/"`
+	CloudProvider                    blob_storage.BlobStorageType        `env:"BLOB_STORAGE_PROVIDER" envDefault:"S3"`
+	BlobStorageEnabled               bool                                `env:"BLOB_STORAGE_ENABLED" envDefault:"false"`
+	BlobStorageS3AccessKey           string                              `env:"BLOB_STORAGE_S3_ACCESS_KEY"`
+	BlobStorageS3SecretKey           string                              `env:"BLOB_STORAGE_S3_SECRET_KEY"`
+	BlobStorageS3Endpoint            string                              `env:"BLOB_STORAGE_S3_ENDPOINT"`
+	BlobStorageS3EndpointInsecure    bool                                `env:"BLOB_STORAGE_S3_ENDPOINT_INSECURE" envDefault:"false"`
+	BlobStorageS3BucketVersioned     bool                                `env:"BLOB_STORAGE_S3_BUCKET_VERSIONED" envDefault:"true"`
+	BlobStorageGcpCredentialJson     string                              `env:"BLOB_STORAGE_GCP_CREDENTIALS_JSON"`
+	AzureAccountName                 string                              `env:"AZURE_ACCOUNT_NAME"`
+	AzureGatewayUrl                  string                              `env:"AZURE_GATEWAY_URL" envDefault:"http://devtron-minio.devtroncd:9000"`
+	AzureGatewayConnectionInsecure   bool                                `env:"AZURE_GATEWAY_CONNECTION_INSECURE" envDefault:"true"`
+	AzureBlobContainerCiLog          string                              `env:"AZURE_BLOB_CONTAINER_CI_LOG"`
+	AzureBlobContainerCiCache        string                              `env:"AZURE_BLOB_CONTAINER_CI_CACHE"`
+	AzureAccountKey                  string                              `env:"AZURE_ACCOUNT_KEY"`
+	BuildLogTTLValue                 int                                 `env:"BUILD_LOG_TTL_VALUE_IN_SECS" envDefault:"3600"`
+	DefaultAddressPoolBaseCidr       string                              `env:"CD_DEFAULT_ADDRESS_POOL_BASE_CIDR"`
+	DefaultAddressPoolSize           int                                 `env:"CD_DEFAULT_ADDRESS_POOL_SIZE"`
+	ExposeCDMetrics                  bool                                `env:"EXPOSE_CD_METRICS" envDefault:"false"`
+	UseBlobStorageConfigInCdWorkflow bool                                `env:"USE_BLOB_STORAGE_CONFIG_IN_CD_WORKFLOW" envDefault:"true"`
+	BaseLogLocationPath              string                              `env:"BASE_LOG_LOCATION_PATH" envDefault:"/home/devtron/"`
+	CdWorkflowExecutorType           pipelineConfig.WorkflowExecutorType `env:"CD_WORKFLOW_EXECUTOR_TYPE" envDefault:"AWF"`
 }
 
 func GetCdConfig() (*CdConfig, error) {
diff --git a/pkg/pipeline/CdWorkflowService.go b/pkg/pipeline/CdWorkflowService.go
index c6ee90c6b..106b3e0d6 100644
--- a/pkg/pipeline/CdWorkflowService.go
+++ b/pkg/pipeline/CdWorkflowService.go
@@ -20,12 +20,14 @@ package pipeline
 import (
 	"context"
 	"encoding/json"
+	"errors"
 	"fmt"
+	"github.com/argoproj/argo-workflows/v3/workflow/common"
 	blob_storage "github.com/devtron-labs/common-lib/blob-storage"
 	repository2 "github.com/devtron-labs/devtron/internal/sql/repository"
+	bean2 "github.com/devtron-labs/devtron/pkg/bean"
 	"github.com/devtron-labs/devtron/pkg/cluster/repository"
-	"k8s.io/apimachinery/pkg/util/intstr"
-	"net/url"
+	bean3 "github.com/devtron-labs/devtron/pkg/pipeline/bean"
 	"strconv"
 	"strings"
 	"time"
@@ -37,7 +39,6 @@ import (
 	"github.com/devtron-labs/devtron/api/bean"
 	"github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig"
 	"github.com/devtron-labs/devtron/pkg/app"
-	bean2 "github.com/devtron-labs/devtron/pkg/bean"
 	"go.uber.org/zap"
 	v12 "k8s.io/api/core/v1"
 	"k8s.io/apimachinery/pkg/api/resource"
@@ -46,7 +47,7 @@ import (
 )
 
 type CdWorkflowService interface {
-	SubmitWorkflow(workflowRequest *CdWorkflowRequest, pipeline *pipelineConfig.Pipeline, env *repository.Environment) (*v1alpha1.Workflow, error)
+	SubmitWorkflow(workflowRequest *CdWorkflowRequest, pipeline *pipelineConfig.Pipeline, env *repository.Environment) error
 	DeleteWorkflow(wfName string, namespace string) error
 	GetWorkflow(name string, namespace string, url string, token string, isExtRun bool) (*v1alpha1.Workflow, error)
 	ListAllWorkflows(namespace string) (*v1alpha1.WorkflowList, error)
@@ -60,58 +61,60 @@ const (
 )
 
 type CdWorkflowServiceImpl struct {
-	Logger            *zap.SugaredLogger
-	config            *rest.Config
-	cdConfig          *CdConfig
-	appService        app.AppService
-	envRepository     repository.EnvironmentRepository
-	globalCMCSService GlobalCMCSService
+	Logger               *zap.SugaredLogger
+	config               *rest.Config
+	cdConfig             *CdConfig
+	appService           app.AppService
+	envRepository        repository.EnvironmentRepository
+	globalCMCSService    GlobalCMCSService
+	argoWorkflowExecutor ArgoWorkflowExecutor
 }
 
 type CdWorkflowRequest struct {
-	AppId                      int                               `json:"appId"`
-	EnvironmentId              int                               `json:"envId"`
-	WorkflowId                 int                               `json:"workflowId"`
-	WorkflowRunnerId           int                               `json:"workflowRunnerId"`
-	CdPipelineId               int                               `json:"cdPipelineId"`
-	TriggeredBy                int32                             `json:"triggeredBy"`
-	StageYaml                  string                            `json:"stageYaml"`
-	ArtifactLocation           string                            `json:"artifactLocation"`
-	ArtifactBucket             string                            `json:"ciArtifactBucket"`
-	ArtifactFileName           string                            `json:"ciArtifactFileName"`
-	ArtifactRegion             string                            `json:"ciArtifactRegion"`
-	CiProjectDetails           []CiProjectDetails                `json:"ciProjectDetails"`
-	CiArtifactDTO              CiArtifactDTO                     `json:"ciArtifactDTO"`
-	Namespace                  string                            `json:"namespace"`
-	WorkflowNamePrefix         string                            `json:"workflowNamePrefix"`
-	CdImage                    string                            `json:"cdImage"`
-	ActiveDeadlineSeconds      int64                             `json:"activeDeadlineSeconds"`
-	StageType                  string                            `json:"stageType"`
-	DockerUsername             string                            `json:"dockerUsername"`
-	DockerPassword             string                            `json:"dockerPassword"`
-	AwsRegion                  string                            `json:"awsRegion"`
-	SecretKey                  string                            `json:"secretKey"`
-	AccessKey                  string                            `json:"accessKey"`
-	DockerConnection           string                            `json:"dockerConnection"`
-	DockerCert                 string                            `json:"dockerCert"`
-	CdCacheLocation            string                            `json:"cdCacheLocation"`
-	CdCacheRegion              string                            `json:"cdCacheRegion"`
-	DockerRegistryType         string                            `json:"dockerRegistryType"`
-	DockerRegistryURL          string                            `json:"dockerRegistryURL"`
-	OrchestratorHost           string                            `json:"orchestratorHost"`
-	OrchestratorToken          string                            `json:"orchestratorToken"`
-	IsExtRun                   bool                              `json:"isExtRun"`
-	ExtraEnvironmentVariables  map[string]string                 `json:"extraEnvironmentVariables"`
-	BlobStorageConfigured      bool                              `json:"blobStorageConfigured"`
-	BlobStorageS3Config        *blob_storage.BlobStorageS3Config `json:"blobStorageS3Config"`
-	CloudProvider              blob_storage.BlobStorageType      `json:"cloudProvider"`
-	AzureBlobConfig            *blob_storage.AzureBlobConfig     `json:"azureBlobConfig"`
-	GcpBlobConfig              *blob_storage.GcpBlobConfig       `json:"gcpBlobConfig"`
-	DefaultAddressPoolBaseCidr string                            `json:"defaultAddressPoolBaseCidr"`
-	DefaultAddressPoolSize     int                               `json:"defaultAddressPoolSize"`
-	DeploymentTriggeredBy      string                            `json:"deploymentTriggeredBy,omitempty"`
-	DeploymentTriggerTime      time.Time                         `json:"deploymentTriggerTime,omitempty"`
-	DeploymentReleaseCounter   int                               `json:"deploymentReleaseCounter,omitempty"`
+	AppId                      int                                 `json:"appId"`
+	EnvironmentId              int                                 `json:"envId"`
+	WorkflowId                 int                                 `json:"workflowId"`
+	WorkflowRunnerId           int                                 `json:"workflowRunnerId"`
+	CdPipelineId               int                                 `json:"cdPipelineId"`
+	TriggeredBy                int32                               `json:"triggeredBy"`
+	StageYaml                  string                              `json:"stageYaml"`
+	ArtifactLocation           string                              `json:"artifactLocation"`
+	ArtifactBucket             string                              `json:"ciArtifactBucket"`
+	ArtifactFileName           string                              `json:"ciArtifactFileName"`
+	ArtifactRegion             string                              `json:"ciArtifactRegion"`
+	CiProjectDetails           []CiProjectDetails                  `json:"ciProjectDetails"`
+	CiArtifactDTO              CiArtifactDTO                       `json:"ciArtifactDTO"`
+	Namespace                  string                              `json:"namespace"`
+	WorkflowNamePrefix         string                              `json:"workflowNamePrefix"`
+	CdImage                    string                              `json:"cdImage"`
+	ActiveDeadlineSeconds      int64                               `json:"activeDeadlineSeconds"`
+	StageType                  string                              `json:"stageType"`
+	DockerUsername             string                              `json:"dockerUsername"`
+	DockerPassword             string                              `json:"dockerPassword"`
+	AwsRegion                  string                              `json:"awsRegion"`
+	SecretKey                  string                              `json:"secretKey"`
+	AccessKey                  string                              `json:"accessKey"`
+	DockerConnection           string                              `json:"dockerConnection"`
+	DockerCert                 string                              `json:"dockerCert"`
+	CdCacheLocation            string                              `json:"cdCacheLocation"`
+	CdCacheRegion              string                              `json:"cdCacheRegion"`
+	DockerRegistryType         string                              `json:"dockerRegistryType"`
+	DockerRegistryURL          string                              `json:"dockerRegistryURL"`
+	OrchestratorHost           string                              `json:"orchestratorHost"`
+	OrchestratorToken          string                              `json:"orchestratorToken"`
+	IsExtRun                   bool                                `json:"isExtRun"`
+	ExtraEnvironmentVariables  map[string]string                   `json:"extraEnvironmentVariables"`
+	BlobStorageConfigured      bool                                `json:"blobStorageConfigured"`
+	BlobStorageS3Config        *blob_storage.BlobStorageS3Config   `json:"blobStorageS3Config"`
+	CloudProvider              blob_storage.BlobStorageType        `json:"cloudProvider"`
+	AzureBlobConfig            *blob_storage.AzureBlobConfig       `json:"azureBlobConfig"`
+	GcpBlobConfig              *blob_storage.GcpBlobConfig         `json:"gcpBlobConfig"`
+	DefaultAddressPoolBaseCidr string                              `json:"defaultAddressPoolBaseCidr"`
+	DefaultAddressPoolSize     int                                 `json:"defaultAddressPoolSize"`
+	DeploymentTriggeredBy      string                              `json:"deploymentTriggeredBy,omitempty"`
+	DeploymentTriggerTime      time.Time                           `json:"deploymentTriggerTime,omitempty"`
+	DeploymentReleaseCounter   int                                 `json:"deploymentReleaseCounter,omitempty"`
+	WorkflowExecutor           pipelineConfig.WorkflowExecutorType `json:"workflowExecutor"`
 }
 
 const PRE = "PRE"
@@ -121,16 +124,19 @@ func NewCdWorkflowServiceImpl(Logger *zap.SugaredLogger,
 	envRepository repository.EnvironmentRepository,
 	cdConfig *CdConfig,
 	appService app.AppService,
-	globalCMCSService GlobalCMCSService) *CdWorkflowServiceImpl {
+	globalCMCSService GlobalCMCSService,
+	argoWorkflowExecutor ArgoWorkflowExecutor) *CdWorkflowServiceImpl {
 	return &CdWorkflowServiceImpl{Logger: Logger,
-		config:            cdConfig.ClusterConfig,
-		cdConfig:          cdConfig,
-		appService:        appService,
-		envRepository:     envRepository,
-		globalCMCSService: globalCMCSService}
+		config:               cdConfig.ClusterConfig,
+		cdConfig:             cdConfig,
+		appService:           appService,
+		envRepository:        envRepository,
+		globalCMCSService:    globalCMCSService,
+		argoWorkflowExecutor: argoWorkflowExecutor}
 }
 
-func (impl *CdWorkflowServiceImpl) SubmitWorkflow(workflowRequest *CdWorkflowRequest, pipeline *pipelineConfig.Pipeline, env *repository.Environment) (*v1alpha1.Workflow, error) {
+func (impl *CdWorkflowServiceImpl) SubmitWorkflow(workflowRequest *CdWorkflowRequest, pipeline *pipelineConfig.Pipeline, env *repository.Environment) error {
+
 	containerEnvVariables := []v12.EnvVar{}
 	if impl.cdConfig.CloudProvider == BLOB_STORAGE_S3 && impl.cdConfig.BlobStorageS3AccessKey != "" {
 		miniCred := []v12.EnvVar{{Name: "AWS_ACCESS_KEY_ID", Value: impl.cdConfig.BlobStorageS3AccessKey}, {Name: "AWS_SECRET_ACCESS_KEY", Value: impl.cdConfig.BlobStorageS3SecretKey}}
@@ -144,533 +150,178 @@ func (impl *CdWorkflowServiceImpl) SubmitWorkflow(workflowRequest *CdWorkflowReq
 	}
 	workflowJson, err := json.Marshal(&ciCdTriggerEvent)
 	if err != nil {
-		impl.Logger.Errorw("err", err)
-		return nil, err
+		impl.Logger.Errorw("error occurred while marshalling ciCdTriggerEvent", "error", err)
+		return err
 	}
 
 	privileged := true
 	storageConfigured := workflowRequest.BlobStorageConfigured
-	archiveLogs := storageConfigured
-
-	limitCpu := impl.cdConfig.LimitCpu
-	limitMem := impl.cdConfig.LimitMem
-
-	reqCpu := impl.cdConfig.ReqCpu
-	reqMem := impl.cdConfig.ReqMem
 	ttl := int32(impl.cdConfig.BuildLogTTLValue)
+	workflowTemplate := bean3.WorkflowTemplate{}
+	workflowTemplate.TTLValue = &ttl
+	workflowTemplate.WorkflowId = workflowRequest.WorkflowId
+	workflowTemplate.WorkflowRunnerId = workflowRequest.WorkflowRunnerId
+	workflowTemplate.WorkflowRequestJson = string(workflowJson)
 
-	entryPoint := CD_WORKFLOW_NAME
-
-	steps := make([]v1alpha1.ParallelSteps, 0)
-	volumes := make([]v12.Volume, 0)
-	templates := make([]v1alpha1.Template, 0)
-
-	var globalCmCsConfigs []*GlobalCMCSDto
+	var globalCmCsConfigs []*bean3.GlobalCMCSDto
+	var workflowConfigMaps []bean.ConfigSecretMap
+	var workflowSecrets []bean.ConfigSecretMap
 
 	if !workflowRequest.IsExtRun {
-		globalCmCsConfigs, err = impl.globalCMCSService.FindAllActiveByPipelineType(repository2.PIPELINE_TYPE_CD)
 		// inject global variables only if IsExtRun is false
+		globalCmCsConfigs, err = impl.globalCMCSService.FindAllActiveByPipelineType(repository2.PIPELINE_TYPE_CD)
 		if err != nil {
 			impl.Logger.Errorw("error in getting all global cm/cs config", "err", err)
-			return nil, err
-		}
-		if len(globalCmCsConfigs) > 0 {
-			entryPoint = CD_WORKFLOW_WITH_STAGES
+			return err
 		}
 		for i := range globalCmCsConfigs {
 			globalCmCsConfigs[i].Name = fmt.Sprintf("%s-%s-%s", strings.ToLower(globalCmCsConfigs[i].Name), strconv.Itoa(workflowRequest.WorkflowRunnerId), CD_WORKFLOW_NAME)
 		}
 
-		err = impl.globalCMCSService.AddTemplatesForGlobalSecretsInWorkflowTemplate(globalCmCsConfigs, &steps, &volumes, &templates)
+		workflowConfigMaps, workflowSecrets, err = GetFromGlobalCmCsDtos(globalCmCsConfigs)
 		if err != nil {
 			impl.Logger.Errorw("error in creating templates for global secrets", "err", err)
 		}
 	}
 
-	preStageConfigMapSecretsJson := pipeline.PreStageConfigMapSecretNames
-	postStageConfigMapSecretsJson := pipeline.PostStageConfigMapSecretNames
-
-	existingConfigMap, existingSecrets, err := impl.appService.GetCmSecretNew(workflowRequest.AppId, workflowRequest.EnvironmentId)
+	cdPipelineLevelConfigMaps, cdPipelineLevelSecrets, err := impl.getConfiguredCmCs(pipeline, workflowRequest.StageType)
 	if err != nil {
-		impl.Logger.Errorw("failed to get configmap data", "err", err)
-		return nil, err
+		impl.Logger.Errorw("error occurred while fetching pipeline configured cm and cs", "pipelineId", pipeline.Id, "err", err)
+		return err
 	}
-	impl.Logger.Debugw("existing cm sec", "cm", existingConfigMap, "sec", existingSecrets)
 
-	preStageConfigmapSecrets := bean2.PreStageConfigMapSecretNames{}
-	err = json.Unmarshal([]byte(preStageConfigMapSecretsJson), &preStageConfigmapSecrets)
-	if err != nil {
-		impl.Logger.Error(err)
-		return nil, err
-	}
-	postStageConfigmapSecrets := bean2.PostStageConfigMapSecretNames{}
-	err = json.Unmarshal([]byte(postStageConfigMapSecretsJson), &postStageConfigmapSecrets)
+	existingConfigMap, existingSecrets, err := impl.appService.GetCmSecretNew(workflowRequest.AppId, workflowRequest.EnvironmentId)
 	if err != nil {
-		impl.Logger.Error(err)
-		return nil, err
-	}
-
-	cdPipelineLevelConfigMaps := make(map[string]bool)
-	cdPipelineLevelSecrets := make(map[string]bool)
-	//cdPipelineLevelSecrets := make(map[string]bool)
-
-	if workflowRequest.StageType == PRE {
-		for _, cm := range preStageConfigmapSecrets.ConfigMaps {
-			cdPipelineLevelConfigMaps[cm] = true
-		}
-		for _, secret := range preStageConfigmapSecrets.Secrets {
-			cdPipelineLevelSecrets[secret] = true
-		}
-	} else {
-		for _, cm := range postStageConfigmapSecrets.ConfigMaps {
-			cdPipelineLevelConfigMaps[cm] = true
-		}
-		for _, secret := range postStageConfigmapSecrets.Secrets {
-			cdPipelineLevelSecrets[secret] = true
-		}
+		impl.Logger.Errorw("failed to get configmap data", "err", err)
+		return err
 	}
+	impl.Logger.Debugw("existing cm", "pipelineId", pipeline.Id, "cm", existingConfigMap)
 
-	configMaps := bean.ConfigMapJson{}
 	for _, cm := range existingConfigMap.Maps {
-		if cm.External {
-			continue
-		}
 		if _, ok := cdPipelineLevelConfigMaps[cm.Name]; ok {
-			configMaps.Maps = append(configMaps.Maps, cm)
+			if !cm.External {
+				cm.Name = cm.Name + "-" + strconv.Itoa(workflowRequest.WorkflowId) + "-" + strconv.Itoa(workflowRequest.WorkflowRunnerId)
+			}
+			workflowConfigMaps = append(workflowConfigMaps, cm)
 		}
 	}
-	for i := range configMaps.Maps {
-		configMaps.Maps[i].Name = configMaps.Maps[i].Name + "-" + strconv.Itoa(workflowRequest.WorkflowId) + "-" + strconv.Itoa(workflowRequest.WorkflowRunnerId)
-	}
 
-	secrets := bean.ConfigSecretJson{}
-	for _, s := range existingSecrets.Secrets {
-		if s.External {
-			continue
-		}
-		if _, ok := cdPipelineLevelSecrets[s.Name]; ok {
-			secrets.Secrets = append(secrets.Secrets, s)
+	for _, secret := range existingSecrets.Secrets {
+		if _, ok := cdPipelineLevelSecrets[secret.Name]; ok {
+			if !secret.External {
+				secret.Name = secret.Name + "-" + strconv.Itoa(workflowRequest.WorkflowId) + "-" + strconv.Itoa(workflowRequest.WorkflowRunnerId)
+			}
+			workflowSecrets = append(workflowSecrets, *secret)
 		}
 	}
-	for i := range configMaps.Maps {
-		configMaps.Maps[i].Name = configMaps.Maps[i].Name + "-" + strconv.Itoa(workflowRequest.WorkflowId) + "-" + strconv.Itoa(workflowRequest.WorkflowRunnerId)
-	}
-	for i := range secrets.Secrets {
-		secrets.Secrets[i].Name = secrets.Secrets[i].Name + "-" + strconv.Itoa(workflowRequest.WorkflowId) + "-" + strconv.Itoa(workflowRequest.WorkflowRunnerId)
-	}
 
-	configsMapping := make(map[string]string)
-	secretsMapping := make(map[string]string)
+	workflowTemplate.ConfigMaps = workflowConfigMaps
+	workflowTemplate.Secrets = workflowSecrets
 
-	if len(configMaps.Maps) > 0 {
-		entryPoint = CD_WORKFLOW_WITH_STAGES
-		for i, cm := range configMaps.Maps {
-			var datamap map[string]string
-			if err := json.Unmarshal(cm.Data, &datamap); err != nil {
-				impl.Logger.Errorw("error while unmarshal data", "err", err)
-				return nil, err
-			}
-			ownerDelete := true
-			cmBody := v12.ConfigMap{
-				TypeMeta: v1.TypeMeta{
-					Kind:       "ConfigMap",
-					APIVersion: "v1",
-				},
-				ObjectMeta: v1.ObjectMeta{
-					Name: cm.Name,
-					OwnerReferences: []v1.OwnerReference{{
-						APIVersion:         "argoproj.io/v1alpha1",
-						Kind:               "Workflow",
-						Name:               "{{workflow.name}}",
-						UID:                "{{workflow.uid}}",
-						BlockOwnerDeletion: &ownerDelete,
-					}},
-				},
-				Data: datamap,
-			}
-			cmJson, err := json.Marshal(cmBody)
-			if err != nil {
-				impl.Logger.Errorw("error in building json", "err", err)
-				return nil, err
-			}
-			configsMapping[cm.Name] = string(cmJson)
-
-			if cm.Type == "volume" {
-				volumes = append(volumes, v12.Volume{
-					Name: cm.Name + "-vol",
-					VolumeSource: v12.VolumeSource{
-						ConfigMap: &v12.ConfigMapVolumeSource{
-							LocalObjectReference: v12.LocalObjectReference{
-								Name: cm.Name,
-							},
-						},
-					},
-				})
-			}
-			steps = append(steps, v1alpha1.ParallelSteps{
-				Steps: []v1alpha1.WorkflowStep{
-					{
-						Name:     "create-env-cm-" + strconv.Itoa(i),
-						Template: "cm-" + strconv.Itoa(i),
-					},
-				},
-			})
-		}
-	}
+	workflowTemplate.ServiceAccountName = impl.cdConfig.WorkflowServiceAccount
+	workflowTemplate.NodeSelector = map[string]string{impl.cdConfig.TaintKey: impl.cdConfig.TaintValue}
+	workflowTemplate.Tolerations = []v12.Toleration{{Key: impl.cdConfig.TaintKey, Value: impl.cdConfig.TaintValue, Operator: v12.TolerationOpEqual, Effect: v12.TaintEffectNoSchedule}}
+	workflowTemplate.Volumes = ExtractVolumesFromCmCs(workflowConfigMaps, workflowSecrets)
+	workflowTemplate.ArchiveLogs = storageConfigured
+	workflowTemplate.RestartPolicy = v12.RestartPolicyNever
 
-	if len(secrets.Secrets) > 0 {
-		entryPoint = CD_WORKFLOW_WITH_STAGES
-		for i, s := range secrets.Secrets {
-			var datamap map[string][]byte
-			if err := json.Unmarshal(s.Data, &datamap); err != nil {
-				impl.Logger.Errorw("error while unmarshal data", "err", err)
-				return nil, err
-			}
-			ownerDelete := true
-			secretObject := v12.Secret{
-				TypeMeta: v1.TypeMeta{
-					Kind:       "Secret",
-					APIVersion: "v1",
-				},
-				ObjectMeta: v1.ObjectMeta{
-					Name: s.Name,
-					OwnerReferences: []v1.OwnerReference{{
-						APIVersion:         "argoproj.io/v1alpha1",
-						Kind:               "Workflow",
-						Name:               "{{workflow.name}}",
-						UID:                "{{workflow.uid}}",
-						BlockOwnerDeletion: &ownerDelete,
-					}},
-				},
-				Data: datamap,
-				Type: "Opaque",
-			}
-			secretJson, err := json.Marshal(secretObject)
-			if err != nil {
-				impl.Logger.Errorw("error in building json", "err", err)
-				return nil, err
-			}
-			secretsMapping[s.Name] = string(secretJson)
-			if s.Type == "volume" {
-				volumes = append(volumes, v12.Volume{
-					Name: s.Name + "-vol",
-					VolumeSource: v12.VolumeSource{
-						Secret: &v12.SecretVolumeSource{
-							SecretName: s.Name,
-						},
-					},
-				})
-			}
-			steps = append(steps, v1alpha1.ParallelSteps{
-				Steps: []v1alpha1.WorkflowStep{
-					{
-						Name:     "create-env-sec-" + strconv.Itoa(i),
-						Template: "sec-" + strconv.Itoa(i),
-					},
-				},
-			})
-		}
+	if len(impl.cdConfig.NodeLabel) > 0 {
+		workflowTemplate.NodeSelector = impl.cdConfig.NodeLabel
 	}
 
-	if len(configsMapping) > 0 {
-		for i, cm := range configMaps.Maps {
-			templates = append(templates, v1alpha1.Template{
-				Name: "cm-" + strconv.Itoa(i),
-				Resource: &v1alpha1.ResourceTemplate{
-					Action:            "create",
-					SetOwnerReference: true,
-					Manifest:          configsMapping[cm.Name],
-				},
-			})
-		}
-	}
-	if len(secretsMapping) > 0 {
-		for i, s := range secrets.Secrets {
-			templates = append(templates, v1alpha1.Template{
-				Name: "sec-" + strconv.Itoa(i),
-				Resource: &v1alpha1.ResourceTemplate{
-					Action:            "create",
-					SetOwnerReference: true,
-					Manifest:          secretsMapping[s.Name],
-				},
-			})
-		}
-	}
-	steps = append(steps, v1alpha1.ParallelSteps{
-		Steps: []v1alpha1.WorkflowStep{
-			{
-				Name:     "run-wf",
-				Template: CD_WORKFLOW_NAME,
-			},
+	limitCpu := impl.cdConfig.LimitCpu
+	limitMem := impl.cdConfig.LimitMem
+	reqCpu := impl.cdConfig.ReqCpu
+	reqMem := impl.cdConfig.ReqMem
+
+	workflowMainContainer := v12.Container{
+		Env:   containerEnvVariables,
+		Name:  common.MainContainerName,
+		Image: workflowRequest.CdImage,
+		Args:  []string{string(workflowJson)},
+		SecurityContext: &v12.SecurityContext{
+			Privileged: &privileged,
 		},
-	})
-	templates = append(templates, v1alpha1.Template{
-		Name:  CD_WORKFLOW_WITH_STAGES,
-		Steps: steps,
-	})
-
-	cdTemplate := v1alpha1.Template{
-		Name: "cd",
-		Container: &v12.Container{
-			Env:   containerEnvVariables,
-			Image: workflowRequest.CdImage,
-			Args:  []string{string(workflowJson)},
-			SecurityContext: &v12.SecurityContext{
-				Privileged: &privileged,
+		Resources: v12.ResourceRequirements{
+			Limits: v12.ResourceList{
+				v12.ResourceCPU:    resource.MustParse(limitCpu),
+				v12.ResourceMemory: resource.MustParse(limitMem),
 			},
-			Resources: v12.ResourceRequirements{
-				Limits: v12.ResourceList{
-					"cpu":    resource.MustParse(limitCpu),
-					"memory": resource.MustParse(limitMem),
-				},
-				Requests: v12.ResourceList{
-					"cpu":    resource.MustParse(reqCpu),
-					"memory": resource.MustParse(reqMem),
-				},
+			Requests: v12.ResourceList{
+				v12.ResourceCPU:    resource.MustParse(reqCpu),
+				v12.ResourceMemory: resource.MustParse(reqMem),
 			},
 		},
-		ActiveDeadlineSeconds: &intstr.IntOrString{
-			IntVal: int32(workflowRequest.ActiveDeadlineSeconds),
-		},
-		ArchiveLocation: &v1alpha1.ArtifactLocation{
-			ArchiveLogs: &archiveLogs,
-		},
 	}
+	UpdateContainerEnvsFromCmCs(&workflowMainContainer, workflowConfigMaps, workflowSecrets)
 
-	if impl.cdConfig.UseBlobStorageConfigInCdWorkflow || !workflowRequest.IsExtRun {
-		var s3Artifact *v1alpha1.S3Artifact
-		var gcsArtifact *v1alpha1.GCSArtifact
-		blobStorageS3Config := workflowRequest.BlobStorageS3Config
-		gcpBlobConfig := workflowRequest.GcpBlobConfig
-		cloudStorageKey := impl.cdConfig.DefaultBuildLogsKeyPrefix + "/" + workflowRequest.WorkflowNamePrefix
-		if storageConfigured && blobStorageS3Config != nil {
-			s3CompatibleEndpointUrl := blobStorageS3Config.EndpointUrl
-			if s3CompatibleEndpointUrl == "" {
-				s3CompatibleEndpointUrl = "s3.amazonaws.com"
-			} else {
-				parsedUrl, err := url.Parse(s3CompatibleEndpointUrl)
-				if err != nil {
-					impl.Logger.Errorw("error occurred while parsing s3CompatibleEndpointUrl, ", "s3CompatibleEndpointUrl", s3CompatibleEndpointUrl, "err", err)
-				} else {
-					s3CompatibleEndpointUrl = parsedUrl.Host
-				}
-			}
-			isInsecure := blobStorageS3Config.IsInSecure
-			var accessKeySelector *v12.SecretKeySelector
-			var secretKeySelector *v12.SecretKeySelector
-			if blobStorageS3Config.AccessKey != "" {
-				accessKeySelector = &v12.SecretKeySelector{
-					Key: "accessKey",
-					LocalObjectReference: v12.LocalObjectReference{
-						Name: "workflow-minio-cred",
-					},
-				}
-				secretKeySelector = &v12.SecretKeySelector{
-					Key: "secretKey",
-					LocalObjectReference: v12.LocalObjectReference{
-						Name: "workflow-minio-cred",
-					},
-				}
-			}
-			s3Artifact = &v1alpha1.S3Artifact{
-				Key: cloudStorageKey,
-				S3Bucket: v1alpha1.S3Bucket{
-					Endpoint:        s3CompatibleEndpointUrl,
-					AccessKeySecret: accessKeySelector,
-					SecretKeySecret: secretKeySelector,
-					Bucket:          blobStorageS3Config.CiLogBucketName,
-					Insecure:        &isInsecure,
-				},
-			}
-			if blobStorageS3Config.CiLogRegion != "" {
-				//TODO checking for Azure
-				s3Artifact.Region = blobStorageS3Config.CiLogRegion
-			}
-		} else if storageConfigured && gcpBlobConfig != nil {
-			gcsArtifact = &v1alpha1.GCSArtifact{
-				Key: cloudStorageKey,
-				GCSBucket: v1alpha1.GCSBucket{
-					Bucket: gcpBlobConfig.LogBucketName,
-					ServiceAccountKeySecret: &v12.SecretKeySelector{
-						Key: "secretKey",
-						LocalObjectReference: v12.LocalObjectReference{
-							Name: "workflow-minio-cred",
-						},
-					},
-				},
-			}
-		}
-
-		// set in ArchiveLocation
-		cdTemplate.ArchiveLocation.S3 = s3Artifact
-		cdTemplate.ArchiveLocation.GCS = gcsArtifact
+	impl.updateBlobStorageConfig(workflowRequest, &workflowTemplate, storageConfigured)
+	workflowTemplate.Containers = []v12.Container{workflowMainContainer}
+	workflowTemplate.WorkflowNamePrefix = workflowRequest.WorkflowNamePrefix
+	workflowTemplate.WfControllerInstanceID = impl.cdConfig.WfControllerInstanceID
+	workflowTemplate.ActiveDeadlineSeconds = &workflowRequest.ActiveDeadlineSeconds
+	workflowTemplate.Namespace = workflowRequest.Namespace
+	if workflowRequest.IsExtRun {
+		workflowTemplate.ClusterConfig = env.Cluster.GetClusterConfig()
+	} else {
+		workflowTemplate.ClusterConfig = impl.config
 	}
-
-	if !workflowRequest.IsExtRun {
-		for _, config := range globalCmCsConfigs {
-			if config.Type == repository2.VOLUME_CONFIG {
-				cdTemplate.Container.VolumeMounts = append(cdTemplate.Container.VolumeMounts, v12.VolumeMount{
-					Name:      config.Name + "-vol",
-					MountPath: config.MountPath,
-				})
-			} else if config.Type == repository2.ENVIRONMENT_CONFIG {
-				if config.ConfigType == repository2.CM_TYPE_CONFIG {
-					cdTemplate.Container.EnvFrom = append(cdTemplate.Container.EnvFrom, v12.EnvFromSource{
-						ConfigMapRef: &v12.ConfigMapEnvSource{
-							LocalObjectReference: v12.LocalObjectReference{
-								Name: config.Name,
-							},
-						},
-					})
-				} else if config.ConfigType == repository2.CS_TYPE_CONFIG {
-					cdTemplate.Container.EnvFrom = append(cdTemplate.Container.EnvFrom, v12.EnvFromSource{
-						SecretRef: &v12.SecretEnvSource{
-							LocalObjectReference: v12.LocalObjectReference{
-								Name: config.Name,
-							},
-						},
-					})
-				}
-			}
-		}
+	workflowExecutor := impl.getWorkflowExecutor(workflowRequest.WorkflowExecutor)
+	if workflowExecutor == nil {
+		return errors.New("workflow executor not found")
 	}
+	return workflowExecutor.ExecuteWorkflow(workflowTemplate)
+}
 
-	for _, cm := range configMaps.Maps {
-		if cm.Type == "environment" {
-			cdTemplate.Container.EnvFrom = append(cdTemplate.Container.EnvFrom, v12.EnvFromSource{
-				ConfigMapRef: &v12.ConfigMapEnvSource{
-					LocalObjectReference: v12.LocalObjectReference{
-						Name: cm.Name,
-					},
-				},
-			})
-		} else if cm.Type == "volume" {
-			cdTemplate.Container.VolumeMounts = append(cdTemplate.Container.VolumeMounts, v12.VolumeMount{
-				Name:      cm.Name + "-vol",
-				MountPath: cm.MountPath,
-			})
-		}
-	}
+func (impl *CdWorkflowServiceImpl) updateBlobStorageConfig(workflowRequest *CdWorkflowRequest, workflowTemplate *bean3.WorkflowTemplate, storageConfigured bool) {
+	workflowTemplate.BlobStorageConfigured = storageConfigured && (impl.cdConfig.UseBlobStorageConfigInCdWorkflow || !workflowRequest.IsExtRun)
+	workflowTemplate.BlobStorageS3Config = workflowRequest.BlobStorageS3Config
+	workflowTemplate.AzureBlobConfig = workflowRequest.AzureBlobConfig
+	workflowTemplate.GcpBlobConfig = workflowRequest.GcpBlobConfig
+	workflowTemplate.CloudStorageKey = impl.cdConfig.DefaultBuildLogsKeyPrefix + "/" + workflowRequest.WorkflowNamePrefix
+}
 
-	// Adding external config map reference in workflow template
-	for _, cm := range existingConfigMap.Maps {
-		if _, ok := cdPipelineLevelConfigMaps[cm.Name]; ok {
-			if cm.External {
-				if cm.Type == "environment" {
-					cdTemplate.Container.EnvFrom = append(cdTemplate.Container.EnvFrom, v12.EnvFromSource{
-						ConfigMapRef: &v12.ConfigMapEnvSource{
-							LocalObjectReference: v12.LocalObjectReference{
-								Name: cm.Name,
-							},
-						},
-					})
-				} else if cm.Type == "volume" {
-					cdTemplate.Container.VolumeMounts = append(cdTemplate.Container.VolumeMounts, v12.VolumeMount{
-						Name:      cm.Name,
-						MountPath: cm.MountPath,
-					})
-				}
-			}
-		}
+func (impl *CdWorkflowServiceImpl) getWorkflowExecutor(executorType pipelineConfig.WorkflowExecutorType) WorkflowExecutor {
+	if executorType == pipelineConfig.WORKFLOW_EXECUTOR_TYPE_AWF {
+		return impl.argoWorkflowExecutor
 	}
+	impl.Logger.Warnw("workflow executor not found", "type", executorType)
+	return nil
+}
 
-	for _, s := range secrets.Secrets {
-		if s.Type == "environment" {
-			cdTemplate.Container.EnvFrom = append(cdTemplate.Container.EnvFrom, v12.EnvFromSource{
-				SecretRef: &v12.SecretEnvSource{
-					LocalObjectReference: v12.LocalObjectReference{
-						Name: s.Name,
-					},
-				},
-			})
-		} else if s.Type == "volume" {
-			cdTemplate.Container.VolumeMounts = append(cdTemplate.Container.VolumeMounts, v12.VolumeMount{
-				Name:      s.Name + "-vol",
-				MountPath: s.MountPath,
-			})
-		}
-	}
+func (impl *CdWorkflowServiceImpl) getConfiguredCmCs(pipeline *pipelineConfig.Pipeline, stage string) (map[string]bool, map[string]bool, error) {
 
-	// Adding external secret reference in workflow template
-	for _, s := range existingSecrets.Secrets {
-		if _, ok := cdPipelineLevelSecrets[s.Name]; ok {
-			if s.External {
-				if s.Type == "environment" {
-					cdTemplate.Container.EnvFrom = append(cdTemplate.Container.EnvFrom, v12.EnvFromSource{
-						SecretRef: &v12.SecretEnvSource{
-							LocalObjectReference: v12.LocalObjectReference{
-								Name: s.Name,
-							},
-						},
-					})
-				} else if s.Type == "volume" {
-					cdTemplate.Container.VolumeMounts = append(cdTemplate.Container.VolumeMounts, v12.VolumeMount{
-						Name:      s.Name,
-						MountPath: s.MountPath,
-					})
-				}
-			}
-		}
-	}
+	cdPipelineLevelConfigMaps := make(map[string]bool)
+	cdPipelineLevelSecrets := make(map[string]bool)
 
-	templates = append(templates, cdTemplate)
-	var (
-		cdWorkflow = v1alpha1.Workflow{
-			ObjectMeta: v1.ObjectMeta{
-				GenerateName: workflowRequest.WorkflowNamePrefix + "-",
-				Annotations:  map[string]string{"workflows.argoproj.io/controller-instanceid": impl.cdConfig.WfControllerInstanceID},
-				Labels:       map[string]string{"devtron.ai/workflow-purpose": "cd"},
-			},
-			Spec: v1alpha1.WorkflowSpec{
-				ServiceAccountName: impl.cdConfig.WorkflowServiceAccount,
-				NodeSelector:       map[string]string{impl.cdConfig.TaintKey: impl.cdConfig.TaintValue},
-				Tolerations:        []v12.Toleration{{Key: impl.cdConfig.TaintKey, Value: impl.cdConfig.TaintValue, Operator: v12.TolerationOpEqual, Effect: v12.TaintEffectNoSchedule}},
-				Entrypoint:         entryPoint,
-				TTLStrategy: &v1alpha1.TTLStrategy{
-					SecondsAfterCompletion: &ttl,
-				},
-				Templates: templates,
-				Volumes:   volumes,
-			},
+	if stage == "PRE" {
+		preStageConfigMapSecretsJson := pipeline.PreStageConfigMapSecretNames
+		preStageConfigmapSecrets := bean2.PreStageConfigMapSecretNames{}
+		err := json.Unmarshal([]byte(preStageConfigMapSecretsJson), &preStageConfigmapSecrets)
+		if err != nil {
+			return cdPipelineLevelConfigMaps, cdPipelineLevelSecrets, err
 		}
-	)
-
-	//
-	if len(impl.cdConfig.NodeLabel) > 0 {
-		cdWorkflow.Spec.NodeSelector = impl.cdConfig.NodeLabel
-	}
-	//
-
-	wfTemplate, err := json.Marshal(cdWorkflow)
-	if err != nil {
-		impl.Logger.Error(err)
-	}
-	impl.Logger.Debug("---->", string(wfTemplate))
-
-	var wfClient v1alpha12.WorkflowInterface
-
-	if workflowRequest.IsExtRun {
-		serverUrl := env.Cluster.ServerUrl
-		configMap := env.Cluster.Config
-		bearerToken := configMap["bearer_token"]
-		wfClient, err = impl.getRuntimeEnvClientInstance(workflowRequest.Namespace, bearerToken, serverUrl)
-	}
-	if wfClient == nil {
-		wfClient, err = impl.getClientInstance(workflowRequest.Namespace)
+		for _, cm := range preStageConfigmapSecrets.ConfigMaps {
+			cdPipelineLevelConfigMaps[cm] = true
+		}
+		for _, secret := range preStageConfigmapSecrets.Secrets {
+			cdPipelineLevelSecrets[secret] = true
+		}
+	} else {
+		postStageConfigMapSecretsJson := pipeline.PostStageConfigMapSecretNames
+		postStageConfigmapSecrets := bean2.PostStageConfigMapSecretNames{}
+		err := json.Unmarshal([]byte(postStageConfigMapSecretsJson), &postStageConfigmapSecrets)
 		if err != nil {
-			impl.Logger.Errorw("cannot build wf client", "err", err)
-			return nil, err
+			return cdPipelineLevelConfigMaps, cdPipelineLevelSecrets, err
+		}
+		for _, cm := range postStageConfigmapSecrets.ConfigMaps {
+			cdPipelineLevelConfigMaps[cm] = true
+		}
+		for _, secret := range postStageConfigmapSecrets.Secrets {
+			cdPipelineLevelSecrets[secret] = true
 		}
 	}
-
-	createdWf, err := wfClient.Create(context.Background(), &cdWorkflow, v1.CreateOptions{}) // submit the hello world workflow
-	if err != nil {
-		impl.Logger.Errorw("error in wf trigger", "err", err)
-		return nil, err
-	}
-	impl.Logger.Debugw("workflow submitted: ", "name", createdWf.Name)
-	impl.checkErr(err)
-	return createdWf, err
+	return cdPipelineLevelConfigMaps, cdPipelineLevelSecrets, nil
 }
 
 func (impl *CdWorkflowServiceImpl) GetWorkflow(name string, namespace string, url string, token string, isExtRun bool) (*v1alpha1.Workflow, error) {
diff --git a/pkg/pipeline/GlobalCMCSService.go b/pkg/pipeline/GlobalCMCSService.go
index 4fd24be07..71e7032c8 100644
--- a/pkg/pipeline/GlobalCMCSService.go
+++ b/pkg/pipeline/GlobalCMCSService.go
@@ -3,24 +3,20 @@ package pipeline
 import (
 	"encoding/json"
 	"fmt"
-	"github.com/argoproj/argo-workflows/v3/pkg/apis/workflow/v1alpha1"
 	"github.com/devtron-labs/devtron/internal/sql/repository"
+	"github.com/devtron-labs/devtron/pkg/pipeline/bean"
 	"github.com/devtron-labs/devtron/pkg/sql"
 	"github.com/go-pg/pg"
 	"go.uber.org/zap"
-	v12 "k8s.io/api/core/v1"
-	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"strconv"
 	"time"
 )
 
 type GlobalCMCSService interface {
-	Create(model *GlobalCMCSDto) (*GlobalCMCSDto, error)
+	Create(model *bean.GlobalCMCSDto) (*bean.GlobalCMCSDto, error)
 	UpdateDataById(config *GlobalCMCSDataUpdateDto) (*GlobalCMCSDataUpdateDto, error)
-	GetGlobalCMCSDataByConfigTypeAndName(configName string, configType string) (*GlobalCMCSDto, error)
-	FindAllActiveByPipelineType(pipelineType string) ([]*GlobalCMCSDto, error)
-	FindAllActive() ([]*GlobalCMCSDto, error)
-	AddTemplatesForGlobalSecretsInWorkflowTemplate(globalCmCsConfigs []*GlobalCMCSDto, steps *[]v1alpha1.ParallelSteps, volumes *[]v12.Volume, templates *[]v1alpha1.Template) error
+	GetGlobalCMCSDataByConfigTypeAndName(configName string, configType string) (*bean.GlobalCMCSDto, error)
+	FindAllActiveByPipelineType(pipelineType string) ([]*bean.GlobalCMCSDto, error)
+	FindAllActive() ([]*bean.GlobalCMCSDto, error)
 	DeleteById(id int) error
 }
 
@@ -37,19 +33,6 @@ func NewGlobalCMCSServiceImpl(logger *zap.SugaredLogger,
 	}
 }
 
-type GlobalCMCSDto struct {
-	Id         int    `json:"id"`
-	ConfigType string `json:"configType" validate:"oneof=CONFIGMAP SECRET"`
-	Name       string `json:"name"  validate:"required"`
-	Type       string `json:"type" validate:"oneof=environment volume"`
-	//map of key:value, example: '{ "a" : "b", "c" : "d"}'
-	Data               map[string]string `json:"data"  validate:"required"`
-	MountPath          string            `json:"mountPath"`
-	Deleted            bool              `json:"deleted"`
-	UserId             int32             `json:"-"`
-	SecretIngestionFor string            `json:"SecretIngestionFor"` // value can be one of [ci, cd, ci/cd]
-}
-
 type GlobalCMCSDataUpdateDto struct {
 	Id                 int               `json:"id"`
 	Data               map[string]string `json:"data"  validate:"required"`
@@ -57,7 +40,7 @@ type GlobalCMCSDataUpdateDto struct {
 	UserId             int32             `json:"-"`
 }
 
-func (impl *GlobalCMCSServiceImpl) validateGlobalCMCSData(config *GlobalCMCSDto) error {
+func (impl *GlobalCMCSServiceImpl) validateGlobalCMCSData(config *bean.GlobalCMCSDto) error {
 	sameNameConfig, err := impl.globalCMCSRepository.FindByConfigTypeAndName(config.ConfigType, config.Name)
 	if err != nil && err != pg.ErrNoRows {
 		impl.logger.Errorw("error in getting global cm/cs config by name and configType", "err", err, "configType", config.ConfigType, "name", config.Name)
@@ -85,7 +68,7 @@ func (impl *GlobalCMCSServiceImpl) validateGlobalCMCSData(config *GlobalCMCSDto)
 	return nil
 }
 
-func (impl *GlobalCMCSServiceImpl) Create(config *GlobalCMCSDto) (*GlobalCMCSDto, error) {
+func (impl *GlobalCMCSServiceImpl) Create(config *bean.GlobalCMCSDto) (*bean.GlobalCMCSDto, error) {
 
 	err := impl.validateGlobalCMCSData(config)
 	if err != nil {
@@ -152,15 +135,15 @@ func (impl *GlobalCMCSServiceImpl) UpdateDataById(config *GlobalCMCSDataUpdateDt
 	return config, nil
 }
 
-func (impl *GlobalCMCSServiceImpl) ConvertGlobalCmcsDbObjectToGlobalCmcsDto(GlobalCMCSDBObject []*repository.GlobalCMCS) []*GlobalCMCSDto {
-	var configDtos []*GlobalCMCSDto
+func (impl *GlobalCMCSServiceImpl) ConvertGlobalCmcsDbObjectToGlobalCmcsDto(GlobalCMCSDBObject []*repository.GlobalCMCS) []*bean.GlobalCMCSDto {
+	var configDtos []*bean.GlobalCMCSDto
 	for _, model := range GlobalCMCSDBObject {
 		data := make(map[string]string)
 		err := json.Unmarshal([]byte(model.Data), &data)
 		if err != nil {
 			impl.logger.Errorw("error in un-marshaling cm/cs data", "err", err)
 		}
-		configDto := &GlobalCMCSDto{
+		configDto := &bean.GlobalCMCSDto{
 			Id:         model.Id,
 			ConfigType: model.ConfigType,
 			Type:       model.Type,
@@ -173,7 +156,7 @@ func (impl *GlobalCMCSServiceImpl) ConvertGlobalCmcsDbObjectToGlobalCmcsDto(Glob
 	return configDtos
 }
 
-func (impl *GlobalCMCSServiceImpl) FindAllActiveByPipelineType(pipelineType string) ([]*GlobalCMCSDto, error) {
+func (impl *GlobalCMCSServiceImpl) FindAllActiveByPipelineType(pipelineType string) ([]*bean.GlobalCMCSDto, error) {
 	models, err := impl.globalCMCSRepository.FindAllActiveByPipelineType(pipelineType)
 	if err != nil && err != pg.ErrNoRows {
 		impl.logger.Errorw("err in getting all global cm/cs configs", "err", err)
@@ -183,7 +166,7 @@ func (impl *GlobalCMCSServiceImpl) FindAllActiveByPipelineType(pipelineType stri
 	return configDtos, nil
 }
 
-func (impl *GlobalCMCSServiceImpl) FindAllActive() ([]*GlobalCMCSDto, error) {
+func (impl *GlobalCMCSServiceImpl) FindAllActive() ([]*bean.GlobalCMCSDto, error) {
 	models, err := impl.globalCMCSRepository.FindAllActive()
 	if err != nil && err != pg.ErrNoRows {
 		impl.logger.Errorw("err in getting all global cm/cs configs", "err", err)
@@ -193,7 +176,7 @@ func (impl *GlobalCMCSServiceImpl) FindAllActive() ([]*GlobalCMCSDto, error) {
 	return configDtos, nil
 }
 
-func (impl *GlobalCMCSServiceImpl) GetGlobalCMCSDataByConfigTypeAndName(configName string, configType string) (*GlobalCMCSDto, error) {
+func (impl *GlobalCMCSServiceImpl) GetGlobalCMCSDataByConfigTypeAndName(configName string, configType string) (*bean.GlobalCMCSDto, error) {
 
 	model, err := impl.globalCMCSRepository.FindByConfigTypeAndName(configType, configName)
 	if err != nil {
@@ -205,7 +188,7 @@ func (impl *GlobalCMCSServiceImpl) GetGlobalCMCSDataByConfigTypeAndName(configNa
 	if err != nil {
 		impl.logger.Errorw("error in un-marshaling cm/cs data", "err", err)
 	}
-	GlobalCMCSDto := &GlobalCMCSDto{
+	GlobalCMCSDto := &bean.GlobalCMCSDto{
 		Id:                 model.Id,
 		ConfigType:         model.ConfigType,
 		Name:               model.Name,
@@ -218,127 +201,6 @@ func (impl *GlobalCMCSServiceImpl) GetGlobalCMCSDataByConfigTypeAndName(configNa
 	return GlobalCMCSDto, nil
 }
 
-func (impl *GlobalCMCSServiceImpl) AddTemplatesForGlobalSecretsInWorkflowTemplate(globalCmCsConfigs []*GlobalCMCSDto, steps *[]v1alpha1.ParallelSteps, volumes *[]v12.Volume, templates *[]v1alpha1.Template) error {
-
-	cmIndex := 0
-	csIndex := 0
-
-	for _, config := range globalCmCsConfigs {
-		if config.ConfigType == repository.CM_TYPE_CONFIG {
-			ownerDelete := true
-			cmBody := v12.ConfigMap{
-				TypeMeta: v1.TypeMeta{
-					Kind:       "ConfigMap",
-					APIVersion: "v1",
-				},
-				ObjectMeta: v1.ObjectMeta{
-					Name: config.Name,
-					OwnerReferences: []v1.OwnerReference{{
-						APIVersion:         "argoproj.io/v1alpha1",
-						Kind:               "Workflow",
-						Name:               "{{workflow.name}}",
-						UID:                "{{workflow.uid}}",
-						BlockOwnerDeletion: &ownerDelete,
-					}},
-				},
-				Data: config.Data,
-			}
-			cmJson, err := json.Marshal(cmBody)
-			if err != nil {
-				impl.logger.Errorw("error in building json", "err", err)
-				return err
-			}
-			if config.Type == repository.VOLUME_CONFIG {
-				*volumes = append(*volumes, v12.Volume{
-					Name: config.Name + "-vol",
-					VolumeSource: v12.VolumeSource{
-						ConfigMap: &v12.ConfigMapVolumeSource{
-							LocalObjectReference: v12.LocalObjectReference{
-								Name: config.Name,
-							},
-						},
-					},
-				})
-			}
-			*steps = append(*steps, v1alpha1.ParallelSteps{
-				Steps: []v1alpha1.WorkflowStep{
-					{
-						Name:     "create-env-cm-gb-" + strconv.Itoa(cmIndex),
-						Template: "cm-gb-" + strconv.Itoa(cmIndex),
-					},
-				},
-			})
-			*templates = append(*templates, v1alpha1.Template{
-				Name: "cm-gb-" + strconv.Itoa(cmIndex),
-				Resource: &v1alpha1.ResourceTemplate{
-					Action:            "create",
-					SetOwnerReference: true,
-					Manifest:          string(cmJson),
-				},
-			})
-			cmIndex++
-		} else if config.ConfigType == repository.CS_TYPE_CONFIG {
-			secretDataMap := make(map[string][]byte)
-			for key, value := range config.Data {
-				secretDataMap[key] = []byte(value)
-			}
-			ownerDelete := true
-			secretObject := v12.Secret{
-				TypeMeta: v1.TypeMeta{
-					Kind:       "Secret",
-					APIVersion: "v1",
-				},
-				ObjectMeta: v1.ObjectMeta{
-					Name: config.Name,
-					OwnerReferences: []v1.OwnerReference{{
-						APIVersion:         "argoproj.io/v1alpha1",
-						Kind:               "Workflow",
-						Name:               "{{workflow.name}}",
-						UID:                "{{workflow.uid}}",
-						BlockOwnerDeletion: &ownerDelete,
-					}},
-				},
-				Data: secretDataMap,
-				Type: "Opaque",
-			}
-			secretJson, err := json.Marshal(secretObject)
-			if err != nil {
-				impl.logger.Errorw("error in building json", "err", err)
-				return err
-			}
-			if config.Type == repository.VOLUME_CONFIG {
-				*volumes = append(*volumes, v12.Volume{
-					Name: config.Name + "-vol",
-					VolumeSource: v12.VolumeSource{
-						Secret: &v12.SecretVolumeSource{
-							SecretName: config.Name,
-						},
-					},
-				})
-			}
-			*steps = append(*steps, v1alpha1.ParallelSteps{
-				Steps: []v1alpha1.WorkflowStep{
-					{
-						Name:     "create-env-sec-gb-" + strconv.Itoa(csIndex),
-						Template: "sec-gb-" + strconv.Itoa(csIndex),
-					},
-				},
-			})
-			*templates = append(*templates, v1alpha1.Template{
-				Name: "sec-gb-" + strconv.Itoa(csIndex),
-				Resource: &v1alpha1.ResourceTemplate{
-					Action:            "create",
-					SetOwnerReference: true,
-					Manifest:          string(secretJson),
-				},
-			})
-			csIndex++
-		}
-	}
-
-	return nil
-}
-
 func (impl *GlobalCMCSServiceImpl) DeleteById(id int) error {
 
 	model, err := impl.globalCMCSRepository.FindById(id)
diff --git a/pkg/pipeline/PipelineBuilder.go b/pkg/pipeline/PipelineBuilder.go
index 37f13669a..0b882b727 100644
--- a/pkg/pipeline/PipelineBuilder.go
+++ b/pkg/pipeline/PipelineBuilder.go
@@ -3184,8 +3184,8 @@ func (impl PipelineBuilderImpl) GetCdPipelinesForAppAndEnv(appId int, envId int)
 }
 
 type ConfigMapSecretsResponse struct {
-	Maps    []bean2.Map `json:"maps"`
-	Secrets []bean2.Map `json:"secrets"`
+	Maps    []bean2.ConfigSecretMap `json:"maps"`
+	Secrets []bean2.ConfigSecretMap `json:"secrets"`
 }
 
 func (impl PipelineBuilderImpl) FetchConfigmapSecretsForCdStages(appId, envId, cdPipelineId int) (ConfigMapSecretsResponse, error) {
diff --git a/pkg/pipeline/WorkflowDagExecutor.go b/pkg/pipeline/WorkflowDagExecutor.go
index 621e921a4..1de1f85a6 100644
--- a/pkg/pipeline/WorkflowDagExecutor.go
+++ b/pkg/pipeline/WorkflowDagExecutor.go
@@ -422,10 +422,11 @@ func (impl *WorkflowDagExecutorImpl) TriggerPreStage(ctx context.Context, cdWf *
 			return err
 		}
 	}
+	cdWorkflowExecutorType := impl.cdConfig.CdWorkflowExecutorType
 	runner := &pipelineConfig.CdWorkflowRunner{
 		Name:               pipeline.Name,
 		WorkflowType:       bean.CD_WORKFLOW_TYPE_PRE,
-		ExecutorType:       pipelineConfig.WORKFLOW_EXECUTOR_TYPE_AWF,
+		ExecutorType:       cdWorkflowExecutorType,
 		Status:             pipelineConfig.WorkflowStarting, //starting
 		TriggeredBy:        triggeredBy,
 		StartedOn:          triggeredAt,
@@ -462,7 +463,7 @@ func (impl *WorkflowDagExecutorImpl) TriggerPreStage(ctx context.Context, cdWf *
 	}
 	cdStageWorkflowRequest.StageType = PRE
 	_, span = otel.Tracer("orchestrator").Start(ctx, "cdWorkflowService.SubmitWorkflow")
-	_, err = impl.cdWorkflowService.SubmitWorkflow(cdStageWorkflowRequest, pipeline, env)
+	err = impl.cdWorkflowService.SubmitWorkflow(cdStageWorkflowRequest, pipeline, env)
 	span.End()
 
 	err = impl.sendPreStageNotification(ctx, cdWf, pipeline)
@@ -514,7 +515,7 @@ func (impl *WorkflowDagExecutorImpl) TriggerPostStage(cdWf *pipelineConfig.CdWor
 	runner := &pipelineConfig.CdWorkflowRunner{
 		Name:               pipeline.Name,
 		WorkflowType:       bean.CD_WORKFLOW_TYPE_POST,
-		ExecutorType:       pipelineConfig.WORKFLOW_EXECUTOR_TYPE_AWF,
+		ExecutorType:       impl.cdConfig.CdWorkflowExecutorType,
 		Status:             pipelineConfig.WorkflowStarting,
 		TriggeredBy:        triggeredBy,
 		StartedOn:          triggeredAt,
@@ -544,7 +545,7 @@ func (impl *WorkflowDagExecutorImpl) TriggerPostStage(cdWf *pipelineConfig.CdWor
 		return err
 	}
 	cdStageWorkflowRequest.StageType = POST
-	_, err = impl.cdWorkflowService.SubmitWorkflow(cdStageWorkflowRequest, pipeline, env)
+	err = impl.cdWorkflowService.SubmitWorkflow(cdStageWorkflowRequest, pipeline, env)
 	if err != nil {
 		impl.logger.Errorw("error in submitting workflow", "err", err, "cdStageWorkflowRequest", cdStageWorkflowRequest, "pipeline", pipeline, "env", env)
 		return err
@@ -590,6 +591,8 @@ func (impl *WorkflowDagExecutorImpl) buildWFRequest(runner *pipelineConfig.CdWor
 		return nil, err
 	}
 
+	workflowExecutor := runner.ExecutorType
+
 	artifact, err := impl.ciArtifactRepository.Get(cdWf.CiArtifactId)
 	if err != nil {
 		return nil, err
@@ -728,6 +731,7 @@ func (impl *WorkflowDagExecutorImpl) buildWFRequest(runner *pipelineConfig.CdWor
 		OrchestratorHost:  impl.cdConfig.OrchestratorHost,
 		OrchestratorToken: impl.cdConfig.OrchestratorToken,
 		CloudProvider:     impl.cdConfig.CloudProvider,
+		WorkflowExecutor:  workflowExecutor,
 	}
 	extraEnvVariables := make(map[string]string)
 	env, err := impl.envRepository.FindById(cdPipeline.EnvironmentId)
diff --git a/pkg/pipeline/WorkflowService.go b/pkg/pipeline/WorkflowService.go
index 1624fc9f8..84ad00558 100644
--- a/pkg/pipeline/WorkflowService.go
+++ b/pkg/pipeline/WorkflowService.go
@@ -258,7 +258,7 @@ func (impl *WorkflowServiceImpl) SubmitWorkflow(workflowRequest *WorkflowRequest
 	volumes := make([]v12.Volume, 0)
 	templates := make([]v1alpha1.Template, 0)
 
-	err = impl.globalCMCSService.AddTemplatesForGlobalSecretsInWorkflowTemplate(globalCmCsConfigs, &steps, &volumes, &templates)
+	err = AddTemplatesForGlobalSecretsInWorkflowTemplate(globalCmCsConfigs, &steps, &volumes, &templates)
 	if err != nil {
 		impl.Logger.Errorw("error in creating templates for global secrets", "err", err)
 	}
diff --git a/pkg/pipeline/WorkflowUtils.go b/pkg/pipeline/WorkflowUtils.go
new file mode 100644
index 000000000..c39a3c520
--- /dev/null
+++ b/pkg/pipeline/WorkflowUtils.go
@@ -0,0 +1,251 @@
+package pipeline
+
+import (
+	"encoding/json"
+	"github.com/argoproj/argo-workflows/v3/pkg/apis/workflow/v1alpha1"
+	bean2 "github.com/devtron-labs/devtron/api/bean"
+	"github.com/devtron-labs/devtron/internal/sql/repository"
+	"github.com/devtron-labs/devtron/pkg/pipeline/bean"
+	"github.com/devtron-labs/devtron/util"
+	v12 "k8s.io/api/core/v1"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"strconv"
+)
+
+var ArgoWorkflowOwnerRef = v1.OwnerReference{APIVersion: "argoproj.io/v1alpha1", Kind: "Workflow", Name: "{{workflow.name}}", UID: "{{workflow.uid}}", BlockOwnerDeletion: &[]bool{true}[0]}
+
+type ConfigMapSecretDto struct {
+	Name     string
+	Data     map[string]string
+	OwnerRef v1.OwnerReference
+}
+
+func ExtractVolumesFromCmCs(configMaps []bean2.ConfigSecretMap, secrets []bean2.ConfigSecretMap) []v12.Volume {
+	var volumes []v12.Volume
+	configMapVolumes := extractVolumesFromConfigSecretMaps(true, configMaps)
+	secretVolumes := extractVolumesFromConfigSecretMaps(false, secrets)
+
+	for _, volume := range configMapVolumes {
+		volumes = append(volumes, volume)
+	}
+	for _, volume := range secretVolumes {
+		volumes = append(volumes, volume)
+	}
+	return volumes
+}
+
+func extractVolumesFromConfigSecretMaps(isCm bool, configSecretMaps []bean2.ConfigSecretMap) []v12.Volume {
+	var volumes []v12.Volume
+	for _, configSecretMap := range configSecretMaps {
+		if configSecretMap.Type != util.ConfigMapSecretUsageTypeVolume {
+			// not volume type so ignoring
+			continue
+		}
+		var volumeSource v12.VolumeSource
+		if isCm {
+			volumeSource = v12.VolumeSource{
+				ConfigMap: &v12.ConfigMapVolumeSource{
+					LocalObjectReference: v12.LocalObjectReference{
+						Name: configSecretMap.Name,
+					},
+				},
+			}
+		} else {
+			volumeSource = v12.VolumeSource{
+				Secret: &v12.SecretVolumeSource{
+					SecretName: configSecretMap.Name,
+				},
+			}
+		}
+		volumes = append(volumes, v12.Volume{
+			Name:         configSecretMap.Name + "-vol",
+			VolumeSource: volumeSource,
+		})
+	}
+	return volumes
+}
+
+func UpdateContainerEnvsFromCmCs(workflowMainContainer *v12.Container, configMaps []bean2.ConfigSecretMap, secrets []bean2.ConfigSecretMap) {
+	for _, configMap := range configMaps {
+		updateContainerEnvs(true, workflowMainContainer, configMap)
+	}
+
+	for _, secret := range secrets {
+		updateContainerEnvs(false, workflowMainContainer, secret)
+	}
+}
+
+func updateContainerEnvs(isCM bool, workflowMainContainer *v12.Container, configSecretMap bean2.ConfigSecretMap) {
+	if configSecretMap.Type == repository.VOLUME_CONFIG {
+		workflowMainContainer.VolumeMounts = append(workflowMainContainer.VolumeMounts, v12.VolumeMount{
+			Name:      configSecretMap.Name + "-vol",
+			MountPath: configSecretMap.MountPath,
+		})
+	} else if configSecretMap.Type == repository.ENVIRONMENT_CONFIG {
+		var envFrom v12.EnvFromSource
+		if isCM {
+			envFrom = v12.EnvFromSource{
+				ConfigMapRef: &v12.ConfigMapEnvSource{
+					LocalObjectReference: v12.LocalObjectReference{
+						Name: configSecretMap.Name,
+					},
+				},
+			}
+		} else {
+			envFrom = v12.EnvFromSource{
+				SecretRef: &v12.SecretEnvSource{
+					LocalObjectReference: v12.LocalObjectReference{
+						Name: configSecretMap.Name,
+					},
+				},
+			}
+		}
+		workflowMainContainer.EnvFrom = append(workflowMainContainer.EnvFrom, envFrom)
+	}
+}
+
+func GetConfigMapJson(configMapSecretDto ConfigMapSecretDto) (string, error) {
+	configMapBody := GetConfigMapBody(configMapSecretDto)
+	configMapJson, err := json.Marshal(configMapBody)
+	if err != nil {
+		return "", err
+	}
+	return string(configMapJson), err
+}
+
+func GetConfigMapBody(configMapSecretDto ConfigMapSecretDto) v12.ConfigMap {
+	return v12.ConfigMap{
+		TypeMeta: v1.TypeMeta{
+			Kind:       "ConfigMap",
+			APIVersion: "v1",
+		},
+		ObjectMeta: v1.ObjectMeta{
+			Name:            configMapSecretDto.Name,
+			OwnerReferences: []v1.OwnerReference{configMapSecretDto.OwnerRef},
+		},
+		Data: configMapSecretDto.Data,
+	}
+}
+
+func GetSecretJson(configMapSecretDto ConfigMapSecretDto) (string, error) {
+	secretBody := GetSecretBody(configMapSecretDto)
+	secretJson, err := json.Marshal(secretBody)
+	if err != nil {
+		return "", err
+	}
+	return string(secretJson), err
+}
+
+func GetSecretBody(configMapSecretDto ConfigMapSecretDto) v12.Secret {
+	secretDataMap := make(map[string][]byte)
+	for key, value := range configMapSecretDto.Data {
+		secretDataMap[key] = []byte(value)
+	}
+	return v12.Secret{
+		TypeMeta: v1.TypeMeta{
+			Kind:       "Secret",
+			APIVersion: "v1",
+		},
+		ObjectMeta: v1.ObjectMeta{
+			Name:            configMapSecretDto.Name,
+			OwnerReferences: []v1.OwnerReference{configMapSecretDto.OwnerRef},
+		},
+		Data: secretDataMap,
+		Type: "Opaque",
+	}
+}
+
+func GetFromGlobalCmCsDtos(globalCmCsConfigs []*bean.GlobalCMCSDto) ([]bean2.ConfigSecretMap, []bean2.ConfigSecretMap, error) {
+	workflowConfigMaps := make([]bean2.ConfigSecretMap, 0, len(globalCmCsConfigs))
+	workflowSecrets := make([]bean2.ConfigSecretMap, 0, len(globalCmCsConfigs))
+
+	for _, config := range globalCmCsConfigs {
+		configSecretMap, err := config.ConvertToConfigSecretMap()
+		if err != nil {
+			return workflowConfigMaps, workflowSecrets, err
+		}
+		if config.ConfigType == repository.CM_TYPE_CONFIG {
+			workflowConfigMaps = append(workflowConfigMaps, configSecretMap)
+		} else {
+			workflowSecrets = append(workflowSecrets, configSecretMap)
+		}
+	}
+	return workflowConfigMaps, workflowSecrets, nil
+}
+
+func AddTemplatesForGlobalSecretsInWorkflowTemplate(globalCmCsConfigs []*bean.GlobalCMCSDto, steps *[]v1alpha1.ParallelSteps, volumes *[]v12.Volume, templates *[]v1alpha1.Template) error {
+
+	cmIndex := 0
+	csIndex := 0
+	for _, config := range globalCmCsConfigs {
+		if config.ConfigType == repository.CM_TYPE_CONFIG {
+			cmJson, err := GetConfigMapJson(ConfigMapSecretDto{Name: config.Name, Data: config.Data, OwnerRef: ArgoWorkflowOwnerRef})
+			if err != nil {
+				return err
+			}
+			if config.Type == repository.VOLUME_CONFIG {
+				*volumes = append(*volumes, v12.Volume{
+					Name: config.Name + "-vol",
+					VolumeSource: v12.VolumeSource{
+						ConfigMap: &v12.ConfigMapVolumeSource{
+							LocalObjectReference: v12.LocalObjectReference{
+								Name: config.Name,
+							},
+						},
+					},
+				})
+			}
+			*steps = append(*steps, v1alpha1.ParallelSteps{
+				Steps: []v1alpha1.WorkflowStep{
+					{
+						Name:     "create-env-cm-gb-" + strconv.Itoa(cmIndex),
+						Template: "cm-gb-" + strconv.Itoa(cmIndex),
+					},
+				},
+			})
+			*templates = append(*templates, v1alpha1.Template{
+				Name: "cm-gb-" + strconv.Itoa(cmIndex),
+				Resource: &v1alpha1.ResourceTemplate{
+					Action:            "create",
+					SetOwnerReference: true,
+					Manifest:          string(cmJson),
+				},
+			})
+			cmIndex++
+		} else if config.ConfigType == repository.CS_TYPE_CONFIG {
+			secretJson, err := GetSecretJson(ConfigMapSecretDto{Name: config.Name, Data: config.Data, OwnerRef: ArgoWorkflowOwnerRef})
+			if err != nil {
+				return err
+			}
+			if config.Type == repository.VOLUME_CONFIG {
+				*volumes = append(*volumes, v12.Volume{
+					Name: config.Name + "-vol",
+					VolumeSource: v12.VolumeSource{
+						Secret: &v12.SecretVolumeSource{
+							SecretName: config.Name,
+						},
+					},
+				})
+			}
+			*steps = append(*steps, v1alpha1.ParallelSteps{
+				Steps: []v1alpha1.WorkflowStep{
+					{
+						Name:     "create-env-sec-gb-" + strconv.Itoa(csIndex),
+						Template: "sec-gb-" + strconv.Itoa(csIndex),
+					},
+				},
+			})
+			*templates = append(*templates, v1alpha1.Template{
+				Name: "sec-gb-" + strconv.Itoa(csIndex),
+				Resource: &v1alpha1.ResourceTemplate{
+					Action:            "create",
+					SetOwnerReference: true,
+					Manifest:          string(secretJson),
+				},
+			})
+			csIndex++
+		}
+	}
+
+	return nil
+}
diff --git a/pkg/pipeline/bean/GlobalCMCSDto.go b/pkg/pipeline/bean/GlobalCMCSDto.go
new file mode 100644
index 000000000..b6b57b6d4
--- /dev/null
+++ b/pkg/pipeline/bean/GlobalCMCSDto.go
@@ -0,0 +1,32 @@
+package bean
+
+import (
+	"encoding/json"
+	"github.com/devtron-labs/devtron/api/bean"
+)
+
+type GlobalCMCSDto struct {
+	Id         int    `json:"id"`
+	ConfigType string `json:"configType" validate:"oneof=CONFIGMAP SECRET"`
+	Name       string `json:"name"  validate:"required"`
+	Type       string `json:"type" validate:"oneof=environment volume"`
+	//map of key:value, example: '{ "a" : "b", "c" : "d"}'
+	Data               map[string]string `json:"data"  validate:"required"`
+	MountPath          string            `json:"mountPath"`
+	Deleted            bool              `json:"deleted"`
+	UserId             int32             `json:"-"`
+	SecretIngestionFor string            `json:"SecretIngestionFor"` // value can be one of [ci, cd, ci/cd]
+}
+
+func (dto GlobalCMCSDto) ConvertToConfigSecretMap() (bean.ConfigSecretMap, error) {
+	configSecretMap := bean.ConfigSecretMap{}
+	configSecretMap.Name = dto.Name
+	configSecretMap.Type = dto.Type
+	configSecretMap.MountPath = dto.MountPath
+	jsonRawMsg, err := json.Marshal(dto.Data)
+	if err != nil {
+		return configSecretMap, err
+	}
+	configSecretMap.Data = jsonRawMsg
+	return configSecretMap, nil
+}
diff --git a/pkg/pipeline/bean/WorkflowTemplate.go b/pkg/pipeline/bean/WorkflowTemplate.go
new file mode 100644
index 000000000..9846d6d65
--- /dev/null
+++ b/pkg/pipeline/bean/WorkflowTemplate.go
@@ -0,0 +1,29 @@
+package bean
+
+import (
+	blob_storage "github.com/devtron-labs/common-lib/blob-storage"
+	"github.com/devtron-labs/devtron/api/bean"
+	v1 "k8s.io/api/core/v1"
+	"k8s.io/client-go/rest"
+)
+
+type WorkflowTemplate struct {
+	WorkflowId       int
+	WorkflowRunnerId int
+	v1.PodSpec
+	ConfigMaps             []bean.ConfigSecretMap
+	Secrets                []bean.ConfigSecretMap
+	TTLValue               *int32
+	WorkflowRequestJson    string
+	WorkflowNamePrefix     string
+	WfControllerInstanceID string
+	ClusterConfig          *rest.Config
+	Namespace              string
+	ArchiveLogs            bool
+	BlobStorageConfigured  bool
+	BlobStorageS3Config    *blob_storage.BlobStorageS3Config
+	CloudProvider          blob_storage.BlobStorageType
+	AzureBlobConfig        *blob_storage.AzureBlobConfig
+	GcpBlobConfig          *blob_storage.GcpBlobConfig
+	CloudStorageKey        string
+}
diff --git a/wire_gen.go b/wire_gen.go
index 9b44c667f..793219b82 100644
--- a/wire_gen.go
+++ b/wire_gen.go
@@ -370,7 +370,8 @@ func InitializeApp() (*App, error) {
 	}
 	globalCMCSRepositoryImpl := repository.NewGlobalCMCSRepositoryImpl(sugaredLogger, db)
 	globalCMCSServiceImpl := pipeline.NewGlobalCMCSServiceImpl(sugaredLogger, globalCMCSRepositoryImpl)
-	cdWorkflowServiceImpl := pipeline.NewCdWorkflowServiceImpl(sugaredLogger, environmentRepositoryImpl, cdConfig, appServiceImpl, globalCMCSServiceImpl)
+	argoWorkflowExecutorImpl := pipeline.NewArgoWorkflowExecutorImpl(sugaredLogger)
+	cdWorkflowServiceImpl := pipeline.NewCdWorkflowServiceImpl(sugaredLogger, environmentRepositoryImpl, cdConfig, appServiceImpl, globalCMCSServiceImpl, argoWorkflowExecutorImpl)
 	materialRepositoryImpl := pipelineConfig.NewMaterialRepositoryImpl(db)
 	deploymentGroupRepositoryImpl := repository.NewDeploymentGroupRepositoryImpl(sugaredLogger, db)
 	cvePolicyRepositoryImpl := security.NewPolicyRepositoryImpl(db)


Test patch:
diff --git a/pkg/pipeline/GlobalCmcsService_test.go b/pkg/pipeline/GlobalCmcsService_test.go
index 0e3a02e7b..6457d5c0c 100644
--- a/pkg/pipeline/GlobalCmcsService_test.go
+++ b/pkg/pipeline/GlobalCmcsService_test.go
@@ -3,6 +3,7 @@ package pipeline
 import (
 	"github.com/argoproj/argo-workflows/v3/pkg/apis/workflow/v1alpha1"
 	"github.com/devtron-labs/devtron/internal/util"
+	"github.com/devtron-labs/devtron/pkg/pipeline/bean"
 	"github.com/stretchr/testify/assert"
 	v12 "k8s.io/api/core/v1"
 	"testing"
@@ -15,16 +16,16 @@ func TestNewGlobalCMCSServiceImpl(t *testing.T) {
 		sugaredLogger, err := util.NewSugardLogger()
 		assert.Nil(t, err)
 
-		GlobalCmcsService := NewGlobalCMCSServiceImpl(sugaredLogger, nil)
+		NewGlobalCMCSServiceImpl(sugaredLogger, nil)
 
-		var globalCmCsConfigs []*GlobalCMCSDto
+		var globalCmCsConfigs []*bean.GlobalCMCSDto
 
 		data := make(map[string]string)
 
 		data["a"] = "b"
 		data["b"] = "c"
 
-		globalCmCsConfigs = append(globalCmCsConfigs, &GlobalCMCSDto{
+		globalCmCsConfigs = append(globalCmCsConfigs, &bean.GlobalCMCSDto{
 			Id:                 0,
 			ConfigType:         "SECRET",
 			Name:               "test-secret-4",
@@ -34,7 +35,7 @@ func TestNewGlobalCMCSServiceImpl(t *testing.T) {
 			Deleted:            false,
 			UserId:             0,
 			SecretIngestionFor: "CI/CD",
-		}, &GlobalCMCSDto{
+		}, &bean.GlobalCMCSDto{
 			Id:                 0,
 			ConfigType:         "CONFIGMAP",
 			Name:               "test-secret-4",
@@ -44,7 +45,7 @@ func TestNewGlobalCMCSServiceImpl(t *testing.T) {
 			Deleted:            false,
 			UserId:             0,
 			SecretIngestionFor: "CI/CD",
-		}, &GlobalCMCSDto{
+		}, &bean.GlobalCMCSDto{
 			Id:                 0,
 			ConfigType:         "SECRET",
 			Name:               "test-secret-4",
@@ -68,7 +69,7 @@ func TestNewGlobalCMCSServiceImpl(t *testing.T) {
 		volumes := make([]v12.Volume, 0)
 		templates := make([]v1alpha1.Template, 0)
 
-		err = GlobalCmcsService.AddTemplatesForGlobalSecretsInWorkflowTemplate(globalCmCsConfigs, &steps, &volumes, &templates)
+		err = AddTemplatesForGlobalSecretsInWorkflowTemplate(globalCmCsConfigs, &steps, &volumes, &templates)
 		assert.Nil(t, err)
 		assert.Equal(t, len(steps), len(globalCmCsConfigs))
 		assert.Equal(t, len(templates), len(globalCmCsConfigs))