Repository: devtron-labs/devtron
Pull request #3097 (2023-03-09 11:42:34)

docs: added jobs section

# Description
 - Added a new documentation section for Jobs.


sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!&nbsp; &nbsp; [![Quality Gate passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonarcloud.io/dashboard?id=devtron-labs_devtron&pullRequest=3097)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=devtron-labs_devtron&pullRequest=3097&resolved=false&types=BUG) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=devtron-labs_devtron&pullRequest=3097&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=devtron-labs_devtron&pullRequest=3097&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=devtron-labs_devtron&pullRequest=3097&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=devtron-labs_devtron&pullRequest=3097&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=devtron-labs_devtron&pullRequest=3097&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=devtron-labs_devtron&pullRequest=3097&resolved=false&types=SECURITY_HOTSPOT) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/security_hotspots?id=devtron-labs_devtron&pullRequest=3097&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=devtron-labs_devtron&pullRequest=3097&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=devtron-labs_devtron&pullRequest=3097&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=devtron-labs_devtron&pullRequest=3097&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=devtron-labs_devtron&pullRequest=3097&resolved=false&types=CODE_SMELL)

[![No Coverage information](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/NoCoverageInfo-16px.png 'No Coverage information')](https://sonarcloud.io/component_measures?id=devtron-labs_devtron&pullRequest=3097) No Coverage information  
[![No Duplication information](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/NoDuplicationInfo-16px.png 'No Duplication information')](https://sonarcloud.io/component_measures?id=devtron-labs_devtron&pullRequest=3097&metric=duplicated_lines_density&view=list) No Duplication information


sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!&nbsp; &nbsp; [![Quality Gate passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonarcloud.io/dashboard?id=devtron-labs_devtron&pullRequest=3097)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=devtron-labs_devtron&pullRequest=3097&resolved=false&types=BUG) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=devtron-labs_devtron&pullRequest=3097&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=devtron-labs_devtron&pullRequest=3097&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=devtron-labs_devtron&pullRequest=3097&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=devtron-labs_devtron&pullRequest=3097&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=devtron-labs_devtron&pullRequest=3097&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=devtron-labs_devtron&pullRequest=3097&resolved=false&types=SECURITY_HOTSPOT) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/security_hotspots?id=devtron-labs_devtron&pullRequest=3097&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=devtron-labs_devtron&pullRequest=3097&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=devtron-labs_devtron&pullRequest=3097&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=devtron-labs_devtron&pullRequest=3097&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=devtron-labs_devtron&pullRequest=3097&resolved=false&types=CODE_SMELL)

[![No Coverage information](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/NoCoverageInfo-16px.png 'No Coverage information')](https://sonarcloud.io/component_measures?id=devtron-labs_devtron&pullRequest=3097) No Coverage information  
[![No Duplication information](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/NoDuplicationInfo-16px.png 'No Duplication information')](https://sonarcloud.io/component_measures?id=devtron-labs_devtron&pullRequest=3097&metric=duplicated_lines_density&view=list) No Duplication information


sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!&nbsp; &nbsp; [![Quality Gate passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonarcloud.io/dashboard?id=devtron-labs_devtron&pullRequest=3097)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=devtron-labs_devtron&pullRequest=3097&resolved=false&types=BUG) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=devtron-labs_devtron&pullRequest=3097&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=devtron-labs_devtron&pullRequest=3097&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=devtron-labs_devtron&pullRequest=3097&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=devtron-labs_devtron&pullRequest=3097&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=devtron-labs_devtron&pullRequest=3097&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=devtron-labs_devtron&pullRequest=3097&resolved=false&types=SECURITY_HOTSPOT) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/security_hotspots?id=devtron-labs_devtron&pullRequest=3097&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=devtron-labs_devtron&pullRequest=3097&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=devtron-labs_devtron&pullRequest=3097&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=devtron-labs_devtron&pullRequest=3097&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=devtron-labs_devtron&pullRequest=3097&resolved=false&types=CODE_SMELL)

[![No Coverage information](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/NoCoverageInfo-16px.png 'No Coverage information')](https://sonarcloud.io/component_measures?id=devtron-labs_devtron&pullRequest=3097) No Coverage information  
[![No Duplication information](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/NoDuplicationInfo-16px.png 'No Duplication information')](https://sonarcloud.io/component_measures?id=devtron-labs_devtron&pullRequest=3097&metric=duplicated_lines_density&view=list) No Duplication information



Patch:
diff --git a/Wire.go b/Wire.go
index 300a71b6d..919b3cd90 100644
--- a/Wire.go
+++ b/Wire.go
@@ -248,6 +248,9 @@ func InitializeApp() (*App, error) {
 		repository.NewAppListingRepositoryImpl,
 		wire.Bind(new(repository.AppListingRepository), new(*repository.AppListingRepositoryImpl)),
 
+		router.NewJobRouterImpl,
+		wire.Bind(new(router.JobRouter), new(*router.JobRouterImpl)),
+
 		pipelineConfig.NewPipelineRepositoryImpl,
 		wire.Bind(new(pipelineConfig.PipelineRepository), new(*pipelineConfig.PipelineRepositoryImpl)),
 		pipeline.NewPropertiesConfigServiceImpl,
@@ -410,6 +413,7 @@ func InitializeApp() (*App, error) {
 		pubsub.NewApplicationStatusHandlerImpl,
 		wire.Bind(new(pubsub.ApplicationStatusHandler), new(*pubsub.ApplicationStatusHandlerImpl)),
 
+		pubsub.GetCiEventConfig,
 		pubsub.NewCiEventHandlerImpl,
 		wire.Bind(new(pubsub.CiEventHandler), new(*pubsub.CiEventHandlerImpl)),
 
diff --git a/api/appStore/deployment/CommonDeploymentRestHandler.go b/api/appStore/deployment/CommonDeploymentRestHandler.go
index 0a09fc3a0..2630b5424 100644
--- a/api/appStore/deployment/CommonDeploymentRestHandler.go
+++ b/api/appStore/deployment/CommonDeploymentRestHandler.go
@@ -34,6 +34,7 @@ import (
 	"github.com/devtron-labs/devtron/util/k8sObjectsUtil"
 	"github.com/devtron-labs/devtron/util/rbac"
 	"github.com/gorilla/mux"
+	"go.opentelemetry.io/otel"
 	"go.uber.org/zap"
 	"gopkg.in/go-playground/validator.v9"
 	"net/http"
@@ -207,13 +208,11 @@ func (handler *CommonDeploymentRestHandlerImpl) GetDeploymentHistoryValues(w htt
 	}
 
 	var ok bool
-
 	if rbacObject2 == "" {
 		ok = handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionGet, rbacObject)
 	} else {
 		ok = handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionGet, rbacObject) || handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionGet, rbacObject2)
 	}
-
 	if !ok {
 		common.WriteJsonResp(w, fmt.Errorf("unauthorized user"), nil, http.StatusForbidden)
 		return
@@ -222,7 +221,9 @@ func (handler *CommonDeploymentRestHandlerImpl) GetDeploymentHistoryValues(w htt
 
 	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
 	defer cancel()
+	_, span := otel.Tracer("orchestrator").Start(ctx, "appStoreDeploymentService.GetDeploymentHistoryInfo")
 	res, err := handler.appStoreDeploymentService.GetDeploymentHistoryInfo(ctx, installedAppDto, installedAppVersionHistoryId)
+	span.End()
 	if err != nil {
 		common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
 		return
@@ -230,7 +231,9 @@ func (handler *CommonDeploymentRestHandlerImpl) GetDeploymentHistoryValues(w htt
 	if util2.IsHelmApp(appOfferingMode) {
 		canUpdate := handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionUpdate, rbacObject)
 		if !canUpdate && res != nil && res.Manifest != nil {
+			_, span = otel.Tracer("orchestrator").Start(ctx, "k8sObjectsUtil.HideValuesIfSecretForWholeYamlInput")
 			modifiedManifest, err := k8sObjectsUtil.HideValuesIfSecretForWholeYamlInput(*res.Manifest)
+			span.End()
 			if err != nil {
 				handler.Logger.Errorw("error in hiding secret values", "err", err)
 				common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
diff --git a/api/bean/AppView.go b/api/bean/AppView.go
index fb8d07470..fdc432303 100644
--- a/api/bean/AppView.go
+++ b/api/bean/AppView.go
@@ -20,6 +20,7 @@ package bean
 import (
 	"encoding/json"
 	"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
+	"time"
 )
 
 type AppContainer struct {
@@ -36,6 +37,11 @@ type AppContainerResponse struct {
 	DeploymentGroupDTO DeploymentGroupDTO `json:"deploymentGroup,omitempty"`
 }
 
+type JobContainerResponse struct {
+	JobContainers []*JobContainer `json:"jobContainers"`
+	JobCount      int             `json:"jobCount"`
+}
+
 type DeploymentGroupDTO struct {
 	Id             int             `json:"id"`
 	Name           string          `json:"name"`
@@ -52,6 +58,36 @@ type CiMaterialDTO struct {
 	SourceValue string `json:"value"`
 }
 
+type JobContainer struct {
+	JobId          int             `json:"jobId"`
+	JobName        string          `json:"jobName""`
+	Description    string          `json:"description"`
+	JobCiPipelines []JobCIPipeline `json:"ciPipelines"'`
+}
+
+type JobCIPipeline struct {
+	CiPipelineId   int       `json:"ciPipelineId"`
+	CiPipelineName string    `json:"ciPipelineName"`
+	Status         string    `json:"status"`
+	LastRunAt      time.Time `json:"lastRunAt"`
+	LastSuccessAt  time.Time `json:"lastSuccessAt"`
+}
+
+type JobListingContainer struct {
+	JobId          int       `json:"job_id"`
+	JobName        string    `json:"job_name"`
+	Description    string    `json:"description"`
+	CiPipelineID   int       `json:"ci_pipeline_id"`
+	CiPipelineName string    `json:"ci_pipeline_name"`
+	Status         string    `json:"status"`
+	StartedOn      time.Time `json:"started_on"`
+}
+
+type CiPipelineLastSucceededTime struct {
+	CiPipelineID    int       `json:"ci_pipeline_id"`
+	LastSucceededOn time.Time `json:"last_succeeded_on"`
+}
+
 type AppEnvironmentContainer struct {
 	AppId                       int                       `json:"appId"`
 	AppName                     string                    `json:"appName"`
diff --git a/api/cluster/EnvironmentRestHandler.go b/api/cluster/EnvironmentRestHandler.go
index be7d59d2d..6a8948328 100644
--- a/api/cluster/EnvironmentRestHandler.go
+++ b/api/cluster/EnvironmentRestHandler.go
@@ -148,24 +148,56 @@ func (impl EnvironmentRestHandlerImpl) Get(w http.ResponseWriter, r *http.Reques
 }
 
 func (impl EnvironmentRestHandlerImpl) GetAll(w http.ResponseWriter, r *http.Request) {
-	bean, err := impl.environmentClusterMappingsService.GetAll()
+	environments, err := impl.environmentClusterMappingsService.GetAll()
 	if err != nil {
 		impl.logger.Errorw("service err, GetAll", "err", err)
 		common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
 		return
 	}
 
-	var result []request.EnvironmentBean
+	userId, err := impl.userService.GetLoggedInUser(r)
+	if userId == 0 || err != nil {
+		common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized)
+		return
+	}
+	isSuperAdmin, err := impl.userService.IsSuperAdmin(int(userId))
+	if err != nil {
+		impl.logger.Errorw("request err, GetAll", "err", err, "userId", userId)
+		common.WriteJsonResp(w, err, "Failed to check is super admin", http.StatusInternalServerError)
+		return
+	}
+	if isSuperAdmin {
+		common.WriteJsonResp(w, err, environments, http.StatusOK)
+		return
+	}
+
 	token := r.Header.Get("token")
-	for _, item := range bean {
-		// RBAC enforcer applying
-		if ok := impl.enforcer.Enforce(token, casbin.ResourceGlobalEnvironment, casbin.ActionGet, strings.ToLower(item.EnvironmentIdentifier)); ok {
-			result = append(result, item)
+	emailId, err := impl.userService.GetEmailFromToken(token)
+	if err != nil {
+		impl.logger.Errorw("error in getting emailId from token", "err", err, "token", token)
+		common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
+		return
+	}
+
+	grantedEnvironments := make([]*request.EnvironmentBean, 0)
+
+	var envIdentifierList []string
+	envIdentifierMap := make(map[string]*request.EnvironmentBean)
+	for _, item := range environments {
+		envIdentifier := strings.ToLower(item.EnvironmentIdentifier)
+		envIdentifierList = append(envIdentifierList, envIdentifier)
+		envIdentifierMap[envIdentifier] = &item
+	}
+
+	// RBAC enforcer applying
+	rbacResultMap := impl.enforcer.EnforceByEmailInBatch(emailId, casbin.ResourceGlobalEnvironment, casbin.ActionGet, envIdentifierList)
+	for envIdentifier, item := range envIdentifierMap {
+		if rbacResultMap[envIdentifier] {
+			grantedEnvironments = append(grantedEnvironments, item)
 		}
-		//RBAC enforcer Ends
 	}
 
-	common.WriteJsonResp(w, err, result, http.StatusOK)
+	common.WriteJsonResp(w, err, grantedEnvironments, http.StatusOK)
 }
 
 func (impl EnvironmentRestHandlerImpl) GetAllActive(w http.ResponseWriter, r *http.Request) {
diff --git a/api/restHandler/AppListingRestHandler.go b/api/restHandler/AppListingRestHandler.go
index f346fc40a..d53c4b3d7 100644
--- a/api/restHandler/AppListingRestHandler.go
+++ b/api/restHandler/AppListingRestHandler.go
@@ -30,6 +30,7 @@ import (
 	"github.com/devtron-labs/devtron/client/argocdServer/application"
 	"github.com/devtron-labs/devtron/client/cron"
 	"github.com/devtron-labs/devtron/internal/constants"
+	"github.com/devtron-labs/devtron/internal/sql/repository/helper"
 	"github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig"
 	"github.com/devtron-labs/devtron/internal/util"
 	"github.com/devtron-labs/devtron/pkg/app"
@@ -57,6 +58,8 @@ import (
 
 type AppListingRestHandler interface {
 	FetchAppsByEnvironment(w http.ResponseWriter, r *http.Request)
+	FetchJobs(w http.ResponseWriter, r *http.Request)
+	FetchJobOverviewCiPipelines(w http.ResponseWriter, r *http.Request)
 	FetchAppDetails(w http.ResponseWriter, r *http.Request)
 	FetchAllDevtronManagedApps(w http.ResponseWriter, r *http.Request)
 	FetchAppTriggerView(w http.ResponseWriter, r *http.Request)
@@ -157,6 +160,91 @@ func (handler AppListingRestHandlerImpl) FetchAllDevtronManagedApps(w http.Respo
 	res, err := handler.appListingService.FetchAllDevtronManagedApps()
 	common.WriteJsonResp(w, err, res, http.StatusOK)
 }
+func (handler AppListingRestHandlerImpl) FetchJobs(w http.ResponseWriter, r *http.Request) {
+	userId, err := handler.userService.GetLoggedInUser(r)
+	if userId == 0 || err != nil {
+		handler.logger.Errorw("request err, userId", "err", err, "payload", userId)
+		common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized)
+		return
+	}
+	isSuperAdmin, err := handler.userService.IsSuperAdmin(int(userId))
+	if !isSuperAdmin || err != nil {
+		if err != nil {
+			handler.logger.Errorw("request err, CheckSuperAdmin", "err", isSuperAdmin, "isSuperAdmin", isSuperAdmin)
+		}
+		common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized)
+		return
+	}
+	var fetchJobListingRequest app.FetchAppListingRequest
+	decoder := json.NewDecoder(r.Body)
+	err = decoder.Decode(&fetchJobListingRequest)
+	if err != nil {
+		handler.logger.Errorw("request err, FetchAppsByEnvironment", "err", err, "payload", fetchJobListingRequest)
+		common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
+		return
+	}
+	jobs, err := handler.appListingService.FetchJobs(fetchJobListingRequest)
+	if err != nil {
+		handler.logger.Errorw("service err, FetchJobs", "err", err, "payload", fetchJobListingRequest)
+		common.WriteJsonResp(w, err, "", http.StatusInternalServerError)
+		return
+	}
+	jobsCount := len(jobs)
+	offset := fetchJobListingRequest.Offset
+	limit := fetchJobListingRequest.Size
+
+	if limit > 0 {
+		if offset+limit <= len(jobs) {
+			jobs = jobs[offset : offset+limit]
+		} else {
+			jobs = jobs[offset:]
+		}
+	}
+	jobContainerResponse := bean.JobContainerResponse{
+		JobContainers: jobs,
+		JobCount:      jobsCount,
+	}
+
+	common.WriteJsonResp(w, err, jobContainerResponse, http.StatusOK)
+}
+func (handler AppListingRestHandlerImpl) FetchJobOverviewCiPipelines(w http.ResponseWriter, r *http.Request) {
+	userId, err := handler.userService.GetLoggedInUser(r)
+	if userId == 0 || err != nil {
+		handler.logger.Errorw("request err, userId", "err", err, "payload", userId)
+		common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized)
+		return
+	}
+	isSuperAdmin, err := handler.userService.IsSuperAdmin(int(userId))
+	if !isSuperAdmin || err != nil {
+		if err != nil {
+			handler.logger.Errorw("request err, CheckSuperAdmin", "err", isSuperAdmin, "isSuperAdmin", isSuperAdmin)
+		}
+		common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized)
+		return
+	}
+	vars := mux.Vars(r)
+	jobId, err := strconv.Atoi(vars["jobId"])
+	if err != nil {
+		handler.logger.Errorw("request err, GetAppMetaInfo", "err", err, "jobId", jobId)
+		common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
+		return
+	}
+	job, err := handler.pipeline.GetApp(jobId)
+	if err != nil || job == nil || job.AppType != helper.Job {
+		handler.logger.Errorw("Job with the given Id does not exist", "err", err, "jobId", jobId)
+		common.WriteJsonResp(w, err, "Job with the given Id does not exist", http.StatusBadRequest)
+		return
+	}
+
+	jobCi, err := handler.appListingService.FetchOverviewCiPipelines(jobId)
+	if err != nil {
+		handler.logger.Errorw("request err, GetJobCi", "err", jobCi, "jobCi", jobCi)
+		common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
+		return
+	}
+
+	common.WriteJsonResp(w, err, jobCi, http.StatusOK)
+}
 func (handler AppListingRestHandlerImpl) FetchAppsByEnvironment(w http.ResponseWriter, r *http.Request) {
 	//Allow CORS here By * or specific origin
 	setupResponse(&w, r)
@@ -571,7 +659,7 @@ func (handler AppListingRestHandlerImpl) FetchAppStageStatus(w http.ResponseWrit
 	}
 	//RBAC enforcer Ends
 
-	triggerView, err := handler.appListingService.FetchAppStageStatus(appId)
+	triggerView, err := handler.appListingService.FetchAppStageStatus(appId, int(app.AppType))
 	if err != nil {
 		handler.logger.Errorw("service err, FetchAppStageStatus", "err", err, "appId", appId)
 		common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
diff --git a/api/restHandler/GlobalCMCSRestHandler.go b/api/restHandler/GlobalCMCSRestHandler.go
index 08308d565..90b0f3980 100644
--- a/api/restHandler/GlobalCMCSRestHandler.go
+++ b/api/restHandler/GlobalCMCSRestHandler.go
@@ -6,13 +6,19 @@ import (
 	"github.com/devtron-labs/devtron/pkg/pipeline"
 	"github.com/devtron-labs/devtron/pkg/user"
 	"github.com/devtron-labs/devtron/pkg/user/casbin"
+	"github.com/gorilla/mux"
 	"go.uber.org/zap"
 	"gopkg.in/go-playground/validator.v9"
 	"net/http"
+	"strconv"
 )
 
 type GlobalCMCSRestHandler interface {
 	CreateGlobalCMCSConfig(w http.ResponseWriter, r *http.Request)
+	UpdateGlobalCMCSDataById(w http.ResponseWriter, r *http.Request)
+	GetGlobalCMCSDataByConfigTypeAndName(w http.ResponseWriter, r *http.Request)
+	GetAllGlobalCMCSData(w http.ResponseWriter, r *http.Request)
+	DeleteByID(w http.ResponseWriter, r *http.Request)
 }
 
 type GlobalCMCSRestHandlerImpl struct {
@@ -77,3 +83,123 @@ func (handler *GlobalCMCSRestHandlerImpl) CreateGlobalCMCSConfig(w http.Response
 	}
 	common.WriteJsonResp(w, nil, res, http.StatusOK)
 }
+
+func (handler *GlobalCMCSRestHandlerImpl) UpdateGlobalCMCSDataById(w http.ResponseWriter, r *http.Request) {
+	decoder := json.NewDecoder(r.Body)
+	userId, err := handler.userAuthService.GetLoggedInUser(r)
+	if userId == 0 || err != nil {
+		common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized)
+		return
+	}
+	var bean pipeline.GlobalCMCSDataUpdateDto
+	err = decoder.Decode(&bean)
+	if err != nil {
+		handler.logger.Errorw("request err, CreateGlobalCMCSConfig", "err", err, "payload", bean)
+		common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
+		return
+	}
+	bean.UserId = userId
+	handler.logger.Infow("request payload, CreateGlobalCMCSConfig", "err", err, "payload", bean)
+	err = handler.validator.Struct(bean)
+	if err != nil {
+		handler.logger.Errorw("validation err, CreateGlobalCMCSConfig", "err", err, "payload", bean)
+		common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
+		return
+	}
+
+	// RBAC enforcer applying
+	token := r.Header.Get("token")
+	if ok := handler.enforcer.Enforce(token, casbin.ResourceGlobal, casbin.ActionUpdate, "*"); !ok {
+		common.WriteJsonResp(w, err, "Unauthorized User", http.StatusForbidden)
+		return
+	}
+	//RBAC enforcer Ends
+
+	res, err := handler.globalCMCSService.UpdateDataById(&bean)
+	if err != nil {
+		handler.logger.Errorw("service err, CreateGlobalCMCSConfig", "err", err, "payload", bean)
+		common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
+		return
+	}
+	common.WriteJsonResp(w, nil, res, http.StatusOK)
+}
+
+func (handler *GlobalCMCSRestHandlerImpl) GetGlobalCMCSDataByConfigTypeAndName(w http.ResponseWriter, r *http.Request) {
+
+	userId, err := handler.userAuthService.GetLoggedInUser(r)
+	if userId == 0 || err != nil {
+		common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized)
+		return
+	}
+
+	vars := mux.Vars(r)
+	configName := vars["config_name"]
+	configType := vars["config_type"]
+
+	// RBAC enforcer applying
+	token := r.Header.Get("token")
+	if ok := handler.enforcer.Enforce(token, casbin.ResourceGlobal, casbin.ActionGet, "*"); !ok {
+		common.WriteJsonResp(w, err, "Unauthorized User", http.StatusForbidden)
+		return
+	}
+	//RBAC enforcer Ends
+
+	res, err := handler.globalCMCSService.GetGlobalCMCSDataByConfigTypeAndName(configName, configType)
+	if err != nil {
+		handler.logger.Errorw("service err, CreateGlobalCMCSConfig", "err", err, "payload", "configName", configName, "configType", configType)
+		common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
+		return
+	}
+	common.WriteJsonResp(w, nil, res, http.StatusOK)
+}
+
+func (handler *GlobalCMCSRestHandlerImpl) GetAllGlobalCMCSData(w http.ResponseWriter, r *http.Request) {
+	userId, err := handler.userAuthService.GetLoggedInUser(r)
+	if userId == 0 || err != nil {
+		common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized)
+		return
+	}
+	token := r.Header.Get("token")
+	if ok := handler.enforcer.Enforce(token, casbin.ResourceGlobal, casbin.ActionGet, "*"); !ok {
+		common.WriteJsonResp(w, err, "Unauthorized User", http.StatusForbidden)
+		return
+	}
+	res, err := handler.globalCMCSService.FindAllActive()
+	if err != nil {
+		handler.logger.Errorw("service err, CreateGlobalCMCSConfig", "err", err, "payload")
+		common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
+		return
+	}
+	common.WriteJsonResp(w, nil, res, http.StatusOK)
+	//RBAC enforcer Ends
+
+}
+
+func (handler *GlobalCMCSRestHandlerImpl) DeleteByID(w http.ResponseWriter, r *http.Request) {
+
+	vars := mux.Vars(r)
+
+	id, err := strconv.Atoi(vars["id"])
+	if err != nil {
+		common.WriteJsonResp(w, err, "error in parsing id for delete config reuest", http.StatusBadRequest)
+		return
+	}
+
+	userId, err := handler.userAuthService.GetLoggedInUser(r)
+	if userId == 0 || err != nil {
+		common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized)
+		return
+	}
+	token := r.Header.Get("token")
+	if ok := handler.enforcer.Enforce(token, casbin.ResourceGlobal, casbin.ActionDelete, "*"); !ok {
+		common.WriteJsonResp(w, err, "Unauthorized User", http.StatusForbidden)
+		return
+	}
+	err = handler.globalCMCSService.DeleteById(id)
+	if err != nil {
+		handler.logger.Errorw("service err, CreateGlobalCMCSConfig", "err", err, "payload")
+		common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
+		return
+	}
+	common.WriteJsonResp(w, nil, "Successfully deleted", http.StatusOK)
+}
diff --git a/api/restHandler/app/AutoCompleteRestHandler.go b/api/restHandler/app/AutoCompleteRestHandler.go
index 0239249a6..03ae78aa7 100644
--- a/api/restHandler/app/AutoCompleteRestHandler.go
+++ b/api/restHandler/app/AutoCompleteRestHandler.go
@@ -2,6 +2,7 @@ package app
 
 import (
 	"github.com/devtron-labs/devtron/api/restHandler/common"
+	"github.com/devtron-labs/devtron/internal/sql/repository/helper"
 	"github.com/devtron-labs/devtron/pkg/pipeline"
 	"github.com/devtron-labs/devtron/pkg/user/casbin"
 	"github.com/gorilla/mux"
@@ -32,10 +33,20 @@ func (handler PipelineConfigRestHandlerImpl) GetAppListForAutocomplete(w http.Re
 	v := r.URL.Query()
 	teamId := v.Get("teamId")
 	appName := v.Get("appName")
+	appTypeParam := v.Get("appType")
+	var appType int
+	if appTypeParam != "" {
+		appType, err = strconv.Atoi(appTypeParam)
+		if err != nil {
+			handler.Logger.Errorw("service err, GetAppListForAutocomplete", "err", err, "teamId", teamId, "appTypeParam", appTypeParam)
+			common.WriteJsonResp(w, err, "Failed to parse appType param", http.StatusInternalServerError)
+			return
+		}
+	}
 	handler.Logger.Infow("request payload, GetAppListForAutocomplete", "teamId", teamId)
 	var apps []*pipeline.AppBean
 	if len(teamId) == 0 {
-		apps, err = handler.pipelineBuilder.FindAllMatchesByAppName(appName)
+		apps, err = handler.pipelineBuilder.FindAllMatchesByAppName(appName, helper.AppType(appType))
 		if err != nil {
 			handler.Logger.Errorw("service err, GetAppListForAutocomplete", "err", err, "teamId", teamId)
 			common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
diff --git a/api/restHandler/app/BuildPipelineRestHandler.go b/api/restHandler/app/BuildPipelineRestHandler.go
index 834702d7b..edc9f1fae 100644
--- a/api/restHandler/app/BuildPipelineRestHandler.go
+++ b/api/restHandler/app/BuildPipelineRestHandler.go
@@ -9,9 +9,11 @@ import (
 	"github.com/devtron-labs/devtron/api/restHandler/common"
 	"github.com/devtron-labs/devtron/client/gitSensor"
 	"github.com/devtron-labs/devtron/internal/sql/repository"
+	"github.com/devtron-labs/devtron/internal/sql/repository/helper"
 	"github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig"
 	"github.com/devtron-labs/devtron/internal/util"
 	"github.com/devtron-labs/devtron/pkg/bean"
+	bean1 "github.com/devtron-labs/devtron/pkg/pipeline/bean"
 	"github.com/devtron-labs/devtron/pkg/user/casbin"
 	"github.com/gorilla/mux"
 	"io"
@@ -208,6 +210,11 @@ func (handler PipelineConfigRestHandlerImpl) PatchCiPipelines(w http.ResponseWri
 		common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized)
 		return
 	}
+	isSuperAdmin, err := handler.userAuthService.IsSuperAdmin(int(userId))
+	if err != nil {
+		common.WriteJsonResp(w, err, "failed to check if user is super admin", http.StatusInternalServerError)
+		return
+	}
 	var patchRequest bean.CiPatchRequest
 	err = decoder.Decode(&patchRequest)
 	patchRequest.UserId = userId
@@ -230,32 +237,46 @@ func (handler PipelineConfigRestHandlerImpl) PatchCiPipelines(w http.ResponseWri
 		common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
 		return
 	}
+
 	resourceName := handler.enforcerUtil.GetAppRBACName(app.AppName)
-	if ok := handler.enforcer.Enforce(token, casbin.ResourceApplications, casbin.ActionCreate, resourceName); !ok {
+	var ok bool
+	if app.AppType == helper.Job {
+		ok = isSuperAdmin
+	} else {
+		ok = handler.enforcer.Enforce(token, casbin.ResourceApplications, casbin.ActionCreate, resourceName)
+	}
+	if !ok {
 		common.WriteJsonResp(w, fmt.Errorf("unauthorized user"), "Unauthorized User", http.StatusForbidden)
 		return
 	}
 
-	pipelineData, err := handler.pipelineRepository.FindActiveByAppIdAndPipelineId(patchRequest.AppId, patchRequest.CiPipeline.Id)
-	if err != nil {
-		common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
-		return
-	}
-	var environmentIds []int
-	for _, pipeline := range pipelineData {
-		environmentIds = append(environmentIds, pipeline.EnvironmentId)
-	}
-	if handler.appWorkflowService.CheckCdPipelineByCiPipelineId(patchRequest.CiPipeline.Id) {
-		for _, envId := range environmentIds {
-			envObject := handler.enforcerUtil.GetEnvRBACNameByCiPipelineIdAndEnvId(patchRequest.CiPipeline.Id, envId)
-			if ok := handler.enforcer.Enforce(token, casbin.ResourceEnvironment, casbin.ActionUpdate, envObject); !ok {
-				common.WriteJsonResp(w, fmt.Errorf("unauthorized user"), "Unauthorized User", http.StatusForbidden)
-				return
-			}
+	ciConf, err := handler.pipelineBuilder.GetCiPipeline(patchRequest.AppId)
+
+	var emptyDockerRegistry string
+	if app.AppType == helper.Job && ciConf == nil {
+		ciConfigRequest := bean.CiConfigRequest{}
+		ciConfigRequest.DockerRegistry = emptyDockerRegistry
+		ciConfigRequest.AppId = patchRequest.AppId
+		ciConfigRequest.CiBuildConfig = &bean1.CiBuildConfigBean{}
+		ciConfigRequest.CiBuildConfig.CiBuildType = "skip-build"
+		ciConfigRequest.UserId = patchRequest.UserId
+		if patchRequest.CiPipeline == nil || patchRequest.CiPipeline.CiMaterial == nil {
+			handler.Logger.Errorw("Invalid patch ci-pipeline request", "request", patchRequest, "err", "invalid CiPipeline data")
+			common.WriteJsonResp(w, fmt.Errorf("invalid CiPipeline data"), nil, http.StatusBadRequest)
+			return
+		}
+		ciConfigRequest.CiBuildConfig.GitMaterialId = patchRequest.CiPipeline.CiMaterial[0].GitMaterialId
+		ciConfigRequest.IsJob = true
+		_, err = handler.pipelineBuilder.CreateCiPipeline(&ciConfigRequest)
+		if err != nil {
+			handler.Logger.Errorw("error occurred in creating ci-pipeline for the Job", "payload", ciConfigRequest, "err", err)
+			common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
+			return
 		}
 	}
 
 	createResp, err := handler.pipelineBuilder.PatchCiPipeline(&patchRequest)
+	createResp.AppName = app.AppName
 	if err != nil {
 		handler.Logger.Errorw("service err, PatchCiPipelines", "err", err, "PatchCiPipelines", patchRequest)
 		common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
@@ -437,7 +458,6 @@ func (handler PipelineConfigRestHandlerImpl) TriggerCiPipeline(w http.ResponseWr
 
 	common.WriteJsonResp(w, err, response, http.StatusOK)
 }
-
 func (handler PipelineConfigRestHandlerImpl) FetchMaterials(w http.ResponseWriter, r *http.Request) {
 	userId, err := handler.userAuthService.GetLoggedInUser(r)
 	if userId == 0 || err != nil {
@@ -872,6 +892,27 @@ func (handler PipelineConfigRestHandlerImpl) CreateMaterial(w http.ResponseWrite
 		common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
 		return
 	}
+	app, err := handler.pipelineBuilder.GetApp(createMaterialDto.AppId)
+	if err != nil {
+		common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
+		return
+	}
+	if app.AppType == helper.Job {
+		isSuperAdmin, err := handler.userAuthService.IsSuperAdmin(int(userId))
+		if !isSuperAdmin || err != nil {
+			if err != nil {
+				handler.Logger.Errorw("request err, CheckSuperAdmin", "err", isSuperAdmin, "isSuperAdmin", isSuperAdmin)
+			}
+			common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized)
+			return
+		}
+	} else {
+		resourceObject := handler.enforcerUtil.GetAppRBACNameByAppId(createMaterialDto.AppId)
+		if ok := handler.enforcer.Enforce(token, casbin.ResourceApplications, casbin.ActionCreate, resourceObject); !ok {
+			common.WriteJsonResp(w, err, "Unauthorized User", http.StatusForbidden)
+			return
+		}
+	}
 	for _, gitMaterial := range createMaterialDto.Material {
 		validationResult, err := handler.ValidateGitMaterialUrl(gitMaterial.GitProviderId, gitMaterial.Url)
 		if err != nil {
@@ -886,11 +927,6 @@ func (handler PipelineConfigRestHandlerImpl) CreateMaterial(w http.ResponseWrite
 			}
 		}
 	}
-	resourceObject := handler.enforcerUtil.GetAppRBACNameByAppId(createMaterialDto.AppId)
-	if ok := handler.enforcer.Enforce(token, casbin.ResourceApplications, casbin.ActionCreate, resourceObject); !ok {
-		common.WriteJsonResp(w, err, "Unauthorized User", http.StatusForbidden)
-		return
-	}
 
 	createResp, err := handler.pipelineBuilder.CreateMaterialsForApp(&createMaterialDto)
 	if err != nil {
@@ -936,11 +972,27 @@ func (handler PipelineConfigRestHandlerImpl) UpdateMaterial(w http.ResponseWrite
 			return
 		}
 	}
-	resourceObject := handler.enforcerUtil.GetAppRBACNameByAppId(updateMaterialDto.AppId)
-	if ok := handler.enforcer.Enforce(token, casbin.ResourceApplications, casbin.ActionCreate, resourceObject); !ok {
-		common.WriteJsonResp(w, err, "Unauthorized User", http.StatusForbidden)
+	app, err := handler.pipelineBuilder.GetApp(updateMaterialDto.AppId)
+	if err != nil {
+		common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
 		return
 	}
+	if app.AppType == helper.Job {
+		isSuperAdmin, err := handler.userAuthService.IsSuperAdmin(int(userId))
+		if !isSuperAdmin || err != nil {
+			if err != nil {
+				handler.Logger.Errorw("request err, CheckSuperAdmin", "err", isSuperAdmin, "isSuperAdmin", isSuperAdmin)
+			}
+			common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized)
+			return
+		}
+	} else {
+		resourceObject := handler.enforcerUtil.GetAppRBACNameByAppId(updateMaterialDto.AppId)
+		if ok := handler.enforcer.Enforce(token, casbin.ResourceApplications, casbin.ActionCreate, resourceObject); !ok {
+			common.WriteJsonResp(w, err, "Unauthorized User", http.StatusForbidden)
+			return
+		}
+	}
 
 	createResp, err := handler.pipelineBuilder.UpdateMaterialsForApp(&updateMaterialDto)
 	if err != nil {
@@ -974,12 +1026,28 @@ func (handler PipelineConfigRestHandlerImpl) DeleteMaterial(w http.ResponseWrite
 		return
 	}
 	//rbac starts
-	resourceObject := handler.enforcerUtil.GetAppRBACNameByAppId(deleteMaterial.AppId)
-	token := r.Header.Get("token")
-	if ok := handler.enforcer.Enforce(token, casbin.ResourceApplications, casbin.ActionCreate, resourceObject); !ok {
-		common.WriteJsonResp(w, err, "Unauthorized User", http.StatusForbidden)
+	app, err := handler.pipelineBuilder.GetApp(deleteMaterial.AppId)
+	if err != nil {
+		common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
 		return
 	}
+	if app.AppType == helper.Job {
+		isSuperAdmin, err := handler.userAuthService.IsSuperAdmin(int(userId))
+		if !isSuperAdmin || err != nil {
+			if err != nil {
+				handler.Logger.Errorw("request err, CheckSuperAdmin", "err", isSuperAdmin, "isSuperAdmin", isSuperAdmin)
+			}
+			common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized)
+			return
+		}
+	} else {
+		resourceObject := handler.enforcerUtil.GetAppRBACNameByAppId(deleteMaterial.AppId)
+		token := r.Header.Get("token")
+		if ok := handler.enforcer.Enforce(token, casbin.ResourceApplications, casbin.ActionCreate, resourceObject); !ok {
+			common.WriteJsonResp(w, err, "Unauthorized User", http.StatusForbidden)
+			return
+		}
+	}
 	//rbac ends
 	err = handler.pipelineBuilder.DeleteMaterial(&deleteMaterial)
 	if err != nil {
diff --git a/api/restHandler/app/DeploymentPipelineRestHandler.go b/api/restHandler/app/DeploymentPipelineRestHandler.go
index ed0e2dcf3..3ec44cb14 100644
--- a/api/restHandler/app/DeploymentPipelineRestHandler.go
+++ b/api/restHandler/app/DeploymentPipelineRestHandler.go
@@ -7,6 +7,7 @@ import (
 	"fmt"
 	bean2 "github.com/devtron-labs/devtron/api/bean"
 	"github.com/devtron-labs/devtron/api/restHandler/common"
+	"github.com/devtron-labs/devtron/internal/sql/repository/helper"
 	"github.com/devtron-labs/devtron/internal/sql/repository/security"
 	"github.com/devtron-labs/devtron/internal/util"
 	"github.com/devtron-labs/devtron/pkg/bean"
@@ -177,7 +178,10 @@ func (handler PipelineConfigRestHandlerImpl) CreateCdPipeline(w http.ResponseWri
 		common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
 		return
 	}
-
+	if app.AppType == helper.Job {
+		common.WriteJsonResp(w, fmt.Errorf("cannot create cd-pipeline for job"), "cannot create cd-pipeline for job", http.StatusBadRequest)
+		return
+	}
 	//RBAC
 	resourceName := handler.enforcerUtil.GetAppRBACName(app.AppName)
 	if ok := handler.enforcer.Enforce(token, casbin.ResourceApplications, casbin.ActionCreate, resourceName); !ok {
@@ -834,7 +838,7 @@ func (handler PipelineConfigRestHandlerImpl) GetArtifactsByCDPipeline(w http.Res
 	}
 	if len(digests) > 0 {
 		vulnerableMap := make(map[string]bool)
-		cvePolicy, severityPolicy, err := handler.policyService.GetApplicablePolicy(pipelineModel.Environment.ClusterId, pipelineModel.EnvironmentId, pipelineModel.AppId, pipelineModel.App.AppStore)
+		cvePolicy, severityPolicy, err := handler.policyService.GetApplicablePolicy(pipelineModel.Environment.ClusterId, pipelineModel.EnvironmentId, pipelineModel.AppId, pipelineModel.App.AppType == helper.ChartStoreApp)
 		if err != nil {
 			handler.Logger.Errorw("service err, GetArtifactsByCDPipeline", "err", err, "cdPipelineId", cdPipelineId, "stage", stage)
 		}
diff --git a/api/restHandler/app/PipelineConfigRestHandler.go b/api/restHandler/app/PipelineConfigRestHandler.go
index d527e7904..098e4e241 100644
--- a/api/restHandler/app/PipelineConfigRestHandler.go
+++ b/api/restHandler/app/PipelineConfigRestHandler.go
@@ -22,6 +22,7 @@ import (
 	"context"
 	"encoding/json"
 	"fmt"
+	"github.com/devtron-labs/devtron/internal/sql/repository/helper"
 	"github.com/devtron-labs/devtron/pkg/chart"
 	"github.com/devtron-labs/devtron/util/argo"
 	"io"
@@ -61,7 +62,6 @@ type DevtronAppRestHandler interface {
 	CreateApp(w http.ResponseWriter, r *http.Request)
 	DeleteApp(w http.ResponseWriter, r *http.Request)
 	GetApp(w http.ResponseWriter, r *http.Request)
-
 	FindAppsByTeamId(w http.ResponseWriter, r *http.Request)
 	FindAppsByTeamName(w http.ResponseWriter, r *http.Request)
 	GetEnvironmentListWithAppData(w http.ResponseWriter, r *http.Request)
@@ -203,13 +203,27 @@ func (handler PipelineConfigRestHandlerImpl) DeleteApp(w http.ResponseWriter, r
 		common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
 		return
 	}
-
-	resourceObject := handler.enforcerUtil.GetAppRBACNameByAppId(appId)
-	if ok := handler.enforcer.Enforce(token, casbin.ResourceApplications, casbin.ActionDelete, resourceObject); !ok {
-		common.WriteJsonResp(w, err, "Unauthorized User", http.StatusForbidden)
+	app, err := handler.pipelineBuilder.GetApp(appId)
+	if err != nil {
+		common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
 		return
 	}
-
+	if app.AppType == helper.Job {
+		isSuperAdmin, err := handler.userAuthService.IsSuperAdmin(int(userId))
+		if !isSuperAdmin || err != nil {
+			if err != nil {
+				handler.Logger.Errorw("request err, CheckSuperAdmin", "err", isSuperAdmin, "isSuperAdmin", isSuperAdmin)
+			}
+			common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized)
+			return
+		}
+	} else {
+		resourceObject := handler.enforcerUtil.GetAppRBACNameByAppId(appId)
+		if ok := handler.enforcer.Enforce(token, casbin.ResourceApplications, casbin.ActionDelete, resourceObject); !ok {
+			common.WriteJsonResp(w, err, "Unauthorized User", http.StatusForbidden)
+			return
+		}
+	}
 	err = handler.pipelineBuilder.DeleteApp(appId, userId)
 	if err != nil {
 		handler.Logger.Errorw("service error, delete app", "err", err, "appId", appId)
@@ -235,7 +249,16 @@ func (handler PipelineConfigRestHandlerImpl) CreateApp(w http.ResponseWriter, r
 		common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
 		return
 	}
-
+	if createRequest.AppType == helper.Job {
+		isSuperAdmin, err := handler.userAuthService.IsSuperAdmin(int(userId))
+		if !isSuperAdmin || err != nil {
+			if err != nil {
+				handler.Logger.Errorw("request err, CheckSuperAdmin", "err", isSuperAdmin, "isSuperAdmin", isSuperAdmin)
+			}
+			common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized)
+			return
+		}
+	}
 	handler.Logger.Infow("request payload, CreateApp", "CreateApp", createRequest)
 	err = handler.validator.Struct(createRequest)
 	if err != nil {
diff --git a/api/router/GlobalCMCSRouter.go b/api/router/GlobalCMCSRouter.go
index 1c4ca8848..57e650575 100644
--- a/api/router/GlobalCMCSRouter.go
+++ b/api/router/GlobalCMCSRouter.go
@@ -18,6 +18,14 @@ func NewGlobalCMCSRouterImpl(restHandler restHandler.GlobalCMCSRestHandler) *Glo
 }
 
 func (router GlobalCMCSRouterImpl) initGlobalCMCSRouter(configRouter *mux.Router) {
+	configRouter.Path("/{config_name}/{config_type}").
+		HandlerFunc(router.restHandler.GetGlobalCMCSDataByConfigTypeAndName).Methods("GET")
+	configRouter.Path("/all").
+		HandlerFunc(router.restHandler.GetAllGlobalCMCSData).Methods("GET")
 	configRouter.Path("").
 		HandlerFunc(router.restHandler.CreateGlobalCMCSConfig).Methods("POST")
+	configRouter.Path("/update").
+		HandlerFunc(router.restHandler.UpdateGlobalCMCSDataById).Methods("PUT")
+	configRouter.Path("/delete/{id}").
+		HandlerFunc(router.restHandler.DeleteByID).Methods("DELETE")
 }
diff --git a/api/router/JobsRouter.go b/api/router/JobsRouter.go
new file mode 100644
index 000000000..e6130ae93
--- /dev/null
+++ b/api/router/JobsRouter.go
@@ -0,0 +1,28 @@
+package router
+
+import (
+	"github.com/devtron-labs/devtron/api/restHandler"
+	"github.com/devtron-labs/devtron/api/restHandler/app"
+	"github.com/gorilla/mux"
+)
+
+type JobRouter interface {
+	InitJobRouter(router *mux.Router)
+}
+type JobRouterImpl struct {
+	pipelineConfigRestHandler app.PipelineConfigRestHandler
+	appListingRestHandler     restHandler.AppListingRestHandler
+}
+
+func NewJobRouterImpl(pipelineConfigRestHandler app.PipelineConfigRestHandler, appListingRestHandler restHandler.AppListingRestHandler) *JobRouterImpl {
+	return &JobRouterImpl{
+		appListingRestHandler:     appListingRestHandler,
+		pipelineConfigRestHandler: pipelineConfigRestHandler,
+	}
+	//return router
+}
+func (router JobRouterImpl) InitJobRouter(jobRouter *mux.Router) {
+	jobRouter.Path("").HandlerFunc(router.pipelineConfigRestHandler.CreateApp).Methods("POST")
+	jobRouter.Path("/list").HandlerFunc(router.appListingRestHandler.FetchJobs).Methods("POST")
+	jobRouter.Path("/ci-pipeline/list/{jobId}").HandlerFunc(router.appListingRestHandler.FetchJobOverviewCiPipelines).Methods("GET")
+}
diff --git a/api/router/PipelineConfigRouter.go b/api/router/PipelineConfigRouter.go
index 3992375f3..f95674866 100644
--- a/api/router/PipelineConfigRouter.go
+++ b/api/router/PipelineConfigRouter.go
@@ -95,6 +95,7 @@ func (router PipelineConfigRouterImpl) initPipelineConfigRouter(configRouter *mu
 	configRouter.Path("/team/by-name/{teamName}").HandlerFunc(router.restHandler.FindAppsByTeamName).Methods("GET")
 
 	configRouter.Path("/ci-pipeline/trigger").HandlerFunc(router.restHandler.TriggerCiPipeline).Methods("POST")
+
 	configRouter.Path("/{appId}/ci-pipeline/min").HandlerFunc(router.restHandler.GetCiPipelineMin).Methods("GET")
 	configRouter.Path("/ci-pipeline/{pipelineId}/material").HandlerFunc(router.restHandler.FetchMaterials).Methods("GET")
 	configRouter.Path("/ci-pipeline/refresh-material/{gitMaterialId}").HandlerFunc(router.restHandler.RefreshMaterials).Methods("GET")
@@ -169,7 +170,7 @@ func (router PipelineConfigRouterImpl) initPipelineConfigRouter(configRouter *mu
 		HandlerFunc(router.pipelineHistoryRestHandler.FetchDeployedHistoryComponentDetail).
 		Methods("GET")
 
-	configRouter.Path("/history/deployed-configuration/all/latest/{appId}/{pipelineId}").
+	configRouter.Path("/history/deployed-configuration/latest/deployed/{appId}/{pipelineId}").
 		HandlerFunc(router.pipelineHistoryRestHandler.GetAllDeployedConfigurationHistoryForLatestWfrIdForPipeline).
 		Methods("GET")
 
diff --git a/api/router/PipelineTriggerRouter.go b/api/router/PipelineTriggerRouter.go
index 6bbd5753e..18177e564 100644
--- a/api/router/PipelineTriggerRouter.go
+++ b/api/router/PipelineTriggerRouter.go
@@ -66,7 +66,7 @@ func (router PipelineTriggerRouterImpl) initPipelineTriggerRouter(pipelineTrigge
 		Methods("GET").
 		Queries("name", "{name}")
 
-	pipelineTriggerRouter.Path("/deployment-configuration/all/latest/{appId}/{pipelineId}").HandlerFunc(router.restHandler.GetAllLatestDeploymentConfiguration).Methods("GET")
+	pipelineTriggerRouter.Path("/deployment-configuration/latest/saved/{appId}/{pipelineId}").HandlerFunc(router.restHandler.GetAllLatestDeploymentConfiguration).Methods("GET")
 }
 
 func fetchReleaseData(r *http.Request, receive <-chan int, send chan<- int) {
diff --git a/api/router/pubsub/CiEventHandler.go b/api/router/pubsub/CiEventHandler.go
index 3fd2f0db8..dba228538 100644
--- a/api/router/pubsub/CiEventHandler.go
+++ b/api/router/pubsub/CiEventHandler.go
@@ -20,13 +20,25 @@ package pubsub
 import (
 	"encoding/json"
 	"fmt"
+	"github.com/caarlos0/env/v6"
 	pubsub "github.com/devtron-labs/common-lib/pubsub-lib"
 	"github.com/devtron-labs/devtron/internal/sql/repository"
 	"github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig"
 	"github.com/devtron-labs/devtron/pkg/pipeline"
+	"github.com/devtron-labs/devtron/util"
 	"go.uber.org/zap"
 )
 
+type CiEventConfig struct {
+	ExposeCiMetrics bool `env:"EXPOSE_CI_METRICS" envDefault:"false"`
+}
+
+func GetCiEventConfig() (*CiEventConfig, error) {
+	cfg := &CiEventConfig{}
+	err := env.Parse(cfg)
+	return cfg, err
+}
+
 type CiEventHandler interface {
 	Subscribe() error
 	BuildCiArtifactRequest(event CiCompleteEvent) (*pipeline.CiArtifactWebhookRequest, error)
@@ -37,25 +49,30 @@ type CiEventHandlerImpl struct {
 	logger         *zap.SugaredLogger
 	pubsubClient   *pubsub.PubSubClientServiceImpl
 	webhookService pipeline.WebhookService
+	ciEventConfig  *CiEventConfig
 }
 
 type CiCompleteEvent struct {
-	CiProjectDetails []pipeline.CiProjectDetails `json:"ciProjectDetails"`
-	DockerImage      string                      `json:"dockerImage" validate:"required,image-validator"`
-	Digest           string                      `json:"digest"`
-	PipelineId       int                         `json:"pipelineId"`
-	WorkflowId       *int                        `json:"workflowId"`
-	TriggeredBy      int32                       `json:"triggeredBy"`
-	PipelineName     string                      `json:"pipelineName"`
-	DataSource       string                      `json:"dataSource"`
-	MaterialType     string                      `json:"materialType"`
+	CiProjectDetails   []pipeline.CiProjectDetails `json:"ciProjectDetails"`
+	DockerImage        string                      `json:"dockerImage" validate:"required,image-validator"`
+	Digest             string                      `json:"digest"`
+	PipelineId         int                         `json:"pipelineId"`
+	WorkflowId         *int                        `json:"workflowId"`
+	TriggeredBy        int32                       `json:"triggeredBy"`
+	PipelineName       string                      `json:"pipelineName"`
+	DataSource         string                      `json:"dataSource"`
+	MaterialType       string                      `json:"materialType"`
+	Metrics            util.CIMetrics              `json:"metrics"`
+	AppName            string                      `json:"appName"`
+	IsArtifactUploaded bool                        `json:"isArtifactUploaded"`
 }
 
-func NewCiEventHandlerImpl(logger *zap.SugaredLogger, pubsubClient *pubsub.PubSubClientServiceImpl, webhookService pipeline.WebhookService) *CiEventHandlerImpl {
+func NewCiEventHandlerImpl(logger *zap.SugaredLogger, pubsubClient *pubsub.PubSubClientServiceImpl, webhookService pipeline.WebhookService, ciEventConfig *CiEventConfig) *CiEventHandlerImpl {
 	ciEventHandlerImpl := &CiEventHandlerImpl{
 		logger:         logger,
 		pubsubClient:   pubsubClient,
 		webhookService: webhookService,
+		ciEventConfig:  ciEventConfig,
 	}
 	err := ciEventHandlerImpl.Subscribe()
 	if err != nil {
@@ -67,7 +84,7 @@ func NewCiEventHandlerImpl(logger *zap.SugaredLogger, pubsubClient *pubsub.PubSu
 
 func (impl *CiEventHandlerImpl) Subscribe() error {
 	callback := func(msg *pubsub.PubSubMsg) {
-		impl.logger.Debug("ci complete event received")
+		impl.logger.Debugw("ci complete event received")
 		//defer msg.Ack()
 		ciCompleteEvent := CiCompleteEvent{}
 		err := json.Unmarshal([]byte(string(msg.Data)), &ciCompleteEvent)
@@ -80,6 +97,7 @@ func (impl *CiEventHandlerImpl) Subscribe() error {
 		if err != nil {
 			return
 		}
+
 		resp, err := impl.webhookService.HandleCiSuccessEvent(ciCompleteEvent.PipelineId, req)
 		if err != nil {
 			impl.logger.Error(err)
@@ -150,13 +168,14 @@ func (impl *CiEventHandlerImpl) BuildCiArtifactRequest(event CiCompleteEvent) (*
 	}
 
 	request := &pipeline.CiArtifactWebhookRequest{
-		Image:        event.DockerImage,
-		ImageDigest:  event.Digest,
-		DataSource:   event.DataSource,
-		PipelineName: event.PipelineName,
-		MaterialInfo: rawMaterialInfo,
-		UserId:       event.TriggeredBy,
-		WorkflowId:   event.WorkflowId,
+		Image:              event.DockerImage,
+		ImageDigest:        event.Digest,
+		DataSource:         event.DataSource,
+		PipelineName:       event.PipelineName,
+		MaterialInfo:       rawMaterialInfo,
+		UserId:             event.TriggeredBy,
+		WorkflowId:         event.WorkflowId,
+		IsArtifactUploaded: event.IsArtifactUploaded,
 	}
 	return request, nil
 }
@@ -219,13 +238,14 @@ func (impl *CiEventHandlerImpl) BuildCiArtifactRequestForWebhook(event CiComplet
 	}
 
 	request := &pipeline.CiArtifactWebhookRequest{
-		Image:        event.DockerImage,
-		ImageDigest:  event.Digest,
-		DataSource:   event.DataSource,
-		PipelineName: event.PipelineName,
-		MaterialInfo: rawMaterialInfo,
-		UserId:       event.TriggeredBy,
-		WorkflowId:   event.WorkflowId,
+		Image:              event.DockerImage,
+		ImageDigest:        event.Digest,
+		DataSource:         event.DataSource,
+		PipelineName:       event.PipelineName,
+		MaterialInfo:       rawMaterialInfo,
+		UserId:             event.TriggeredBy,
+		WorkflowId:         event.WorkflowId,
+		IsArtifactUploaded: event.IsArtifactUploaded,
 	}
 	return request, nil
 }
diff --git a/api/router/pubsub/WorkflowStatusUpdateHandler.go b/api/router/pubsub/WorkflowStatusUpdateHandler.go
index 76e5fc1c9..532c72e54 100644
--- a/api/router/pubsub/WorkflowStatusUpdateHandler.go
+++ b/api/router/pubsub/WorkflowStatusUpdateHandler.go
@@ -24,7 +24,6 @@ import (
 	"github.com/argoproj/argo-workflows/v3/pkg/apis/workflow/v1alpha1"
 	"github.com/devtron-labs/devtron/api/bean"
 	client "github.com/devtron-labs/devtron/client/events"
-	//"github.com/devtron-labs/devtron/client/pubsub"
 	"github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig"
 	"github.com/devtron-labs/devtron/pkg/pipeline"
 	util "github.com/devtron-labs/devtron/util/event"
diff --git a/api/router/router.go b/api/router/router.go
index 4ac04f750..a5d29b33c 100644
--- a/api/router/router.go
+++ b/api/router/router.go
@@ -55,6 +55,7 @@ type MuxRouter struct {
 	Router                             *mux.Router
 	HelmRouter                         PipelineTriggerRouter
 	PipelineConfigRouter               PipelineConfigRouter
+	JobRouter                          JobRouter
 	MigrateDbRouter                    MigrateDbRouter
 	EnvironmentClusterMappingsRouter   cluster.EnvironmentRouter
 	AppListingRouter                   AppListingRouter
@@ -144,8 +145,8 @@ func NewMuxRouter(logger *zap.SugaredLogger, HelmRouter PipelineTriggerRouter, P
 	serverRouter server.ServerRouter, apiTokenRouter apiToken.ApiTokenRouter,
 	helmApplicationStatusUpdateHandler cron.CdApplicationStatusUpdateHandler, k8sCapacityRouter k8s.K8sCapacityRouter,
 	webhookHelmRouter webhookHelm.WebhookHelmRouter, globalCMCSRouter GlobalCMCSRouter,
-	userTerminalAccessRouter terminal2.UserTerminalAccessRouter, ciStatusUpdateCron cron.CiStatusUpdateCron,
-	appGroupingRouter AppGroupingRouter) *MuxRouter {
+	userTerminalAccessRouter terminal2.UserTerminalAccessRouter,
+	jobRouter JobRouter, ciStatusUpdateCron cron.CiStatusUpdateCron, appGroupingRouter AppGroupingRouter) *MuxRouter {
 	r := &MuxRouter{
 		Router:                             mux.NewRouter(),
 		HelmRouter:                         HelmRouter,
@@ -212,6 +213,7 @@ func NewMuxRouter(logger *zap.SugaredLogger, HelmRouter PipelineTriggerRouter, P
 		globalCMCSRouter:                   globalCMCSRouter,
 		userTerminalAccessRouter:           userTerminalAccessRouter,
 		ciStatusUpdateCron:                 ciStatusUpdateCron,
+		JobRouter:                          jobRouter,
 		appGroupingRouter:                  appGroupingRouter,
 	}
 	return r
@@ -261,6 +263,9 @@ func (r MuxRouter) Init() {
 	r.HelmRouter.initPipelineTriggerRouter(pipelineConfigRouter)
 	r.appRouter.InitAppRouter(pipelineConfigRouter)
 
+	jobConfigRouter := r.Router.PathPrefix("/orchestrator/job").Subrouter()
+	r.JobRouter.InitJobRouter(jobConfigRouter)
+
 	migrateRouter := r.Router.PathPrefix("/orchestrator/migrate").Subrouter()
 	r.MigrateDbRouter.InitMigrateDbRouter(migrateRouter)
 
diff --git a/client/cron/CdApplicationStatusUpdateHandler.go b/client/cron/CdApplicationStatusUpdateHandler.go
index 10b7ee3a6..fc371afc9 100644
--- a/client/cron/CdApplicationStatusUpdateHandler.go
+++ b/client/cron/CdApplicationStatusUpdateHandler.go
@@ -134,13 +134,13 @@ func (impl *CdApplicationStatusUpdateHandlerImpl) HelmApplicationStatusUpdate()
 }
 
 func (impl *CdApplicationStatusUpdateHandlerImpl) ArgoApplicationStatusUpdate() {
-	degradedTime, err := strconv.Atoi(impl.AppStatusConfig.PipelineDegradedTime)
+	getPipelineDeployedBeforeMinutes, err := strconv.Atoi(impl.AppStatusConfig.PipelineDegradedTime)
 	if err != nil {
 		impl.logger.Errorw("error in converting string to int", "err", err)
 		return
 	}
-
-	err = impl.CdHandler.CheckArgoAppStatusPeriodicallyAndUpdateInDb(degradedTime)
+	getPipelineDeployedWithinHours := impl.AppStatusConfig.GetPipelineDeployedWithinHours
+	err = impl.CdHandler.CheckArgoAppStatusPeriodicallyAndUpdateInDb(getPipelineDeployedBeforeMinutes, getPipelineDeployedWithinHours)
 	if err != nil {
 		impl.logger.Errorw("error argo app status update - cron job", "err", err)
 		return
diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md
index b991c2ab6..90dbfa8d8 100644
--- a/docs/SUMMARY.md
+++ b/docs/SUMMARY.md
@@ -74,6 +74,12 @@
     * [Debugging Deployment And Monitoring](user-guide/debugging-deployment-and-monitoring.md)
     * [Application Metrics](user-guide/creating-application/app-metrics.md) 
   * [Overview](user-guide/creating-application/overview.md)
+* [Jobs](user-guide/jobs/README.md)
+  * [Create a new job](user-guide/jobs/create-job.md)
+  * [Configurations](user-guide/jobs/configuration-job.md)
+  * [Workflow Editor](user-guide/jobs/workflow-editor-job.md)
+  * [Trigger Job](user-guide/jobs/triggering-job.md)
+  * [Overview](user-guide/jobs/overview-job.md) 
 * [Resource Browser](user-guide/resource-browser.md)   
 * [Charts](user-guide/deploy-chart/README.md)
   * [Charts Overview](user-guide/deploy-chart/overview-of-charts.md)
diff --git a/docs/user-guide/jobs/README.md b/docs/user-guide/jobs/README.md
new file mode 100644
index 000000000..133b579e5
--- /dev/null
+++ b/docs/user-guide/jobs/README.md
@@ -0,0 +1,18 @@
+# Jobs
+
+Job allows manual and automated execution of your source code. Job pipeline will not have CI/CD pipeline as the job is limited to your source code only. You can also configure [preset plugins](https://docs.devtron.ai/v/v0.6/usage/applications/creating-application/ci-pipeline/ci-build-pre-post-plugins#preset-plugins) in your job pipeline.
+
+With job, you can execute your source code quickly and easily without going through CI/CD pipelines, which also optimize time.
+
+![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/create-job/jobs.jpg)
+
+There are two main steps in executing Job:
+
+* [Configurations](configuration-job.md)
+
+* [Trigger Job](triggering-cd.md)
+
+In the next section, we will learn on how to create, configure, trigger a job. You can also view the details on the [Overview](overview-job.md) tab and `Run History`.
+
+
+
diff --git a/docs/user-guide/jobs/configuration-job.md b/docs/user-guide/jobs/configuration-job.md
new file mode 100644
index 000000000..c513c4e3a
--- /dev/null
+++ b/docs/user-guide/jobs/configuration-job.md
@@ -0,0 +1,9 @@
+# Configuration
+
+For the Jobs, you must configure the following sections before you run and trigger the job:
+
+[Source Code](https://docs.devtron.ai/v/v0.6/usage/applications/creating-application/git-material)
+
+[Workflow Editor](workflow-editor-job.md)
+
+
diff --git a/docs/user-guide/jobs/create-job.md b/docs/user-guide/jobs/create-job.md
new file mode 100644
index 000000000..2573747b6
--- /dev/null
+++ b/docs/user-guide/jobs/create-job.md
@@ -0,0 +1,42 @@
+# Create a New Job
+
+* On the Devtron dashboard, select **Jobs**.
+* On the upper-right corner of the screen, click **Create**.
+* Select **Job** from the drop-down list.
+* **Create job** page opens.
+
+![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/create-job/select-create-job-latest.jpg)
+
+
+## Create Job
+
+![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/create-job/create-job-page.jpg)
+
+
+Provide below information on the `Create job` page:
+
+| Fields | Description |
+| --- | --- |
+| **Job Name** | User-defined name for the job in Devtron. |
+| **Description** | Enter the decription of a job. |
+| **Registry URL** | This is the URL of your private registry in Quay. E.g. `quay.io` |
+| **Select one of them** |  <ul><li>**Create from scratch** :Select the project from the drop-down list.<br>`Note`: You have to add [project under Global Configurations](https://docs.devtron.ai/global-configurations/projects). Only then, it will appear in the drop-down list here.</li><li>**Clone existing application**: Select an app you want to clone from and the project from the drop-down list.<br>`Note`: You have to add [project under Global Configurations](https://docs.devtron.ai/global-configurations/projects). Only then, it will appear in the drop-down list here.</li></ul> |
+
+**Note**: Do not forget to modify git repositories and corresponding branches to be used for each Job Pipeline if required.
+
+
+### Tags
+
+`Tags` are key-value pairs. You can add one or multiple tags in your application. 
+
+**Propagate Tags** 
+When tags are propagated, they are considered as labels to Kubernetes resources. Kubernetes offers integrated support for using these labels to query objects and perform bulk operations e.g., consolidated billing using labels. You can use these tags to filter/identify resources via CLI or in other Kubernetes tools.
+
+![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/creating-application/propagate-tags.jpg)
+
+* Click `+ Add tag` to add a new tag.
+* Click the symbol <img src="https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/creating-application/donot-propagate.jpg"  height="10"> on the left side of your tag to propagate a tag.<br>`Note`: Dark grey colour in symbol specifies that the tags are propagated.
+* To remove the tags from propagation, click the symbol <img src="https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/creating-application/propagate-dark.jpg" height="10"> again.
+* Click `Save`.
+
+
diff --git a/docs/user-guide/jobs/overview-job.md b/docs/user-guide/jobs/overview-job.md
new file mode 100644
index 000000000..ec2a06b07
--- /dev/null
+++ b/docs/user-guide/jobs/overview-job.md
@@ -0,0 +1,49 @@
+# Overview
+
+The `Overview` section contains the brief information of the job, any added tags, and deployment details of the particular job. 
+In this section, you can also [change project of your job](#change-project-of-your-job) and [manage tags](#manage-tags) if you added them while creating job.
+
+![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/create-job/overview-job.jpg)
+
+
+The following details are provided on the **Overview** page:
+
+| Fields | Description |
+| :---    |     :---       |
+| **Job Name**  | Displays the name of the job. |
+| **Created on** | Displays the day, date and time the job was created. |
+| **Created by**  | Displays the email address of a user who created the job. |
+| **Project**   | Displays the currect project of the job. You can change the project by selecting a different project from the drop-down list. |
+
+
+## Change Project of your Job
+
+You can change the project of your job by clicking **Project** on the `Overview` section.
+
+1. Click `Project`. 
+2. On the `Change project` dialog box, select the different project you want to change from the drop-down list.
+
+Click **Save**. The job will be moved to the selected project.
+
+## Manage Tags
+
+`Tags` are key-value pairs. You can add one or multiple tags in your application. When tags are propagated, they are considered as labels to Kubernetes resources. Kubernetes offers integrated support for using these labels to query objects and perform bulk operations e.g., consolidated billing using labels. You can use these tags to filter/identify resources via CLI or in other Kubernetes tools.
+
+`Manage tags` is the central place where you can create, edit, and delete tags. You can also propagate tags as labels to Kubernetes resources for the application.
+
+![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/creating-application/manage-tags-latest.jpg)
+
+* Click `Edit tags`.
+* On the `Manage tags` page, click `+ Add tag` to add a new tag.
+* Click `X` to delete a tag.
+* Click the symbol <img src="https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/creating-application/donot-propagate.jpg" height="10"> on the left side of your tag to propagate a tag.<br>`Note`: Dark grey colour in symbol specifies that the tags are propagated.
+* To remove the tags from propagation, click the symbol <img src="https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/creating-application/propagate-dark.jpg" height="10"> again.
+* Click `Save`.
+
+The changes in the tags will be reflected in the `Tags` on the `Overview` section.
+
+
+
+
+
+ 
diff --git a/docs/user-guide/jobs/triggering-job.md b/docs/user-guide/jobs/triggering-job.md
new file mode 100644
index 000000000..4cbe03082
--- /dev/null
+++ b/docs/user-guide/jobs/triggering-job.md
@@ -0,0 +1,34 @@
+# Triggering Job 
+
+## Triggering Job Pipeline
+
+The Job Pipeline can be triggered by selecting `Select Material`
+
+![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/create-job/trigger-job.jpg)
+
+Job Pipelines that are set as automatic are always triggered as soon as a new commit is made to the git branch they're sensing. However, Job pipelines can always be manually triggered as and if required.
+
+Various commits done in the repository can be seen here along with details like Author, Date etc. Select the commit that you want to trigger and then click on `Run Job` to trigger the job pipeline.
+
+![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/create-job/run-job.jpg)
+
+
+**Refresh** icon, refreshes Git Commits in the job Pipeline and fetches the latest commits from the `Git Repository`.
+
+**Ignore Cache** : This option will ignore the previous build cache and create a fresh build. If selected, will take a longer build time than usual.
+
+It can be seen that the job pipeline is triggered here and is the _Running_ state.
+
+![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/create-job/click-job-details.jpg)
+
+Click your `job pipeline` or click `Run History` to get the details about the job pipeline such as logs, reports etc.
+
+![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/create-job/run-history-job.jpg)
+
+Click `Source code` to view the details such as commit id, Author and commit message of the Git Material that you have selected for the job.
+
+Click `Artifacts` to download the _reports_ of the job, if any.
+
+If you have mulitple job pipelines, you can select a pipeline from the drop-down list to view th details of logs, source code, or artifacts.
+
+
diff --git a/docs/user-guide/jobs/workflow-editor-job.md b/docs/user-guide/jobs/workflow-editor-job.md
new file mode 100644
index 000000000..d73ae98df
--- /dev/null
+++ b/docs/user-guide/jobs/workflow-editor-job.md
@@ -0,0 +1,98 @@
+# Workflow Editor
+
+In the `Workflow Editor` section, you can configure a job pipeline to be executed. Pipelines can be configured to be triggered automatically or manually based on code change or time.
+
+* After adding Git repo in the `Source Code` section, go to the `Workflow Editor`. 
+* Click `Job Pipeline`.
+* Provide the information in the following fields on the **Create job pipeline** page:
+
+![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/create-job/create-job-pipeline-basic.jpg)
+
+| Field Name | Required/Optional | Description |
+| :--- | :--- | :--- |
+| Pipeline Name | Required | A name for the pipeline |
+| Source type | Required | Source type to trigger the job pipeline. Available options: [Branch Fixed](#source-type-branch-fixed) \| [Branch Regex](#source-type-branch-regex) \|[Pull Request](#source-type-pull-request) \| [Tag Creation](#source-type-tag-creation) |
+| Branch Name | Required | Branch that triggers the job pipeline. |
+
+* Click **Create Pipeline**.
+
+* The job pipeline is created.
+
+![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/create-job/job-pipeline-created.jpg)
+
+* To trigger job pipeline, go to the [Trigger Job](triggering-job.md) section. 
+
+`Note`: You can create more than one job pipeline by clicking **+ Job Pipeine**.
+
+
+### Source type: Branch Fixed
+
+The **Source type** - "Branch Fixed" allows you to trigger a CI build whenever there is a code change on the specified branch.
+
+Select the **Source type** as "Branch Fixed" and enter the **Branch Name**.
+
+### Source type: Branch Regex
+
+`Branch Regex` allows users to easily switch between branches matching the configured Regex before triggering the build pipeline.
+In case of `Branch Fixed`, users cannot change the branch name in ci-pipeline unless they have admin access for the app. So, if users with 
+`Build and Deploy` access should be allowed to switch branch name before triggering ci-pipeline, `Branch Regex` should be selected as source type by a user with Admin access.
+
+For example if the user sets the Branch Regex as `feature-*`, then users can trigger from branches such as `feature-1450`, `feature-hot-fix` etc.
+
+### Source type: Pull Request
+
+The **Source type** - "Pull Request" allows you to configure the CI Pipeline using the PR raised in your repository.
+
+> Before you begin, [configure the webhook](#configuring-webhook) for either GitHub or Bitbucket.
+
+> The "Pull Request" source type feature only works for the host GitHub or Bitbucket cloud for now. To request support for a different Git host, please create a github issue [here](https://github.com/devtron-labs/devtron/issues).
+
+
+To trigger the build from specific PRs, you can filter the PRs based on the following keys:
+
+| Filter key | Description |
+| :--- | :--- |
+| `Author` | Author of the PR |
+| `Source branch name` | Branch from which the Pull Request is generated |
+| `Target branch name` | Branch to which the Pull request will be merged |
+| `Title` | Title of the Pull Request |
+| `State` | State of the PR. Default is "open" and cannot be changed |
+
+Select the appropriate filter and pass the matching condition as a regular expression (`regex`).
+
+> Devtron uses regexp library, view [regexp cheatsheet](https://yourbasic.org/golang/regexp-cheat-sheet/). You can test your custom regex from [here](https://regex101.com/r/lHHuaE/1).
+
+### Source type: Tag Creation
+
+The **Source type** - "Tag Creation" allows you to build the CI pipeline from a tag.
+
+> Before you begin, [configure the webhook](#configuring-webhook) for either GitHub or Bitbucket.
+
+To trigger the build from specific tags, you can filter the tags based on the `author` and/or the `tag name`.
+
+| Filter key | Description |
+| :--- | :--- |
+| `Author` | The one who created the tag |
+| `Tag name` | Name of the tag for which the webhook will be triggered |
+
+Select the appropriate filter and pass the matching condition as a regular expression (`regex`).
+
+
+### Add Preset Plugins
+
+![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/create-job/create-job-pipeline-add-tasks.jpg)
+
+You can also add preset plugins in your job pipeline to execute some standard tasks, such as Code analysis, Load testing, Security scanning etc. Click `Add Task` to add [preset plugins](https://docs.devtron.ai/v/v0.6/usage/applications/creating-application/ci-pipeline/ci-build-pre-post-plugins#configuring-pre-post-build-tasks).
+
+
+## Update Job Pipeline
+
+You can update the configurations of an existing Job Pipeline except for the pipeline's name.
+To update a pipeline, select your job pipeline.
+In the **Edit job pipeline** window, edit the required fields and select **Update Pipeline**.
+
+## Delete Job Pipeline
+
+You can only delete a job pipeline in your workflow.
+
+To delete a job pipeline, go to **Configurations > Workflow Editor** and select **Delete Pipeline**.
diff --git a/go.mod b/go.mod
index 8ce0b4ff2..cdec16434 100644
--- a/go.mod
+++ b/go.mod
@@ -36,7 +36,6 @@ require (
 	github.com/ktrysmt/go-bitbucket v0.9.40
 	github.com/lib/pq v1.10.4
 	github.com/microsoft/azure-devops-go-api/azuredevops v1.0.0-b5
-	github.com/nats-io/nats.go v1.19.0
 	github.com/otiai10/copy v1.0.2
 	github.com/patrickmn/go-cache v2.1.0+incompatible
 	github.com/pkg/errors v0.9.1
@@ -190,6 +189,7 @@ require (
 	github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
 	github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
 	github.com/nats-io/jwt/v2 v2.2.1-0.20220330180145-442af02fd36a // indirect
+	github.com/nats-io/nats.go v1.19.0 // indirect
 	github.com/nats-io/nkeys v0.3.0 // indirect
 	github.com/nats-io/nuid v1.0.1 // indirect
 	github.com/oliveagle/jsonpath v0.0.0-20180606110733-2e52cf6e6852 // indirect
diff --git a/go.sum b/go.sum
index caa5c5f55..373ab84e2 100644
--- a/go.sum
+++ b/go.sum
@@ -282,20 +282,6 @@ github.com/denisenkom/go-mssqldb v0.0.0-20190707035753-2be1aa521ff4 h1:YcpmyvADG
 github.com/denisenkom/go-mssqldb v0.0.0-20190707035753-2be1aa521ff4/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM=
 github.com/devtron-labs/authenticator v0.4.31-0.20221213131053-6e4668309f53 h1:oHDpsCsuYiL+u5TEhilKNLGhH9lwRNkIqrzhHQA6d3c=
 github.com/devtron-labs/authenticator v0.4.31-0.20221213131053-6e4668309f53/go.mod h1:ozNfT8WcruiSgnUbyp48WVfc41++W6xYXhKFp67lNTU=
-github.com/devtron-labs/common-lib v0.0.0-20221028123910-ac349a64526a h1:g2S75h+OAXXN5SGsdxxCfmKZXJFGUKTNtPaUW5Gp9ck=
-github.com/devtron-labs/common-lib v0.0.0-20221028123910-ac349a64526a/go.mod h1:wDldcLG0CzfnxCBEXeitEkYF9bk62yG+HLGqQg6VZ4o=
-github.com/devtron-labs/common-lib v0.0.0-20221111092855-6dae5a34a041 h1:4yQ7v/fC39TzKzcn24CHzB8XL2wl3JFhsJ1VsXiTjXQ=
-github.com/devtron-labs/common-lib v0.0.0-20221111092855-6dae5a34a041/go.mod h1:PWHsHmhRVy50rvYlTv2bfoW/4oX8lPTcITiF8l9+ULg=
-github.com/devtron-labs/common-lib v0.0.0-20221111102018-8cffc22d80e3 h1:wswsi1r6tDtmycUaUGGUtoUNbKvQyJByKyxiDm+o9Lw=
-github.com/devtron-labs/common-lib v0.0.0-20221111102018-8cffc22d80e3/go.mod h1:PWHsHmhRVy50rvYlTv2bfoW/4oX8lPTcITiF8l9+ULg=
-github.com/devtron-labs/common-lib v0.0.0-20221117072858-bd2f19e16dd2 h1:dEtjnQqSWGCl4sIWYvsBsJuBLfmVV2kw1OyuBpkAp64=
-github.com/devtron-labs/common-lib v0.0.0-20221117072858-bd2f19e16dd2/go.mod h1:PWHsHmhRVy50rvYlTv2bfoW/4oX8lPTcITiF8l9+ULg=
-github.com/devtron-labs/common-lib v0.0.0-20221126093411-794588b004ea h1:cJWdGd6bXNGqt7yWjsIhV3mHcnhe2T3s3e7hKOgK2iU=
-github.com/devtron-labs/common-lib v0.0.0-20221126093411-794588b004ea/go.mod h1:R24nOqgk4buk9zv+BXzORfObZsOe3NE9P55KrZXGX9k=
-github.com/devtron-labs/common-lib v0.0.0-20221130083108-d35a1c63675b h1:Z9tehff98lhxdX9Z7ggdBuFzrCNacr4hIjdNCRubVt8=
-github.com/devtron-labs/common-lib v0.0.0-20221130083108-d35a1c63675b/go.mod h1:R24nOqgk4buk9zv+BXzORfObZsOe3NE9P55KrZXGX9k=
-github.com/devtron-labs/common-lib v0.0.0-20221208044859-269008fed09b h1:yGXerrqwyjPIr62q1RadJh6MYH3vG6T9nChH+yOJnnA=
-github.com/devtron-labs/common-lib v0.0.0-20221208044859-269008fed09b/go.mod h1:R24nOqgk4buk9zv+BXzORfObZsOe3NE9P55KrZXGX9k=
 github.com/devtron-labs/common-lib v0.0.0-20230109070754-ff4dca200a2c h1:jz7yPUlIJXFg9AvJh2fb0QW7JT6+RKj8LOl1mWM/HQA=
 github.com/devtron-labs/common-lib v0.0.0-20230109070754-ff4dca200a2c/go.mod h1:R24nOqgk4buk9zv+BXzORfObZsOe3NE9P55KrZXGX9k=
 github.com/devtron-labs/common-lib v0.0.0-20230202071119-47116fd18242 h1:FfS2R86Ft/WFShnwGu4z14iOKZAPhfDV7tvvlaJfRmI=
@@ -897,8 +883,6 @@ github.com/nats-io/jwt/v2 v2.2.1-0.20220330180145-442af02fd36a/go.mod h1:0tqz9Hl
 github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k=
 github.com/nats-io/nats-server/v2 v2.8.4 h1:0jQzze1T9mECg8YZEl8+WYUXb9JKluJfCBriPUtluB4=
 github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w=
-github.com/nats-io/nats.go v1.15.0 h1:3IXNBolWrwIUf2soxh6Rla8gPzYWEZQBUBK6RV21s+o=
-github.com/nats-io/nats.go v1.15.0/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w=
 github.com/nats-io/nats.go v1.19.0 h1:H6j8aBnTQFoVrTGB6Xjd903UMdE7jz6DS4YkmAqgZ9Q=
 github.com/nats-io/nats.go v1.19.0/go.mod h1:tLqubohF7t4z3du1QDPYJIQQyhb4wl6DhjxEajSI7UA=
 github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
diff --git a/internal/constants/InternalErrorCode.go b/internal/constants/InternalErrorCode.go
index e8dc49384..7a60d5d29 100644
--- a/internal/constants/InternalErrorCode.go
+++ b/internal/constants/InternalErrorCode.go
@@ -82,3 +82,4 @@ const (
 )
 
 var AppAlreadyExists = &ErrorCode{"4001", "application %s already exists"}
+var AppDoesNotExist = &ErrorCode{"4004", "application %s does not exist"}
diff --git a/internal/middleware/instrument.go b/internal/middleware/instrument.go
index 6d293a8d6..e7b41cb2d 100644
--- a/internal/middleware/instrument.go
+++ b/internal/middleware/instrument.go
@@ -33,11 +33,52 @@ var (
 	}, []string{"path", "method", "status"})
 )
 
+var PgQueryDuration = promauto.NewHistogramVec(prometheus.HistogramOpts{
+	Name: "pg_query_duration_seconds",
+	Help: "Duration of PG queries",
+}, []string{"label"})
+
 var CdDuration = promauto.NewHistogramVec(prometheus.HistogramOpts{
 	Name: "cd_duration_seconds",
 	Help: "Duration of CD process",
 }, []string{"appName", "status", "envName", "deploymentType"})
 
+var CiDuration = promauto.NewHistogramVec(prometheus.HistogramOpts{
+	Name:    "ci_duration_seconds",
+	Help:    "Duration of CI process",
+	Buckets: prometheus.LinearBuckets(20, 20, 5),
+}, []string{"pipelineName", "appName"})
+
+var CacheDownloadDuration = promauto.NewHistogramVec(prometheus.HistogramOpts{
+	Name:    "cache_download_duration_seconds",
+	Help:    "Duration of Cache Download process",
+	Buckets: prometheus.LinearBuckets(20, 20, 5),
+}, []string{"pipelineName", "appName"})
+
+var PreCiDuration = promauto.NewHistogramVec(prometheus.HistogramOpts{
+	Name:    "pre_ci_duration_seconds",
+	Help:    "Duration of Pre CI process",
+	Buckets: prometheus.LinearBuckets(20, 20, 5),
+}, []string{"pipelineName", "appName"})
+
+var BuildDuration = promauto.NewHistogramVec(prometheus.HistogramOpts{
+	Name:    "build_duration_seconds",
+	Help:    "Duration of Build process",
+	Buckets: prometheus.LinearBuckets(20, 20, 5),
+}, []string{"pipelineName", "appName"})
+
+var PostCiDuration = promauto.NewHistogramVec(prometheus.HistogramOpts{
+	Name:    "post_ci_duration_seconds",
+	Help:    "Duration of Post CI process",
+	Buckets: prometheus.LinearBuckets(20, 20, 5),
+}, []string{"pipelineName", "appName"})
+
+var CacheUploadDuration = promauto.NewHistogramVec(prometheus.HistogramOpts{
+	Name:    "cache_upload_duration_seconds",
+	Help:    "Duration of Cache Upload process",
+	Buckets: prometheus.LinearBuckets(20, 20, 5),
+}, []string{"pipelineName", "appName"})
+
 var requestCounter = promauto.NewCounterVec(
 	prometheus.CounterOpts{
 		Name: "orchestrator_http_requests_total",
@@ -60,7 +101,7 @@ var CdTriggerCounter = promauto.NewCounterVec(prometheus.CounterOpts{
 
 var CiTriggerCounter = promauto.NewCounterVec(prometheus.CounterOpts{
 	Name: "ci_trigger_counter",
-}, []string{"appName"})
+}, []string{"appName", "pipelineName"})
 
 // prometheusMiddleware implements mux.MiddlewareFunc.
 func PrometheusMiddleware(next http.Handler) http.Handler {
diff --git a/internal/sql/repository/AppListingRepository.go b/internal/sql/repository/AppListingRepository.go
index 860b35048..793eaa543 100644
--- a/internal/sql/repository/AppListingRepository.go
+++ b/internal/sql/repository/AppListingRepository.go
@@ -37,11 +37,14 @@ import (
 
 type AppListingRepository interface {
 	FetchAppsByEnvironment(appListingFilter helper.AppListingFilter) ([]*bean.AppEnvironmentContainer, error)
+	FetchJobs(appIds []int, statuses []string, sortOrder string) ([]*bean.JobListingContainer, error)
+	FetchOverviewCiPipelines(jobId int) ([]*bean.JobListingContainer, error)
+	FetchJobsLastSucceededOn(ciPipelineIDs []int) ([]*bean.CiPipelineLastSucceededTime, error)
 	DeploymentDetailsByAppIdAndEnvId(ctx context.Context, appId int, envId int) (bean.DeploymentDetailContainer, error)
 	FetchAppDetail(ctx context.Context, appId int, envId int) (bean.AppDetailContainer, error)
 
 	FetchAppTriggerView(appId int) ([]bean.TriggerView, error)
-	FetchAppStageStatus(appId int) ([]bean.AppStageStatus, error)
+	FetchAppStageStatus(appId int, appType int) ([]bean.AppStageStatus, error)
 
 	//Not in used
 	PrometheusApiByEnvId(id int) (*string, error)
@@ -80,11 +83,47 @@ func NewAppListingRepositoryImpl(Logger *zap.SugaredLogger, dbConnection *pg.DB,
 	return &AppListingRepositoryImpl{dbConnection: dbConnection, Logger: Logger, appListingRepositoryQueryBuilder: appListingRepositoryQueryBuilder}
 }
 
-/*
-*
-It will return the list of filtered apps with details related to each env
-*/
+func (impl AppListingRepositoryImpl) FetchJobs(appIds []int, statuses []string, sortOrder string) ([]*bean.JobListingContainer, error) {
+	var jobContainers []*bean.JobListingContainer
+	if len(appIds) == 0 {
+		return jobContainers, nil
+	}
+	jobsQuery := impl.appListingRepositoryQueryBuilder.BuildJobListingQuery(appIds, statuses, sortOrder)
+
+	impl.Logger.Debugw("basic app detail query: ", jobsQuery)
+	_, appsErr := impl.dbConnection.Query(&jobContainers, jobsQuery)
+	if appsErr != nil {
+		impl.Logger.Error(appsErr)
+		return jobContainers, appsErr
+	}
+	return jobContainers, nil
+}
+func (impl AppListingRepositoryImpl) FetchOverviewCiPipelines(jobId int) ([]*bean.JobListingContainer, error) {
+	var jobContainers []*bean.JobListingContainer
+	jobsQuery := impl.appListingRepositoryQueryBuilder.OverviewCiPipelineQuery()
+	impl.Logger.Debugw("basic app detail query: ", jobsQuery)
+	_, appsErr := impl.dbConnection.Query(&jobContainers, jobsQuery, jobId)
+	if appsErr != nil {
+		impl.Logger.Error(appsErr)
+		return jobContainers, appsErr
+	}
+	return jobContainers, nil
+}
 
+func (impl AppListingRepositoryImpl) FetchJobsLastSucceededOn(CiPipelineIDs []int) ([]*bean.CiPipelineLastSucceededTime, error) {
+	var lastSucceededTimeArray []*bean.CiPipelineLastSucceededTime
+	if len(CiPipelineIDs) == 0 {
+		return lastSucceededTimeArray, nil
+	}
+	jobsLastFinishedOnQuery := impl.appListingRepositoryQueryBuilder.JobsLastSucceededOnTimeQuery(CiPipelineIDs)
+	impl.Logger.Debugw("basic app detail query: ", jobsLastFinishedOnQuery)
+	_, appsErr := impl.dbConnection.Query(&lastSucceededTimeArray, jobsLastFinishedOnQuery)
+	if appsErr != nil {
+		impl.Logger.Errorw("error in fetching lastSucceededTimeArray", "error", appsErr, jobsLastFinishedOnQuery)
+		return lastSucceededTimeArray, appsErr
+	}
+	return lastSucceededTimeArray, nil
+}
 func (impl AppListingRepositoryImpl) FetchAppsByEnvironment(appListingFilter helper.AppListingFilter) ([]*bean.AppEnvironmentContainer, error) {
 	impl.Logger.Debug("reached at FetchAppsByEnvironment:")
 	var appEnvArr []*bean.AppEnvironmentContainer
@@ -174,7 +213,7 @@ func (impl AppListingRepositoryImpl) DeploymentDetailsByAppIdAndEnvId(ctx contex
 		" INNER JOIN ci_artifact cia on cia.id = pco.ci_artifact_id" +
 		" INNER JOIN app a ON a.id=p.app_id" +
 		" LEFT JOIN users u on u.id=pco.created_by" +
-		" WHERE a.app_store is false AND a.id=? AND env.id=? AND p.deleted = FALSE AND env.active = TRUE" +
+		" WHERE a.app_type = 0 AND a.id=? AND env.id=? AND p.deleted = FALSE AND env.active = TRUE" +
 		" ORDER BY pco.created_on desc limit 1;"
 	impl.Logger.Debugf("query:", query)
 	_, err := impl.dbConnection.Query(&deploymentDetail, query, appId, envId)
@@ -314,7 +353,7 @@ func (impl AppListingRepositoryImpl) FetchAppTriggerView(appId int) ([]bean.Trig
 		" INNER JOIN ci_pipeline cp on cp.id = p.ci_pipeline_id" +
 		" INNER JOIN app a ON a.id = p.app_id" +
 		" INNER JOIN environment env on env.id = p.environment_id" +
-		" WHERE p.app_id=? and p.deleted=false and a.app_store is false AND env.active = TRUE;"
+		" WHERE p.app_id=? and p.deleted=false and a.app_type = 0 AND env.active = TRUE;"
 
 	impl.Logger.Debugw("query", query)
 	_, err := impl.dbConnection.Query(&triggerView, query, appId)
@@ -370,7 +409,7 @@ func (impl AppListingRepositoryImpl) FetchAppTriggerView(appId int) ([]bean.Trig
 	return triggerViewResponse, nil
 }
 
-func (impl AppListingRepositoryImpl) FetchAppStageStatus(appId int) ([]bean.AppStageStatus, error) {
+func (impl AppListingRepositoryImpl) FetchAppStageStatus(appId int, appType int) ([]bean.AppStageStatus, error) {
 	impl.Logger.Debug("reached at AppListingRepository:")
 	var appStageStatus []bean.AppStageStatus
 
@@ -393,11 +432,11 @@ func (impl AppListingRepositoryImpl) FetchAppStageStatus(appId int) ([]bean.AppS
 		" LEFT JOIN charts ch on ch.app_id=app.id" +
 		" LEFT JOIN pipeline p on p.app_id=app.id" +
 		" LEFT JOIN chart_env_config_override ceco on ceco.chart_id=ch.id" +
-		" WHERE app.id=? and app.app_store is false;"
+		" WHERE app.id=? and app.app_type = ? limit 1;"
 
 	impl.Logger.Debugw("last app stages status query:", "query", query)
 
-	_, err := impl.dbConnection.Query(&stages, query, appId)
+	_, err := impl.dbConnection.Query(&stages, query, appId, appType)
 	if err != nil {
 		impl.Logger.Errorw("error:", err)
 		return appStageStatus, err
diff --git a/internal/sql/repository/CiArtifactRepository.go b/internal/sql/repository/CiArtifactRepository.go
index 307e24fee..d58416fb3 100644
--- a/internal/sql/repository/CiArtifactRepository.go
+++ b/internal/sql/repository/CiArtifactRepository.go
@@ -43,6 +43,7 @@ type CiArtifact struct {
 	ScanEnabled          bool      `sql:"scan_enabled,notnull"`
 	Scanned              bool      `sql:"scanned,notnull"`
 	ExternalCiPipelineId int       `sql:"external_ci_pipeline_id"`
+	IsArtifactUploaded   bool      `sql:"is_artifact_uploaded"`
 	DeployedTime         time.Time `sql:"-"`
 	Deployed             bool      `sql:"-"`
 	Latest               bool      `sql:"-"`
diff --git a/internal/sql/repository/GlobalCMCSRepository.go b/internal/sql/repository/GlobalCMCSRepository.go
index f4296a080..78c758f44 100644
--- a/internal/sql/repository/GlobalCMCSRepository.go
+++ b/internal/sql/repository/GlobalCMCSRepository.go
@@ -1,7 +1,6 @@
 package repository
 
 import (
-	"encoding/json"
 	"github.com/devtron-labs/devtron/pkg/sql"
 	"github.com/go-pg/pg"
 	"go.uber.org/zap"
@@ -11,8 +10,11 @@ type GlobalCMCSRepository interface {
 	Save(model *GlobalCMCS) (*GlobalCMCS, error)
 	Update(model *GlobalCMCS) (*GlobalCMCS, error)
 	FindAllActive() ([]*GlobalCMCS, error)
+	FindById(id int) (*GlobalCMCS, error)
 	FindByConfigTypeAndName(configType, name string) (*GlobalCMCS, error)
 	FindByMountPath(mountPath string) (*GlobalCMCS, error)
+	FindAllActiveByPipelineType(pipelineType string) ([]*GlobalCMCS, error)
+	Delete(model *GlobalCMCS) error
 }
 
 const (
@@ -22,6 +24,12 @@ const (
 	VOLUME_CONFIG      = "volume"
 )
 
+const (
+	PIPELINE_TYPE_CI    = "CI"
+	PIPELINE_TYPE_CD    = "CD"
+	PIPELINE_TYPE_CI_CD = "CI/CD"
+)
+
 type GlobalCMCSRepositoryImpl struct {
 	dbConnection *pg.DB
 	logger       *zap.SugaredLogger
@@ -38,9 +46,10 @@ type GlobalCMCS struct {
 	Name       string   `sql:"name"`
 	Type       string   `sql:"type"` // [environment, volume]
 	//json string of map of key:value, example: '{ "a" : "b", "c" : "d"}'
-	Data      json.RawMessage `sql:"data"`
-	MountPath string          `sql:"mount_path"`
-	Deleted   bool            `sql:"deleted,notnull"`
+	Data               string `sql:"data"`
+	MountPath          string          `sql:"mount_path"`
+	Deleted            bool            `sql:"deleted,notnull"`
+	SecretIngestionFor string          `sql:"secret_ingestion_for,notnull"` // [CI, CD, CI/CD]
 	sql.AuditLog
 }
 
@@ -97,3 +106,35 @@ func (impl *GlobalCMCSRepositoryImpl) FindByMountPath(mountPath string) (*Global
 	}
 	return model, nil
 }
+
+func (impl *GlobalCMCSRepositoryImpl) FindAllActiveByPipelineType(pipelineType string) ([]*GlobalCMCS, error) {
+	var models []*GlobalCMCS
+	err := impl.dbConnection.Model(&models).
+		Where("deleted = ?", false).
+		Where("secret_ingestion_for = ? OR secret_ingestion_for = ?", pipelineType, PIPELINE_TYPE_CI_CD).
+		Select()
+	if err != nil {
+		impl.logger.Errorw("err on getting global cm/cs config to be used by default in ci/cd pipeline", "err", err)
+		return nil, err
+	}
+	return models, nil
+}
+
+func (impl *GlobalCMCSRepositoryImpl) FindById(id int) (*GlobalCMCS, error) {
+	model := &GlobalCMCS{}
+	err := impl.dbConnection.Model(model).Where("id = ? ", id).Select()
+	if err != nil {
+		impl.logger.Errorw("err on getting global cm/cs config to be used by default in ci/cd pipeline", "err", err)
+		return nil, err
+	}
+	return model, err
+}
+
+func (impl *GlobalCMCSRepositoryImpl) Delete(model *GlobalCMCS) error {
+	err := impl.dbConnection.Delete(model)
+	if err != nil {
+		impl.logger.Errorw("error in deleting global cm cs ", "err", err)
+		return err
+	}
+	return nil
+}
diff --git a/internal/sql/repository/app/AppRepository.go b/internal/sql/repository/app/AppRepository.go
index 3c33f0f00..d7ecf51f8 100644
--- a/internal/sql/repository/app/AppRepository.go
+++ b/internal/sql/repository/app/AppRepository.go
@@ -19,6 +19,7 @@ package app
 
 import (
 	"fmt"
+	"github.com/devtron-labs/devtron/internal/sql/repository/helper"
 	"github.com/devtron-labs/devtron/pkg/sql"
 	"github.com/devtron-labs/devtron/pkg/team"
 	"github.com/go-pg/pg"
@@ -26,13 +27,15 @@ import (
 )
 
 type App struct {
-	tableName       struct{} `sql:"app" pg:",discard_unknown_columns"`
-	Id              int      `sql:"id,pk"`
-	AppName         string   `sql:"app_name,notnull"` //same as app name
-	Active          bool     `sql:"active, notnull"`
-	TeamId          int      `sql:"team_id"`
-	AppStore        bool     `sql:"app_store, notnull"`
-	AppOfferingMode string   `sql:"app_offering_mode,notnull"`
+	tableName       struct{}       `sql:"app" pg:",discard_unknown_columns"`
+	Id              int            `sql:"id,pk"`
+	AppName         string         `sql:"app_name,notnull"` //same as app name
+	DisplayName     string         `sql:"display_name"`
+	Active          bool           `sql:"active, notnull"`
+	TeamId          int            `sql:"team_id"`
+	AppType         helper.AppType `sql:"app_type, notnull"`
+	AppOfferingMode string         `sql:"app_offering_mode,notnull"`
+	Description     string         `sql:"description"`
 	Team            team.Team
 	sql.AuditLog
 }
@@ -43,6 +46,7 @@ type AppRepository interface {
 	Update(app *App) error
 	UpdateWithTxn(app *App, tx *pg.Tx) error
 	FindActiveByName(appName string) (pipelineGroup *App, err error)
+	FindJobByDisplayName(appName string) (pipelineGroup *App, err error)
 	FindActiveListByName(appName string) ([]*App, error)
 	FindById(id int) (pipelineGroup *App, err error)
 	FindAppsByTeamId(teamId int) ([]*App, error)
@@ -58,12 +62,13 @@ type AppRepository interface {
 	FindAppAndProjectByAppId(appId int) (*App, error)
 	FindAppAndProjectByAppName(appName string) (*App, error)
 	GetConnection() *pg.DB
-	FindAllMatchesByAppName(appName string) ([]*App, error)
+	FindAllMatchesByAppName(appName string, appType helper.AppType) ([]*App, error)
 	FindIdsByTeamIdsAndTeamNames(teamIds []int, teamNames []string) ([]int, error)
 	FindIdsByNames(appNames []string) ([]int, error)
 	FetchAllActiveInstalledAppsWithAppIdAndName() ([]*App, error)
 	FetchAllActiveDevtronAppsWithAppIdAndName() ([]*App, error)
 	FindEnvironmentIdForInstalledApp(appId int) (int, error)
+	FetchAppIdsWithFilter(jobListingFilter helper.AppListingFilter) ([]int, error)
 }
 
 const DevtronApp = "DevtronApp"
@@ -117,6 +122,18 @@ func (repo AppRepositoryImpl) FindActiveByName(appName string) (*App, error) {
 	// there is only single active app will be present in db with a same name.
 	return pipelineGroup, err
 }
+func (repo AppRepositoryImpl) FindJobByDisplayName(appName string) (*App, error) {
+	pipelineGroup := &App{}
+	err := repo.dbConnection.
+		Model(pipelineGroup).
+		Where("display_name = ?", appName).
+		Where("active = ?", true).
+		Where("app_type = ?", helper.Job).
+		Order("id DESC").Limit(1).
+		Select()
+	// there is only single active app will be present in db with a same name.
+	return pipelineGroup, err
+}
 
 func (repo AppRepositoryImpl) FindActiveListByName(appName string) ([]*App, error) {
 	var apps []*App
@@ -142,7 +159,8 @@ func (repo AppRepositoryImpl) CheckAppExists(appNames []string) ([]*App, error)
 
 func (repo AppRepositoryImpl) FindById(id int) (*App, error) {
 	pipelineGroup := &App{}
-	err := repo.dbConnection.Model(pipelineGroup).Where("id = ?", id).Select()
+	err := repo.dbConnection.Model(pipelineGroup).Where("id = ?", id).
+		Where("active = ?", true).Select()
 	return pipelineGroup, err
 }
 
@@ -160,7 +178,7 @@ func (repo AppRepositoryImpl) FindAppsByTeamIds(teamId []int, appType string) ([
 	}
 	var apps []App
 	err := repo.dbConnection.Model(&apps).Column("app.*", "Team").Where("team_id in (?)", pg.In(teamId)).
-		Where("app.active=?", true).Where("app.app_store=?", onlyDevtronCharts).Select()
+		Where("app.active=?", true).Where("app.app_type=?", onlyDevtronCharts).Select()
 	return apps, err
 }
 
@@ -175,7 +193,7 @@ func (repo AppRepositoryImpl) FindAppsByTeamName(teamName string) ([]App, error)
 
 func (repo AppRepositoryImpl) FindAll() ([]*App, error) {
 	var apps []*App
-	err := repo.dbConnection.Model(&apps).Where("active = ?", true).Where("app_store = ?", false).Select()
+	err := repo.dbConnection.Model(&apps).Where("active = ?", true).Where("app_type = ?", 0).Select()
 	return apps, err
 }
 
@@ -190,7 +208,7 @@ func (repo AppRepositoryImpl) FindAppsByEnvironmentId(environmentId int) ([]App,
 func (repo AppRepositoryImpl) FindAllActiveAppsWithTeam() ([]*App, error) {
 	var apps []*App
 	err := repo.dbConnection.Model(&apps).Column("Team").
-		Where("app.active = ?", true).Where("app.app_store = ?", false).
+		Where("app.active = ?", true).Where("app.app_type = ?", 0).
 		Select()
 	return apps, err
 }
@@ -208,25 +226,25 @@ func (repo AppRepositoryImpl) FetchAppsByFilterV2(appNameIncludes string, appNam
 		err = repo.dbConnection.Model(&apps).ColumnExpr("DISTINCT app.*").
 			Join("inner join pipeline p on p.app_id=app.id").
 			Where("app.app_name like ?", ""+appNameIncludes+"%").Where("app.app_name not like ?", ""+appNameExcludes+"%").
-			Where("app.active=?", true).Where("app_store=?", false).
+			Where("app.active=?", true).Where("app_type=?", 0).
 			Where("p.environment_id = ?", environmentId).Where("p.deleted = ?", false).
 			Select()
 	} else if environmentId > 0 && appNameExcludes == "" {
 		err = repo.dbConnection.Model(&apps).ColumnExpr("DISTINCT app.*").
 			Join("inner join pipeline p on p.app_id=app.id").
 			Where("app.app_name like ?", ""+appNameIncludes+"%").
-			Where("app.active=?", true).Where("app_store=?", false).
+			Where("app.active=?", true).Where("app_type=?", 0).
 			Where("p.environment_id = ?", environmentId).Where("p.deleted = ?", false).
 			Select()
 	} else if environmentId == 0 && len(appNameExcludes) > 0 {
 		err = repo.dbConnection.Model(&apps).ColumnExpr("DISTINCT app.*").
 			Where("app.app_name like ?", ""+appNameIncludes+"%").Where("app.app_name not like ?", ""+appNameExcludes+"%").
-			Where("app.active=?", true).Where("app_store=?", false).
+			Where("app.active=?", true).Where("app_type=?", 0).
 			Select()
 	} else if environmentId == 0 && appNameExcludes == "" {
 		err = repo.dbConnection.Model(&apps).ColumnExpr("DISTINCT app.*").
 			Where("app.app_name like ?", ""+appNameIncludes+"%").
-			Where("app.active=?", true).Where("app_store=?", false).
+			Where("app.active=?", true).Where("app_type=?", 0).
 			Select()
 	}
 	return apps, err
@@ -250,9 +268,15 @@ func (repo AppRepositoryImpl) FindAppAndProjectByAppName(appName string) (*App,
 	return app, err
 }
 
-func (repo AppRepositoryImpl) FindAllMatchesByAppName(appName string) ([]*App, error) {
+func (repo AppRepositoryImpl) FindAllMatchesByAppName(appName string, appType helper.AppType) ([]*App, error) {
 	var apps []*App
-	err := repo.dbConnection.Model(&apps).Where("app_name ILIKE ?", "%"+appName+"%").Where("active = ?", true).Where("app_store = ?", false).Select()
+	var err error
+	if appType == helper.Job {
+		err = repo.dbConnection.Model(&apps).Where("display_name LIKE ?", "%"+appName+"%").Where("active = ?", true).Where("app_type = ?", appType).Select()
+	} else {
+		err = repo.dbConnection.Model(&apps).Where("app_name LIKE ?", "%"+appName+"%").Where("active = ?", true).Where("app_type = ?", appType).Select()
+	}
+
 	return apps, err
 }
 
@@ -314,7 +338,7 @@ func (repo AppRepositoryImpl) FetchAllActiveDevtronAppsWithAppIdAndName() ([]*Ap
 
 	err := repo.dbConnection.Model(&apps).
 		Column("id", "app_name").
-		Where("app_store = ?", false).
+		Where("app_type = ?", 0).
 		Where("active", true).
 		Select()
 	if err != nil && err != pg.ErrNoRows {
@@ -334,3 +358,29 @@ func (repo AppRepositoryImpl) FindEnvironmentIdForInstalledApp(appId int) (int,
 	_, err := repo.dbConnection.Query(&res, query, appId)
 	return res.envId, err
 }
+func (repo AppRepositoryImpl) FetchAppIdsWithFilter(jobListingFilter helper.AppListingFilter) ([]int, error) {
+	type AppId struct {
+		Id int `json:"id"`
+	}
+	var jobIds []AppId
+	whereCondition := " where active = true and app_type = 2 "
+	if len(jobListingFilter.Teams) > 0 {
+		whereCondition += " and team_id in (" + helper.GetCommaSepratedString(jobListingFilter.Teams) + ")"
+	}
+
+	if len(jobListingFilter.AppNameSearch) > 0 {
+		whereCondition += " and display_name like '%" + jobListingFilter.AppNameSearch + "%' "
+	}
+	orderByCondition := " order by display_name "
+	if jobListingFilter.SortOrder == "DESC" {
+		orderByCondition += string(jobListingFilter.SortOrder)
+	}
+	query := "select id " + "from app " + whereCondition + orderByCondition
+
+	_, err := repo.dbConnection.Query(&jobIds, query)
+	appCounts := make([]int, 0)
+	for _, id := range jobIds {
+		appCounts = append(appCounts, id.Id)
+	}
+	return appCounts, err
+}
diff --git a/internal/sql/repository/appStatus/AppStatusRepository.go b/internal/sql/repository/appStatus/AppStatusRepository.go
index 0a90f0da4..22f84f793 100644
--- a/internal/sql/repository/appStatus/AppStatusRepository.go
+++ b/internal/sql/repository/appStatus/AppStatusRepository.go
@@ -13,7 +13,7 @@ type AppStatusContainer struct {
 	InstalledAppId int       `json:"installed_app_id"`
 	EnvId          int       `json:"env_id"`
 	Status         string    `json:"status"`
-	AppStore       bool      `json:"app_store"`
+	AppType        int       `json:"app_type"`
 	UpdatedOn      time.Time `json:"updated_on"`
 }
 
diff --git a/internal/sql/repository/helper/AppListingRepositoryQueryBuilder.go b/internal/sql/repository/helper/AppListingRepositoryQueryBuilder.go
index 12293c059..b167f7956 100644
--- a/internal/sql/repository/helper/AppListingRepositoryQueryBuilder.go
+++ b/internal/sql/repository/helper/AppListingRepositoryQueryBuilder.go
@@ -25,6 +25,14 @@ import (
 	"strings"
 )
 
+type AppType int
+
+const (
+	CustomApp     AppType = 0 // cicd app
+	ChartStoreApp AppType = 1 // helm app
+	Job           AppType = 2 // jobs
+)
+
 type AppListingRepositoryQueryBuilder struct {
 	logger *zap.SugaredLogger
 }
@@ -60,6 +68,49 @@ const (
 	AppNameSortBy SortBy = "appNameSort"
 )
 
+func (impl AppListingRepositoryQueryBuilder) BuildJobListingQuery(appIDs []int, statuses []string, sortOrder string) string {
+	query := "select ci_pipeline.name as ci_pipeline_name,ci_pipeline.id as ci_pipeline_id,app.id as job_id,app.display_name " +
+		"as job_name,app.description,cwr.started_on,cwr.status from app left join ci_pipeline on" +
+		" app.id = ci_pipeline.app_id and ci_pipeline.active=true left join (select cw.ci_pipeline_id, cw.status, cw.started_on " +
+		"  from ci_workflow cw inner join (select ci_pipeline_id, MAX(started_on) max_started_on from ci_workflow group by ci_pipeline_id ) " +
+		"cws on cw.ci_pipeline_id = cws.ci_pipeline_id " +
+		"and cw.started_on = cws.max_started_on order by cw.ci_pipeline_id) cwr on cwr.ci_pipeline_id = ci_pipeline.id" +
+		" where app.active = true and app.app_type = 2 "
+	if len(appIDs) > 0 {
+		query += "and app.id IN (" + GetCommaSepratedString(appIDs) + ") "
+	}
+	if len(statuses) > 0 {
+		query += "and cwr.status IN (" + util.ProcessAppStatuses(statuses) + ") "
+	}
+	query += " order by app.display_name"
+	if sortOrder == "DESC" {
+		query += " DESC "
+	}
+	return query
+}
+func (impl AppListingRepositoryQueryBuilder) OverviewCiPipelineQuery() string {
+	query := "select ci_pipeline.id as ci_pipeline_id,ci_pipeline.name " +
+		"as ci_pipeline_name,cwr.status,cwr.started_on from ci_pipeline" +
+		" left join (select cw.ci_pipeline_id,cw.status,cw.started_on from ci_workflow cw" +
+		" inner join (SELECT  ci_pipeline_id, MAX(started_on) max_started_on FROM ci_workflow GROUP BY ci_pipeline_id)" +
+		" cws on cw.ci_pipeline_id = cws.ci_pipeline_id and cw.started_on = cws.max_started_on order by cw.ci_pipeline_id)" +
+		" cwr on cwr.ci_pipeline_id = ci_pipeline.id where ci_pipeline.active = true and ci_pipeline.app_id = ? ;"
+	return query
+}
+
+// use this query with atleast 1 cipipeline id
+func (impl AppListingRepositoryQueryBuilder) JobsLastSucceededOnTimeQuery(ciPipelineIDs []int) string {
+	// use this query with atleast 1 cipipeline id
+	query := "select cw.ci_pipeline_id,cw.finished_on " +
+		"as last_succeeded_on from ci_workflow cw inner join " +
+		"(SELECT  ci_pipeline_id, MAX(finished_on) finished_on " +
+		"FROM ci_workflow WHERE ci_workflow.status = 'Succeeded'" +
+		"GROUP BY ci_pipeline_id) cws on cw.ci_pipeline_id = cws.ci_pipeline_id and cw.finished_on = cws.finished_on " +
+		"where cw.ci_pipeline_id IN (" + GetCommaSepratedString(ciPipelineIDs) + "); "
+
+	return query
+}
+
 func (impl AppListingRepositoryQueryBuilder) BuildAppListingQuery(appListingFilter AppListingFilter) string {
 	whereCondition := impl.buildAppListingWhereCondition(appListingFilter)
 	orderByClause := impl.buildAppListingSortBy(appListingFilter)
@@ -93,8 +144,33 @@ func (impl AppListingRepositoryQueryBuilder) buildAppListingSortBy(appListingFil
 	return orderByCondition
 }
 
+func (impl AppListingRepositoryQueryBuilder) buildJobListingSortBy(appListingFilter AppListingFilter) string {
+	orderByCondition := " ORDER BY a.name"
+	return orderByCondition
+}
+
+func (impl AppListingRepositoryQueryBuilder) buildJobListingWhereCondition(jobListingFilter AppListingFilter) string {
+	whereCondition := "WHERE a.active = true and a.app_type = 2 "
+
+	if len(jobListingFilter.Teams) > 0 {
+		teamIds := strings.Trim(strings.Join(strings.Fields(fmt.Sprint(jobListingFilter.Teams)), ","), "[]")
+		whereCondition = whereCondition + "and a.team_id IN (" + teamIds + ") "
+	}
+
+	if jobListingFilter.AppNameSearch != "" {
+		likeClause := "'%" + jobListingFilter.AppNameSearch + "%'"
+		whereCondition = whereCondition + "and a.display_name like " + likeClause + " "
+	}
+	// add job stats filter here
+	if len(jobListingFilter.AppStatuses) > 0 {
+		appStatuses := util.ProcessAppStatuses(jobListingFilter.AppStatuses)
+		whereCondition = whereCondition + "and aps.status IN (" + appStatuses + ") "
+	}
+	return whereCondition
+}
+
 func (impl AppListingRepositoryQueryBuilder) buildAppListingWhereCondition(appListingFilter AppListingFilter) string {
-	whereCondition := "WHERE a.active = true and a.app_store is false "
+	whereCondition := "WHERE a.active = true and a.app_type = 0 "
 	if len(appListingFilter.Environments) > 0 {
 		envIds := strings.Trim(strings.Join(strings.Fields(fmt.Sprint(appListingFilter.Environments)), ","), "[]")
 		whereCondition = whereCondition + "and env.id IN (" + envIds + ") "
@@ -120,3 +196,13 @@ func (impl AppListingRepositoryQueryBuilder) buildAppListingWhereCondition(appLi
 	}
 	return whereCondition
 }
+func GetCommaSepratedString(appIds []int) string {
+	appIdsString := ""
+	for i, appId := range appIds {
+		appIdsString += fmt.Sprintf("%d", appId)
+		if i != len(appIds)-1 {
+			appIdsString += ","
+		}
+	}
+	return appIdsString
+}
diff --git a/internal/sql/repository/pipelineConfig/CiTemplateRepository.go b/internal/sql/repository/pipelineConfig/CiTemplateRepository.go
index 012512965..cc36ba47f 100644
--- a/internal/sql/repository/pipelineConfig/CiTemplateRepository.go
+++ b/internal/sql/repository/pipelineConfig/CiTemplateRepository.go
@@ -30,7 +30,7 @@ type CiTemplate struct {
 	tableName          struct{} `sql:"ci_template" pg:",discard_unknown_columns"`
 	Id                 int      `sql:"id"`
 	AppId              int      `sql:"app_id"`             //foreign key of app
-	DockerRegistryId   string   `sql:"docker_registry_id"` //foreign key of registry
+	DockerRegistryId   *string  `sql:"docker_registry_id"` //foreign key of registry
 	DockerRepository   string   `sql:"docker_repository"`
 	DockerfilePath     string   `sql:"dockerfile_path"`
 	Args               string   `sql:"args"` //json string format of map[string]string
diff --git a/internal/sql/repository/pipelineConfig/CiWorkflowRepository.go b/internal/sql/repository/pipelineConfig/CiWorkflowRepository.go
index a6a3df217..662964223 100644
--- a/internal/sql/repository/pipelineConfig/CiWorkflowRepository.go
+++ b/internal/sql/repository/pipelineConfig/CiWorkflowRepository.go
@@ -87,6 +87,7 @@ type WorkflowWithArtifact struct {
 	CiArtifactId       int               `json:"ci_artifact_d"`
 	BlobStorageEnabled bool              `json:"blobStorageEnabled"`
 	CiBuildType        string            `json:"ci_build_type"`
+	IsArtifactUploaded bool              `json:"is_artifact_uploaded"`
 }
 
 type GitCommit struct {
@@ -158,7 +159,7 @@ func (impl *CiWorkflowRepositoryImpl) FindByStatusesIn(activeStatuses []string)
 
 func (impl *CiWorkflowRepositoryImpl) FindByPipelineId(pipelineId int, offset int, limit int) ([]WorkflowWithArtifact, error) {
 	var wfs []WorkflowWithArtifact
-	queryTemp := "select cia.id as ci_artifact_id, cia.image, wf.*, u.email_id from ci_workflow wf left join users u on u.id = wf.triggered_by left join ci_artifact cia on wf.id = cia.ci_workflow_id where wf.ci_pipeline_id = ? order by wf.started_on desc offset ? limit ?;"
+	queryTemp := "select cia.id as ci_artifact_id, cia.image, cia.is_artifact_uploaded, wf.*, u.email_id from ci_workflow wf left join users u on u.id = wf.triggered_by left join ci_artifact cia on wf.id = cia.ci_workflow_id where wf.ci_pipeline_id = ? order by wf.started_on desc offset ? limit ?;"
 	_, err := impl.dbConnection.Query(&wfs, queryTemp, pipelineId, offset, limit)
 	if err != nil {
 		return nil, err
diff --git a/internal/sql/repository/pipelineConfig/PipelineRepository.go b/internal/sql/repository/pipelineConfig/PipelineRepository.go
index 3fde67434..bd0355229 100644
--- a/internal/sql/repository/pipelineConfig/PipelineRepository.go
+++ b/internal/sql/repository/pipelineConfig/PipelineRepository.go
@@ -97,7 +97,7 @@ type PipelineRepository interface {
 	FindNumberOfAppsWithCdPipeline(appIds []int) (count int, err error)
 	GetAppAndEnvDetailsForDeploymentAppTypePipeline(deploymentAppType string, clusterIds []int) ([]*Pipeline, error)
 	GetArgoPipelinesHavingTriggersStuckInLastPossibleNonTerminalTimelines(pendingSinceSeconds int, timeForDegradation int) ([]*Pipeline, error)
-	GetArgoPipelinesHavingLatestTriggerStuckInNonTerminalStatuses(deployedBeforeMinutes int) ([]*Pipeline, error)
+	GetArgoPipelinesHavingLatestTriggerStuckInNonTerminalStatuses(deployedBeforeMinutes int, getPipelineDeployedWithinHours int) ([]*Pipeline, error)
 	FindIdsByAppIdsAndEnvironmentIds(appIds, environmentIds []int) (ids []int, err error)
 	FindIdsByProjectIdsAndEnvironmentIds(projectIds, environmentIds []int) ([]int, error)
 
@@ -524,16 +524,16 @@ func (impl PipelineRepositoryImpl) GetArgoPipelinesHavingTriggersStuckInLastPoss
 	return pipelines, nil
 }
 
-func (impl PipelineRepositoryImpl) GetArgoPipelinesHavingLatestTriggerStuckInNonTerminalStatuses(deployedBeforeMinutes int) ([]*Pipeline, error) {
+func (impl PipelineRepositoryImpl) GetArgoPipelinesHavingLatestTriggerStuckInNonTerminalStatuses(getPipelineDeployedBeforeMinutes int, getPipelineDeployedWithinHours int) ([]*Pipeline, error) {
 	var pipelines []*Pipeline
 	queryString := `select p.* from pipeline p inner join cd_workflow cw on cw.pipeline_id = p.id  
     inner join cd_workflow_runner cwr on cwr.cd_workflow_id=cw.id  
     where cwr.id in (select id from cd_workflow_runner 
-                     	where started_on < NOW() - INTERVAL '? minutes' and status not in (?) 
+                     	where started_on < NOW() - INTERVAL '? minutes' and started_on > NOW() - INTERVAL '? hours' and status not in (?) 
                      	and workflow_type=? and cd_workflow_id in (select DISTINCT ON (pipeline_id) max(id) as id from cd_workflow
                      	  group by pipeline_id, id order by pipeline_id, id desc))
     and p.deployment_app_type=? and p.deleted=?;`
-	_, err := impl.dbConnection.Query(&pipelines, queryString, deployedBeforeMinutes,
+	_, err := impl.dbConnection.Query(&pipelines, queryString, getPipelineDeployedBeforeMinutes, getPipelineDeployedWithinHours,
 		pg.In([]string{WorkflowAborted, WorkflowFailed, WorkflowSucceeded, string(health.HealthStatusHealthy), string(health.HealthStatusDegraded)}),
 		bean.CD_WORKFLOW_TYPE_DEPLOY, util.PIPELINE_DEPLOYMENT_TYPE_ACD, false)
 	if err != nil {
diff --git a/internal/sql/repository/pipelineConfig/mocks/PipelineRepository.go b/internal/sql/repository/pipelineConfig/mocks/PipelineRepository.go
index af52498bc..533d3db4a 100644
--- a/internal/sql/repository/pipelineConfig/mocks/PipelineRepository.go
+++ b/internal/sql/repository/pipelineConfig/mocks/PipelineRepository.go
@@ -654,7 +654,7 @@ func (_m *PipelineRepository) GetArgoPipelineByArgoAppName(argoAppName string) (
 }
 
 // GetArgoPipelinesHavingLatestTriggerStuckInNonTerminalStatuses provides a mock function with given fields: deployedBeforeMinutes
-func (_m *PipelineRepository) GetArgoPipelinesHavingLatestTriggerStuckInNonTerminalStatuses(deployedBeforeMinutes int) ([]*pipelineConfig.Pipeline, error) {
+func (_m *PipelineRepository) GetArgoPipelinesHavingLatestTriggerStuckInNonTerminalStatuses(deployedBeforeMinutes int, pipelineStatusCheckDeployedSince int) ([]*pipelineConfig.Pipeline, error) {
 	ret := _m.Called(deployedBeforeMinutes)
 
 	var r0 []*pipelineConfig.Pipeline
diff --git a/internal/sql/repository/security/CveStoreRepository.go b/internal/sql/repository/security/CveStoreRepository.go
index 333e95924..e99034660 100644
--- a/internal/sql/repository/security/CveStoreRepository.go
+++ b/internal/sql/repository/security/CveStoreRepository.go
@@ -117,7 +117,7 @@ func (impl CveStoreRepositoryImpl) Update(team *CveStore) error {
 func (impl CveStoreRepositoryImpl) VulnerabilityExposure(request *VulnerabilityRequest) ([]*VulnerabilityExposure, error) {
 	var items []*VulnerabilityExposure
 
-	query := "SELECT a.id as app_id, a.app_name, a.app_store, p.environment_id as pipeline_env_id, ia.environment_id  as chart_env_id " +
+	query := "SELECT a.id as app_id, a.app_name, a.app_type, p.environment_id as pipeline_env_id, ia.environment_id  as chart_env_id " +
 		" FROM app a" +
 		" LEFT JOIN pipeline p ON p.app_id=a.id" +
 		" LEFT JOIN installed_apps ia ON ia.app_id=a.id" +
diff --git a/pkg/app/AppCrudOperationService.go b/pkg/app/AppCrudOperationService.go
index e07aa4bde..4b7bddc69 100644
--- a/pkg/app/AppCrudOperationService.go
+++ b/pkg/app/AppCrudOperationService.go
@@ -20,7 +20,8 @@ package app
 import (
 	"encoding/json"
 	"fmt"
-	"github.com/devtron-labs/devtron/internal/sql/repository/app"
+	appRepository "github.com/devtron-labs/devtron/internal/sql/repository/app"
+	"github.com/devtron-labs/devtron/internal/sql/repository/helper"
 	"github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig"
 	repository2 "github.com/devtron-labs/devtron/pkg/appStore/deployment/repository"
 	"github.com/devtron-labs/devtron/pkg/bean"
@@ -49,13 +50,13 @@ type AppCrudOperationService interface {
 type AppCrudOperationServiceImpl struct {
 	logger                 *zap.SugaredLogger
 	appLabelRepository     pipelineConfig.AppLabelRepository
-	appRepository          app.AppRepository
+	appRepository          appRepository.AppRepository
 	userRepository         repository.UserRepository
 	installedAppRepository repository2.InstalledAppRepository
 }
 
 func NewAppCrudOperationServiceImpl(appLabelRepository pipelineConfig.AppLabelRepository,
-	logger *zap.SugaredLogger, appRepository app.AppRepository, userRepository repository.UserRepository, installedAppRepository repository2.InstalledAppRepository) *AppCrudOperationServiceImpl {
+	logger *zap.SugaredLogger, appRepository appRepository.AppRepository, userRepository repository.UserRepository, installedAppRepository repository2.InstalledAppRepository) *AppCrudOperationServiceImpl {
 	return &AppCrudOperationServiceImpl{
 		appLabelRepository:     appLabelRepository,
 		logger:                 logger,
@@ -104,6 +105,7 @@ func (impl AppCrudOperationServiceImpl) UpdateApp(request *bean.CreateAppDTO) (*
 		impl.logger.Errorw("error in fetching app", "error", err)
 		return nil, err
 	}
+	app.Description = request.Description
 	app.TeamId = request.TeamId
 	app.UpdatedOn = time.Now()
 	app.UpdatedBy = request.UserId
@@ -313,15 +315,20 @@ func (impl AppCrudOperationServiceImpl) GetAppMetaInfo(appId int) (*bean.AppMeta
 			userEmailId = fmt.Sprintf("%s (inactive)", user.EmailId)
 		}
 	}
+	appName := app.AppName
+	if app.AppType == helper.Job {
+		appName = app.DisplayName
+	}
 	info := &bean.AppMetaInfoDto{
 		AppId:       app.Id,
-		AppName:     app.AppName,
+		AppName:     appName,
 		ProjectId:   app.TeamId,
 		ProjectName: app.Team.Name,
 		CreatedBy:   userEmailId,
 		CreatedOn:   app.CreatedOn,
 		Labels:      labels,
 		Active:      app.Active,
+		Description: app.Description,
 	}
 	return info, nil
 }
@@ -331,7 +338,7 @@ func (impl AppCrudOperationServiceImpl) GetHelmAppMetaInfo(appId string) (*bean.
 	// adding separate function for helm apps because for CLI helm apps, apps can be of form "1|clusterName|releaseName"
 	// In this case app details can be fetched using app name / release Name.
 	appIdSplitted := strings.Split(appId, "|")
-	app := &app.App{}
+	app := &appRepository.App{}
 	var err error
 	impl.logger.Info("request payload, appId", appId)
 	if len(appIdSplitted) > 1 {
diff --git a/pkg/app/AppListingService.go b/pkg/app/AppListingService.go
index 00bfbdff7..e8750434b 100644
--- a/pkg/app/AppListingService.go
+++ b/pkg/app/AppListingService.go
@@ -53,6 +53,8 @@ import (
 
 type AppListingService interface {
 	FetchAppsByEnvironment(fetchAppListingRequest FetchAppListingRequest, w http.ResponseWriter, r *http.Request, token string) ([]*bean.AppEnvironmentContainer, error)
+	FetchJobs(fetchJobListingRequest FetchAppListingRequest) ([]*bean.JobContainer, error)
+	FetchOverviewCiPipelines(jobId int) ([]*bean.JobListingContainer, error)
 	BuildAppListingResponse(fetchAppListingRequest FetchAppListingRequest, envContainers []*bean.AppEnvironmentContainer) ([]*bean.AppContainer, error)
 	FetchAllDevtronManagedApps() ([]AppNameTypeIdContainer, error)
 	FetchAppDetails(ctx context.Context, appId int, envId int) (bean.AppDetailContainer, error)
@@ -78,7 +80,7 @@ type AppListingService interface {
 	GraphAPI(appId int, envId int) error
 
 	FetchAppTriggerView(appId int) ([]bean.TriggerView, error)
-	FetchAppStageStatus(appId int) ([]bean.AppStageStatus, error)
+	FetchAppStageStatus(appId int, appType int) ([]bean.AppStageStatus, error)
 
 	FetchOtherEnvironment(ctx context.Context, appId int) ([]*bean.Environment, error)
 	RedirectToLinkouts(Id int, appId int, envId int, podName string, containerName string) (string, error)
@@ -220,6 +222,42 @@ func (impl AppListingServiceImpl) FetchAllDevtronManagedApps() ([]AppNameTypeIdC
 	}
 	return apps, nil
 }
+func (impl AppListingServiceImpl) FetchJobs(fetchJobListingRequest FetchAppListingRequest) ([]*bean.JobContainer, error) {
+
+	jobListingFilter := helper.AppListingFilter{
+		Teams:         fetchJobListingRequest.Teams,
+		AppNameSearch: fetchJobListingRequest.AppNameSearch,
+		SortOrder:     fetchJobListingRequest.SortOrder,
+		SortBy:        fetchJobListingRequest.SortBy,
+		Offset:        fetchJobListingRequest.Offset,
+		Size:          fetchJobListingRequest.Size,
+		AppStatuses:   fetchJobListingRequest.AppStatuses,
+	}
+	appIds, err := impl.appRepository.FetchAppIdsWithFilter(jobListingFilter)
+	if err != nil {
+		impl.Logger.Errorw("error in fetching app ids list", "error", err, jobListingFilter)
+		return []*bean.JobContainer{}, err
+	}
+	jobListingContainers, err := impl.appListingRepository.FetchJobs(appIds, jobListingFilter.AppStatuses, string(jobListingFilter.SortOrder))
+	if err != nil {
+		impl.Logger.Errorw("error in fetching job list", "error", err, jobListingFilter)
+		return []*bean.JobContainer{}, err
+	}
+	CiPipelineIDs := GetCIPipelineIDs(jobListingContainers)
+	JobsLastSucceededOnTime, err := impl.appListingRepository.FetchJobsLastSucceededOn(CiPipelineIDs)
+	jobContainers := BuildJobListingResponse(jobListingContainers, JobsLastSucceededOnTime)
+	return jobContainers, nil
+}
+
+func (impl AppListingServiceImpl) FetchOverviewCiPipelines(jobId int) ([]*bean.JobListingContainer, error) {
+	jobCiContainers, err := impl.appListingRepository.FetchOverviewCiPipelines(jobId)
+	if err != nil {
+		impl.Logger.Errorw("error in fetching job container", "error", err, jobId)
+		return []*bean.JobListingContainer{}, err
+	}
+	return jobCiContainers, nil
+}
+
 func (impl AppListingServiceImpl) FetchAppsByEnvironment(fetchAppListingRequest FetchAppListingRequest, w http.ResponseWriter, r *http.Request, token string) ([]*bean.AppEnvironmentContainer, error) {
 	impl.Logger.Debug("reached at FetchAppsByEnvironment:")
 	// TODO: check statuses
@@ -336,6 +374,64 @@ func (impl AppListingServiceImpl) BuildAppListingResponse(fetchAppListingRequest
 	appContainerResponses, err := impl.appListingViewBuilder.BuildView(fetchAppListingRequest, appEnvMapping)
 	return appContainerResponses, err
 }
+func GetCIPipelineIDs(jobContainers []*bean.JobListingContainer) []int {
+
+	var ciPipelineIDs []int
+	for _, jobContainer := range jobContainers {
+		ciPipelineIDs = append(ciPipelineIDs, jobContainer.CiPipelineID)
+	}
+	return ciPipelineIDs
+}
+func BuildJobListingResponse(jobContainers []*bean.JobListingContainer, JobsLastSucceededOnTime []*bean.CiPipelineLastSucceededTime) []*bean.JobContainer {
+	jobContainersMapping := make(map[int]bean.JobContainer)
+	var appIds []int
+
+	lastSucceededTimeMapping := make(map[int]time.Time)
+	for _, lastSuccessTime := range JobsLastSucceededOnTime {
+		lastSucceededTimeMapping[lastSuccessTime.CiPipelineID] = lastSuccessTime.LastSucceededOn
+	}
+
+	//Storing the sequence in appIds array
+	for _, jobContainer := range jobContainers {
+		val, ok := jobContainersMapping[jobContainer.JobId]
+		if !ok {
+			appIds = append(appIds, jobContainer.JobId)
+			val = bean.JobContainer{}
+			val.JobId = jobContainer.JobId
+			val.JobName = jobContainer.JobName
+			val.Description = jobContainer.Description
+		}
+
+		if len(val.JobCiPipelines) == 0 {
+			val.JobCiPipelines = make([]bean.JobCIPipeline, 0)
+		}
+
+		if jobContainer.CiPipelineID != 0 {
+			ciPipelineObj := bean.JobCIPipeline{
+				CiPipelineId:   jobContainer.CiPipelineID,
+				CiPipelineName: jobContainer.CiPipelineName,
+				Status:         jobContainer.Status,
+				LastRunAt:      jobContainer.StartedOn,
+				//LastSuccessAt: jobContainer.LastSuccessAt,
+			}
+			if lastSuccessAt, ok := lastSucceededTimeMapping[jobContainer.CiPipelineID]; ok {
+				ciPipelineObj.LastSuccessAt = lastSuccessAt
+			}
+
+			val.JobCiPipelines = append(val.JobCiPipelines, ciPipelineObj)
+		}
+		jobContainersMapping[jobContainer.JobId] = val
+
+	}
+
+	result := make([]*bean.JobContainer, 0)
+	for _, appId := range appIds {
+		val := jobContainersMapping[appId]
+		result = append(result, &val)
+	}
+
+	return result
+}
 
 func (impl AppListingServiceImpl) fetchACDAppStatus(fetchAppListingRequest FetchAppListingRequest, existingAppEnvContainers []*bean.AppEnvironmentContainer) (map[string][]*bean.AppEnvironmentContainer, error) {
 	appEnvMapping := make(map[string][]*bean.AppEnvironmentContainer)
@@ -672,16 +768,16 @@ func (impl AppListingServiceImpl) setIpAccessProvidedData(ctx context.Context, a
 			return bean.AppDetailContainer{}, err
 		}
 
-		if ciPipeline != nil && ciPipeline.CiTemplate != nil && len(ciPipeline.CiTemplate.DockerRegistryId) > 0 {
+		if ciPipeline != nil && ciPipeline.CiTemplate != nil && len(*ciPipeline.CiTemplate.DockerRegistryId) > 0 {
 			dockerRegistryId := ciPipeline.CiTemplate.DockerRegistryId
-			appDetailContainer.DockerRegistryId = dockerRegistryId
+			appDetailContainer.DockerRegistryId = *dockerRegistryId
 			if !ciPipeline.IsExternal || ciPipeline.ParentCiPipeline != 0 {
 				appDetailContainer.IsExternalCi = false
 			}
 
 			_, span = otel.Tracer("orchestrator").Start(ctx, "dockerRegistryIpsConfigService.IsImagePullSecretAccessProvided")
 			// check ips access provided to this docker registry for that cluster
-			ipsAccessProvided, err := impl.dockerRegistryIpsConfigService.IsImagePullSecretAccessProvided(dockerRegistryId, clusterId)
+			ipsAccessProvided, err := impl.dockerRegistryIpsConfigService.IsImagePullSecretAccessProvided(*dockerRegistryId, clusterId)
 			span.End()
 			if err != nil {
 				impl.Logger.Errorw("error in checking if docker registry ips access provided", "dockerRegistryId", dockerRegistryId, "clusterId", clusterId, "error", err)
@@ -1436,8 +1532,9 @@ func (impl AppListingServiceImpl) FetchAppTriggerView(appId int) ([]bean.Trigger
 	return impl.appListingRepository.FetchAppTriggerView(appId)
 }
 
-func (impl AppListingServiceImpl) FetchAppStageStatus(appId int) ([]bean.AppStageStatus, error) {
-	return impl.appListingRepository.FetchAppStageStatus(appId)
+func (impl AppListingServiceImpl) FetchAppStageStatus(appId int, appType int) ([]bean.AppStageStatus, error) {
+	appStageStatuses, err := impl.appListingRepository.FetchAppStageStatus(appId, appType)
+	return appStageStatuses, err
 }
 
 func (impl AppListingServiceImpl) FetchOtherEnvironment(ctx context.Context, appId int) ([]*bean.Environment, error) {
diff --git a/pkg/app/AppService.go b/pkg/app/AppService.go
index 64ab6e21a..7b1f92bd4 100644
--- a/pkg/app/AppService.go
+++ b/pkg/app/AppService.go
@@ -87,9 +87,10 @@ import (
 type AppServiceConfig struct {
 	CdPipelineStatusCronTime            string `env:"CD_PIPELINE_STATUS_CRON_TIME" envDefault:"*/2 * * * *"`
 	CdHelmPipelineStatusCronTime        string `env:"CD_HELM_PIPELINE_STATUS_CRON_TIME" envDefault:"*/2 * * * *"`
-	CdPipelineStatusTimeoutDuration     string `env:"CD_PIPELINE_STATUS_TIMEOUT_DURATION" envDefault:"20"`       //in minutes
-	PipelineDegradedTime                string `env:"PIPELINE_DEGRADED_TIME" envDefault:"10"`                    //in minutes
-	HelmPipelineStatusCheckEligibleTime string `env:"HELM_PIPELINE_STATUS_CHECK_ELIGIBLE_TIME" envDefault:"120"` //in seconds
+	CdPipelineStatusTimeoutDuration     string `env:"CD_PIPELINE_STATUS_TIMEOUT_DURATION" envDefault:"20"`                   //in minutes
+	PipelineDegradedTime                string `env:"PIPELINE_DEGRADED_TIME" envDefault:"10"`                                //in minutes
+	GetPipelineDeployedWithinHours      int    `env:"DEPLOY_STATUS_CRON_GET_PIPELINE_DEPLOYED_WITHIN_HOURS" envDefault:"12"` //in hours
+	HelmPipelineStatusCheckEligibleTime string `env:"HELM_PIPELINE_STATUS_CHECK_ELIGIBLE_TIME" envDefault:"120"`             //in seconds
 	ExposeCDMetrics                     bool   `env:"EXPOSE_CD_METRICS" envDefault:"false"`
 }
 
@@ -419,8 +420,9 @@ func (impl *AppServiceImpl) UpdateDeploymentStatusForGitOpsCdPipelines(app *v1al
 	if app != nil {
 		reconciledAt = app.Status.ReconciledAt
 	}
+	var kubectlSyncedTimeline *pipelineConfig.PipelineStatusTimeline
 	//updating cd pipeline status timeline
-	isTimelineUpdated, isTimelineTimedOut, err = impl.UpdatePipelineStatusTimelineForApplicationChanges(app, cdWfr.Id, statusTime, cdWfr.StartedOn, timeoutDuration, latestTimelineBeforeThisEvent, reconciledAt)
+	isTimelineUpdated, isTimelineTimedOut, kubectlSyncedTimeline, err = impl.UpdatePipelineStatusTimelineForApplicationChanges(app, cdWfr.Id, statusTime, cdWfr.StartedOn, timeoutDuration, latestTimelineBeforeThisEvent, reconciledAt)
 	if err != nil {
 		impl.logger.Errorw("error in updating pipeline status timeline", "err", err)
 	}
@@ -433,11 +435,6 @@ func (impl *AppServiceImpl) UpdateDeploymentStatusForGitOpsCdPipelines(app *v1al
 		}
 		return isSucceeded, isTimelineUpdated, nil
 	}
-	kubectlSyncedTimeline, err := impl.pipelineStatusTimelineRepository.FetchTimelineByWfrIdAndStatus(cdWfr.Id, pipelineConfig.TIMELINE_STATUS_KUBECTL_APPLY_SYNCED)
-	if err != nil && err != pg.ErrNoRows {
-		impl.logger.Errorw("error in getting latest timeline", "err", err, "cdWfrId", cdWfr.Id)
-		return isSucceeded, isTimelineUpdated, err
-	}
 	if reconciledAt.IsZero() || (kubectlSyncedTimeline != nil && kubectlSyncedTimeline.Id > 0 && reconciledAt.After(kubectlSyncedTimeline.StatusTime)) {
 		releaseCounter, err := impl.pipelineOverrideRepository.GetCurrentPipelineReleaseCounter(pipelineOverride.PipelineId)
 		if err != nil {
@@ -520,18 +517,21 @@ func (impl *AppServiceImpl) UpdateDeploymentStatusForPipeline(app *v1alpha1.Appl
 	return isSucceeded, nil
 }
 
-func (impl *AppServiceImpl) UpdatePipelineStatusTimelineForApplicationChanges(app *v1alpha1.Application, cdWfrId int, statusTime time.Time, triggeredAt time.Time, statusTimeoutDuration int, latestTimelineBeforeUpdate *pipelineConfig.PipelineStatusTimeline, reconciledAt *metav1.Time) (bool, bool, error) {
+func (impl *AppServiceImpl) UpdatePipelineStatusTimelineForApplicationChanges(app *v1alpha1.Application, cdWfrId int,
+	statusTime time.Time, triggeredAt time.Time, statusTimeoutDuration int,
+	latestTimelineBeforeUpdate *pipelineConfig.PipelineStatusTimeline, reconciledAt *metav1.Time) (isTimelineUpdated bool,
+	isTimelineTimedOut bool, kubectlApplySyncedTimeline *pipelineConfig.PipelineStatusTimeline, err error) {
 	impl.logger.Debugw("updating pipeline status timeline", "app", app, "pipelineOverride", cdWfrId, "APP_TO_UPDATE", app.Name)
-	isTimelineUpdated := false
-	isTimelineTimedOut := false
+	isTimelineUpdated = false
+	isTimelineTimedOut = false
 	terminalStatusExists, err := impl.pipelineStatusTimelineRepository.CheckIfTerminalStatusTimelinePresentByWfrId(cdWfrId)
 	if err != nil {
 		impl.logger.Errorw("error in checking if terminal status timeline exists by wfrId", "err", err, "wfrId", cdWfrId)
-		return isTimelineUpdated, isTimelineTimedOut, err
+		return isTimelineUpdated, isTimelineTimedOut, kubectlApplySyncedTimeline, err
 	}
 	if terminalStatusExists {
 		impl.logger.Infow("terminal status timeline exists for cdWfr, skipping more timeline changes", "wfrId", cdWfrId)
-		return isTimelineUpdated, isTimelineTimedOut, nil
+		return isTimelineUpdated, isTimelineTimedOut, kubectlApplySyncedTimeline, nil
 	}
 	err = impl.pipelineStatusSyncDetailService.SaveOrUpdateSyncDetail(cdWfrId, 1)
 	if err != nil {
@@ -556,24 +556,31 @@ func (impl *AppServiceImpl) UpdatePipelineStatusTimelineForApplicationChanges(ap
 	_, err, isTimelineUpdated = impl.SavePipelineStatusTimelineIfNotAlreadyPresent(cdWfrId, timeline.Status, timeline)
 	if err != nil {
 		impl.logger.Errorw("error in saving pipeline status timeline", "err", err)
-		return isTimelineUpdated, isTimelineTimedOut, err
+		return isTimelineUpdated, isTimelineTimedOut, kubectlApplySyncedTimeline, err
 	}
 	//saving timeline resource details
 	err = impl.pipelineStatusTimelineResourcesService.SaveOrUpdateCdPipelineTimelineResources(cdWfrId, app, nil, 1)
 	if err != nil {
 		impl.logger.Errorw("error in saving/updating timeline resources", "err", err, "cdWfrId", cdWfrId)
 	}
-	var kubectlApplySyncedTimeline *pipelineConfig.PipelineStatusTimeline
-	if app != nil && app.Status.OperationState != nil && app.Status.OperationState.Phase == common.OperationSucceeded {
+	var kubectlSyncTimelineFetchErr error
+	kubectlApplySyncedTimeline, kubectlSyncTimelineFetchErr = impl.pipelineStatusTimelineRepository.FetchTimelineByWfrIdAndStatus(cdWfrId, pipelineConfig.TIMELINE_STATUS_KUBECTL_APPLY_SYNCED)
+	if kubectlSyncTimelineFetchErr != nil && kubectlSyncTimelineFetchErr != pg.ErrNoRows {
+		impl.logger.Errorw("error in getting latest timeline", "err", kubectlSyncTimelineFetchErr, "cdWfrId", cdWfrId)
+		return isTimelineUpdated, isTimelineTimedOut, kubectlApplySyncedTimeline, kubectlSyncTimelineFetchErr
+	}
+	if (kubectlApplySyncedTimeline == nil || kubectlApplySyncedTimeline.Id == 0) && app != nil && app.Status.OperationState != nil && app.Status.OperationState.Phase == common.OperationSucceeded {
 		timeline.Id = 0
 		timeline.Status = pipelineConfig.TIMELINE_STATUS_KUBECTL_APPLY_SYNCED
 		timeline.StatusDetail = app.Status.OperationState.Message
 		//checking and saving if this timeline is present or not because kubewatch may stream same objects multiple times
-		kubectlApplySyncedTimeline, err, isTimelineUpdated = impl.SavePipelineStatusTimelineIfNotAlreadyPresent(cdWfrId, timeline.Status, timeline)
+		err = impl.pipelineStatusTimelineService.SaveTimeline(timeline, nil)
 		if err != nil {
 			impl.logger.Errorw("error in saving pipeline status timeline", "err", err)
-			return isTimelineUpdated, isTimelineTimedOut, err
+			return isTimelineUpdated, isTimelineTimedOut, kubectlApplySyncedTimeline, err
 		}
+		isTimelineUpdated = true
+		kubectlApplySyncedTimeline = timeline
 		impl.logger.Debugw("APP_STATUS_UPDATE_REQ", "stage", "APPLY_SYNCED", "app", app, "status", timeline.Status)
 	}
 	if reconciledAt.IsZero() || (kubectlApplySyncedTimeline != nil && kubectlApplySyncedTimeline.Id > 0 && reconciledAt.After(kubectlApplySyncedTimeline.StatusTime)) {
@@ -590,7 +597,7 @@ func (impl *AppServiceImpl) UpdatePipelineStatusTimelineForApplicationChanges(ap
 			err = impl.pipelineStatusTimelineService.SaveTimeline(timeline, nil)
 			if err != nil {
 				impl.logger.Errorw("error in creating timeline status", "err", err, "timeline", timeline)
-				return isTimelineUpdated, isTimelineTimedOut, err
+				return isTimelineUpdated, isTimelineTimedOut, kubectlApplySyncedTimeline, err
 			}
 			isTimelineUpdated = true
 			impl.logger.Debugw("APP_STATUS_UPDATE_REQ", "stage", "terminal_status", "app", app, "status", timeline.Status)
@@ -612,14 +619,14 @@ func (impl *AppServiceImpl) UpdatePipelineStatusTimelineForApplicationChanges(ap
 			_, err, isTimelineUpdated = impl.SavePipelineStatusTimelineIfNotAlreadyPresent(cdWfrId, timeline.Status, timeline)
 			if err != nil {
 				impl.logger.Errorw("error in saving pipeline status timeline", "err", err)
-				return isTimelineUpdated, isTimelineTimedOut, err
+				return isTimelineUpdated, isTimelineTimedOut, kubectlApplySyncedTimeline, err
 			}
 			isTimelineTimedOut = true
 		} else {
 			// deployment status will be in progress so leave timeline
 		}
 	}
-	return isTimelineUpdated, isTimelineTimedOut, nil
+	return isTimelineUpdated, isTimelineTimedOut, kubectlApplySyncedTimeline, nil
 }
 
 func (impl *AppServiceImpl) SavePipelineStatusTimelineIfNotAlreadyPresent(cdWfrId int, timelineStatus pipelineConfig.TimelineStatus, timeline *pipelineConfig.PipelineStatusTimeline) (latestTimeline *pipelineConfig.PipelineStatusTimeline, err error, isTimelineUpdated bool) {
@@ -1592,6 +1599,18 @@ func (impl *AppServiceImpl) getReleaseOverride(envOverride *chartConfig.EnvConfi
 	artifactImage := artifact.Image
 	imageTag := strings.Split(artifactImage, ":")
 
+	imageTagLen := len(imageTag)
+
+	imageName := ""
+
+	for i := 0; i < imageTagLen-1; i++ {
+		if i != imageTagLen-2 {
+			imageName = imageName + imageTag[i] + ":"
+		} else {
+			imageName = imageName + imageTag[i]
+		}
+	}
+
 	appId := strconv.Itoa(pipeline.App.Id)
 	envId := strconv.Itoa(pipeline.EnvironmentId)
 
@@ -1600,8 +1619,8 @@ func (impl *AppServiceImpl) getReleaseOverride(envOverride *chartConfig.EnvConfi
 		deploymentStrategy = string(strategy.Strategy)
 	}
 	releaseAttribute := ReleaseAttributes{
-		Name:           imageTag[0],
-		Tag:            imageTag[1],
+		Name:           imageName,
+		Tag:            imageTag[imageTagLen-1],
 		PipelineName:   pipeline.Name,
 		ReleaseVersion: strconv.Itoa(pipelineOverride.PipelineReleaseCounter),
 		DeploymentType: deploymentStrategy,
diff --git a/pkg/appClone/AppCloneService.go b/pkg/appClone/AppCloneService.go
index 449ead356..bde508f85 100644
--- a/pkg/appClone/AppCloneService.go
+++ b/pkg/appClone/AppCloneService.go
@@ -20,7 +20,12 @@ package appClone
 import (
 	"context"
 	bean2 "github.com/devtron-labs/devtron/api/bean"
+	"github.com/devtron-labs/devtron/internal/constants"
+	app2 "github.com/devtron-labs/devtron/internal/sql/repository/app"
+	"github.com/devtron-labs/devtron/internal/sql/repository/helper"
+	"github.com/devtron-labs/devtron/internal/util"
 	"github.com/devtron-labs/devtron/pkg/chart"
+	"github.com/go-pg/pg"
 	"strings"
 
 	"fmt"
@@ -47,6 +52,7 @@ type AppCloneServiceImpl struct {
 	propertiesConfigService pipeline.PropertiesConfigService
 	pipelineStageService    pipeline.PipelineStageService
 	ciTemplateService       pipeline.CiTemplateService
+	appRepository           app2.AppRepository
 }
 
 func NewAppCloneServiceImpl(logger *zap.SugaredLogger,
@@ -58,7 +64,8 @@ func NewAppCloneServiceImpl(logger *zap.SugaredLogger,
 	appListingService app.AppListingService,
 	propertiesConfigService pipeline.PropertiesConfigService,
 	ciTemplateOverrideRepository pipelineConfig.CiTemplateOverrideRepository,
-	pipelineStageService pipeline.PipelineStageService, ciTemplateService pipeline.CiTemplateService) *AppCloneServiceImpl {
+	pipelineStageService pipeline.PipelineStageService, ciTemplateService pipeline.CiTemplateService,
+	appRepository app2.AppRepository) *AppCloneServiceImpl {
 	return &AppCloneServiceImpl{
 		logger:                  logger,
 		pipelineBuilder:         pipelineBuilder,
@@ -70,26 +77,48 @@ func NewAppCloneServiceImpl(logger *zap.SugaredLogger,
 		propertiesConfigService: propertiesConfigService,
 		pipelineStageService:    pipelineStageService,
 		ciTemplateService:       ciTemplateService,
+		appRepository:           appRepository,
 	}
 }
 
 type CloneRequest struct {
-	RefAppId  int           `json:"refAppId"`
-	Name      string        `json:"name"`
-	ProjectId int           `json:"projectId"`
-	AppLabels []*bean.Label `json:"labels,omitempty" validate:"dive"`
+	RefAppId    int            `json:"refAppId"`
+	Name        string         `json:"name"`
+	ProjectId   int            `json:"projectId"`
+	AppLabels   []*bean.Label  `json:"labels,omitempty" validate:"dive"`
+	Description string         `json:"description"`
+	AppType     helper.AppType `json:"appType"`
 }
 
 func (impl *AppCloneServiceImpl) CloneApp(createReq *bean.CreateAppDTO, context context.Context) (*bean.CreateAppDTO, error) {
+	//validate template app
+	templateApp, err := impl.appRepository.FindById(createReq.TemplateId)
+	if err != nil && err != pg.ErrNoRows {
+		return nil, err
+	}
+	//If the template does not exist then don't clone
+	//If the template app-type is chart-store app then don't clone
+	//If the template app-type and create request app-type is not same then don't clone
+	if (templateApp == nil && templateApp.Id == 0) || (templateApp.AppType == helper.ChartStoreApp) || (templateApp.AppType != createReq.AppType) {
+		impl.logger.Warnw("template app does not exist", "id", createReq.TemplateId)
+		err = &util.ApiError{
+			Code:            constants.AppDoesNotExist.Code,
+			InternalMessage: "app does not exist",
+			UserMessage:     constants.AppAlreadyExists.UserMessage(createReq.TemplateId),
+		}
+		return nil, err
+	}
 	//create new app
 	cloneReq := &CloneRequest{
-		RefAppId:  createReq.TemplateId,
-		Name:      createReq.AppName,
-		ProjectId: createReq.TeamId,
-		AppLabels: createReq.AppLabels,
+		RefAppId:    createReq.TemplateId,
+		Name:        createReq.AppName,
+		ProjectId:   createReq.TeamId,
+		AppLabels:   createReq.AppLabels,
+		AppType:     createReq.AppType,
+		Description: createReq.Description,
 	}
 	userId := createReq.UserId
-	appStatus, err := impl.appListingService.FetchAppStageStatus(cloneReq.RefAppId)
+	appStatus, err := impl.appListingService.FetchAppStageStatus(cloneReq.RefAppId, int(cloneReq.AppType))
 	if err != nil {
 		return nil, err
 	}
@@ -97,7 +126,7 @@ func (impl *AppCloneServiceImpl) CloneApp(createReq *bean.CreateAppDTO, context
 	if err != nil {
 		return nil, err
 	}
-	isSmaeProject := refApp.TeamId == cloneReq.ProjectId
+	isSameProject := refApp.TeamId == cloneReq.ProjectId
 	/*	appStageStatus = append(appStageStatus, impl.makeAppStageStatus(0, "APP", stages.AppId))
 		appStageStatus = append(appStageStatus, impl.makeAppStageStatus(1, "MATERIAL", materialExists))
 		appStageStatus = append(appStageStatus, impl.makeAppStageStatus(2, "TEMPLATE", stages.CiTemplateId))
@@ -111,9 +140,11 @@ func (impl *AppCloneServiceImpl) CloneApp(createReq *bean.CreateAppDTO, context
 	}
 
 	//TODO check stage of current app
-	if !refAppStatus["APP"] {
-		impl.logger.Warnw("status not", "APP", cloneReq.RefAppId)
-		return nil, nil
+	if createReq.AppType != helper.Job {
+		if !refAppStatus["APP"] {
+			impl.logger.Warnw("status not", "APP", cloneReq.RefAppId)
+			return nil, nil
+		}
 	}
 	app, err := impl.CreateApp(cloneReq, userId)
 	if err != nil {
@@ -136,49 +167,50 @@ func (impl *AppCloneServiceImpl) CloneApp(createReq *bean.CreateAppDTO, context
 		impl.logger.Errorw("error in cloning docker template", "ref", cloneReq.RefAppId, "new", newAppId, "err", err)
 		return nil, err
 	}
-	if !refAppStatus["TEMPLATE"] {
-		impl.logger.Errorw("status not", "TEMPLATE", cloneReq.RefAppId)
-		return app, nil
-	}
-	if !refAppStatus["CHART"] {
-		impl.logger.Errorw("status not", "CHART", cloneReq.RefAppId)
-		return app, nil
-	}
-	_, err = impl.CreateDeploymentTemplate(cloneReq.RefAppId, newAppId, userId, context)
-	if err != nil {
-		impl.logger.Errorw("error in creating deployment template", "ref", cloneReq.RefAppId, "new", newAppId, "err", err)
-		return nil, err
-	}
-	_, err = impl.CreateGlobalCM(cloneReq.RefAppId, newAppId, userId)
-
-	if err != nil {
-		impl.logger.Errorw("error in creating global cm", "ref", cloneReq.RefAppId, "new", newAppId, "err", err)
-		return nil, err
-	}
-	_, err = impl.CreateGlobalSecret(cloneReq.RefAppId, newAppId, userId)
-	if err != nil {
-		impl.logger.Errorw("error in creating global secret", "ref", cloneReq.RefAppId, "new", newAppId, "err", err)
-		return nil, err
-	}
-	if isSmaeProject {
-		_, err = impl.CreateEnvCm(context, cloneReq.RefAppId, newAppId, userId)
+	if createReq.AppType != helper.Job {
+		if !refAppStatus["TEMPLATE"] {
+			impl.logger.Errorw("status not", "TEMPLATE", cloneReq.RefAppId)
+			return app, nil
+		}
+		if !refAppStatus["CHART"] {
+			impl.logger.Errorw("status not", "CHART", cloneReq.RefAppId)
+			return app, nil
+		}
+		_, err = impl.CreateDeploymentTemplate(cloneReq.RefAppId, newAppId, userId, context)
 		if err != nil {
-			impl.logger.Errorw("error in creating env cm", "err", err)
+			impl.logger.Errorw("error in creating deployment template", "ref", cloneReq.RefAppId, "new", newAppId, "err", err)
 			return nil, err
 		}
-		_, err = impl.CreateEnvSecret(context, cloneReq.RefAppId, newAppId, userId)
+		_, err = impl.CreateGlobalCM(cloneReq.RefAppId, newAppId, userId)
+
 		if err != nil {
-			impl.logger.Errorw("error in creating env secret", "err", err)
+			impl.logger.Errorw("error in creating global cm", "ref", cloneReq.RefAppId, "new", newAppId, "err", err)
 			return nil, err
 		}
-		_, err = impl.createEnvOverride(cloneReq.RefAppId, newAppId, userId, context)
+		_, err = impl.CreateGlobalSecret(cloneReq.RefAppId, newAppId, userId)
 		if err != nil {
-			impl.logger.Errorw("error in cloning  env override", "err", err)
+			impl.logger.Errorw("error in creating global secret", "ref", cloneReq.RefAppId, "new", newAppId, "err", err)
 			return nil, err
 		}
+		if isSameProject {
+			_, err = impl.CreateEnvCm(context, cloneReq.RefAppId, newAppId, userId)
+			if err != nil {
+				impl.logger.Errorw("error in creating env cm", "err", err)
+				return nil, err
+			}
+			_, err = impl.CreateEnvSecret(context, cloneReq.RefAppId, newAppId, userId)
+			if err != nil {
+				impl.logger.Errorw("error in creating env secret", "err", err)
+				return nil, err
+			}
+			_, err = impl.createEnvOverride(cloneReq.RefAppId, newAppId, userId, context)
+			if err != nil {
+				impl.logger.Errorw("error in cloning  env override", "err", err)
+				return nil, err
+			}
+		}
 	}
-
-	_, err = impl.CreateWf(cloneReq.RefAppId, newAppId, userId, gitMaerialMap, context, isSmaeProject)
+	_, err = impl.CreateWf(cloneReq.RefAppId, newAppId, userId, gitMaerialMap, context, isSameProject)
 	if err != nil {
 		impl.logger.Errorw("error in creating wf", "ref", cloneReq.RefAppId, "new", newAppId, "err", err)
 		return nil, err
@@ -189,10 +221,12 @@ func (impl *AppCloneServiceImpl) CloneApp(createReq *bean.CreateAppDTO, context
 
 func (impl *AppCloneServiceImpl) CreateApp(cloneReq *CloneRequest, userId int32) (*bean.CreateAppDTO, error) {
 	createAppReq := &bean.CreateAppDTO{
-		AppName:   cloneReq.Name,
-		UserId:    userId,
-		TeamId:    cloneReq.ProjectId,
-		AppLabels: cloneReq.AppLabels,
+		AppName:     cloneReq.Name,
+		UserId:      userId,
+		TeamId:      cloneReq.ProjectId,
+		AppLabels:   cloneReq.AppLabels,
+		AppType:     cloneReq.AppType,
+		Description: cloneReq.Description,
 	}
 	createRes, err := impl.pipelineBuilder.CreateApp(createAppReq)
 	return createRes, err
@@ -557,7 +591,7 @@ func (impl *AppCloneServiceImpl) CreateGlobalSecret(oldAppId, newAppId int, user
 	return thisCm, err
 }
 
-func (impl *AppCloneServiceImpl) CreateWf(oldAppId, newAppId int, userId int32, gitMaterialMapping map[int]int, ctx context.Context, isSmaeProject bool) (interface{}, error) {
+func (impl *AppCloneServiceImpl) CreateWf(oldAppId, newAppId int, userId int32, gitMaterialMapping map[int]int, ctx context.Context, isSameProject bool) (interface{}, error) {
 	refAppWFs, err := impl.appWorkflowService.FindAppWorkflows(oldAppId)
 	if err != nil {
 		return nil, err
@@ -575,7 +609,7 @@ func (impl *AppCloneServiceImpl) CreateWf(oldAppId, newAppId int, userId int32,
 		if err != nil {
 			return nil, err
 		}
-		err = impl.createWfMappings(refAppWF.AppWorkflowMappingDto, oldAppId, newAppId, userId, thisWf.Id, gitMaterialMapping, ctx, isSmaeProject)
+		err = impl.createWfMappings(refAppWF.AppWorkflowMappingDto, oldAppId, newAppId, userId, thisWf.Id, gitMaterialMapping, ctx, isSameProject)
 		if err != nil {
 			return nil, err
 		}
@@ -583,7 +617,7 @@ func (impl *AppCloneServiceImpl) CreateWf(oldAppId, newAppId int, userId int32,
 	return nil, nil
 }
 
-func (impl *AppCloneServiceImpl) createWfMappings(refWfMappings []appWorkflow.AppWorkflowMappingDto, oldAppId, newAppId int, userId int32, thisWfId int, gitMaterialMapping map[int]int, ctx context.Context, isSmaeProject bool) error {
+func (impl *AppCloneServiceImpl) createWfMappings(refWfMappings []appWorkflow.AppWorkflowMappingDto, oldAppId, newAppId int, userId int32, thisWfId int, gitMaterialMapping map[int]int, ctx context.Context, isSameProject bool) error {
 	impl.logger.Debugw("wf mapping cloning", "refWfMappings", refWfMappings)
 	var ciMapping []appWorkflow.AppWorkflowMappingDto
 	var cdMappings []appWorkflow.AppWorkflowMappingDto
@@ -633,7 +667,7 @@ func (impl *AppCloneServiceImpl) createWfMappings(refWfMappings []appWorkflow.Ap
 		}
 		impl.logger.Debugw("ci created", "ci", ci)
 	}
-	if isSmaeProject {
+	if isSameProject {
 		for _, refCdMapping := range cdMappings {
 			cdCloneReq := &cloneCdPipelineRequest{
 				refCdPipelineId: refCdMapping.ComponentId,
diff --git a/pkg/appStore/deployment/service/AppStoreDeploymentService.go b/pkg/appStore/deployment/service/AppStoreDeploymentService.go
index 2f174fc54..8529f0182 100644
--- a/pkg/appStore/deployment/service/AppStoreDeploymentService.go
+++ b/pkg/appStore/deployment/service/AppStoreDeploymentService.go
@@ -28,6 +28,7 @@ import (
 	"github.com/devtron-labs/devtron/internal/constants"
 	repository2 "github.com/devtron-labs/devtron/internal/sql/repository"
 	"github.com/devtron-labs/devtron/internal/sql/repository/app"
+	"github.com/devtron-labs/devtron/internal/sql/repository/helper"
 	"github.com/devtron-labs/devtron/internal/util"
 	appStoreBean "github.com/devtron-labs/devtron/pkg/appStore/bean"
 	appStoreDeploymentCommon "github.com/devtron-labs/devtron/pkg/appStore/deployment/common"
@@ -43,6 +44,7 @@ import (
 	"github.com/devtron-labs/devtron/pkg/sql"
 	util2 "github.com/devtron-labs/devtron/util"
 	"github.com/go-pg/pg"
+	"go.opentelemetry.io/otel"
 	"go.uber.org/zap"
 	"net/http"
 	"strings"
@@ -410,7 +412,7 @@ func (impl AppStoreDeploymentServiceImpl) createAppForAppStore(createRequest *be
 		Active:          true,
 		AppName:         createRequest.AppName,
 		TeamId:          createRequest.TeamId,
-		AppStore:        true,
+		AppType:         helper.ChartStoreApp,
 		AppOfferingMode: appInstallationMode,
 		AuditLog:        sql.AuditLog{UpdatedBy: createRequest.UserId, CreatedBy: createRequest.UserId, UpdatedOn: time.Now(), CreatedOn: time.Now()},
 	}
@@ -907,13 +909,17 @@ func (impl AppStoreDeploymentServiceImpl) GetDeploymentHistoryInfo(ctx context.C
 	result := &openapi.HelmAppDeploymentManifestDetail{}
 	var err error
 	if util2.IsHelmApp(installedApp.AppOfferingMode) || installedApp.DeploymentAppType == util.PIPELINE_DEPLOYMENT_TYPE_HELM {
+		_, span := otel.Tracer("orchestrator").Start(ctx, "appStoreDeploymentHelmService.GetDeploymentHistoryInfo")
 		result, err = impl.appStoreDeploymentHelmService.GetDeploymentHistoryInfo(ctx, installedApp, int32(version))
+		span.End()
 		if err != nil {
 			impl.logger.Errorw("error while getting deployment history info", "error", err)
 			return nil, err
 		}
 	} else {
+		_, span := otel.Tracer("orchestrator").Start(ctx, "appStoreDeploymentArgoCdService.GetDeploymentHistoryInfo")
 		result, err = impl.appStoreDeploymentArgoCdService.GetDeploymentHistoryInfo(ctx, installedApp, int32(version))
+		span.End()
 		if err != nil {
 			impl.logger.Errorw("error while getting deployment history info", "error", err)
 			return nil, err
diff --git a/pkg/appStore/deployment/tool/AppStoreDeploymentHelmService.go b/pkg/appStore/deployment/tool/AppStoreDeploymentHelmService.go
index 2a80b4242..28f563bca 100644
--- a/pkg/appStore/deployment/tool/AppStoreDeploymentHelmService.go
+++ b/pkg/appStore/deployment/tool/AppStoreDeploymentHelmService.go
@@ -13,6 +13,7 @@ import (
 	clusterRepository "github.com/devtron-labs/devtron/pkg/cluster/repository"
 	"github.com/ghodss/yaml"
 	"github.com/go-pg/pg"
+	"go.opentelemetry.io/otel"
 	"go.uber.org/zap"
 	"net/http"
 	"time"
@@ -218,8 +219,9 @@ func (impl *AppStoreDeploymentHelmServiceImpl) GetDeploymentHistoryInfo(ctx cont
 		},
 		DeploymentVersion: version,
 	}
-
+	_, span := otel.Tracer("orchestrator").Start(ctx, "helmAppClient.GetDeploymentDetail")
 	deploymentDetail, err := impl.helmAppClient.GetDeploymentDetail(ctx, req)
+	span.End()
 	if err != nil {
 		impl.Logger.Errorw("error in getting deployment detail", "err", err)
 		return nil, err
diff --git a/pkg/appStore/deployment/tool/gitops/AppStoreDeploymentArgoCdService.go b/pkg/appStore/deployment/tool/gitops/AppStoreDeploymentArgoCdService.go
index 61b355925..3eb056aa8 100644
--- a/pkg/appStore/deployment/tool/gitops/AppStoreDeploymentArgoCdService.go
+++ b/pkg/appStore/deployment/tool/gitops/AppStoreDeploymentArgoCdService.go
@@ -26,6 +26,7 @@ import (
 	"github.com/ghodss/yaml"
 	"github.com/go-pg/pg"
 	"github.com/golang/protobuf/ptypes/timestamp"
+	"go.opentelemetry.io/otel"
 	"go.uber.org/zap"
 	"net/http"
 	"strings"
@@ -317,7 +318,9 @@ func (impl AppStoreDeploymentArgoCdServiceImpl) GetDeploymentHistory(ctx context
 
 func (impl AppStoreDeploymentArgoCdServiceImpl) GetDeploymentHistoryInfo(ctx context.Context, installedApp *appStoreBean.InstallAppVersionDTO, version int32) (*openapi.HelmAppDeploymentManifestDetail, error) {
 	values := &openapi.HelmAppDeploymentManifestDetail{}
+	_, span := otel.Tracer("orchestrator").Start(ctx, "installedAppRepositoryHistory.GetInstalledAppVersionHistory")
 	versionHistory, err := impl.installedAppRepositoryHistory.GetInstalledAppVersionHistory(int(version))
+	span.End()
 	if err != nil {
 		impl.Logger.Errorw("error while fetching installed version history", "error", err)
 		return nil, err
@@ -337,8 +340,9 @@ func (impl AppStoreDeploymentArgoCdServiceImpl) GetDeploymentHistoryInfo(ctx con
 		ValuesYaml:                   values.ValuesYaml,
 	}
 
+	_, span = otel.Tracer("orchestrator").Start(ctx, "helmAppService.TemplateChart")
 	templateChart, manifestErr := impl.helmAppService.TemplateChart(ctx, &manifestRequest)
-
+	span.End()
 	manifest := templateChart.GetManifest()
 
 	if manifestErr != nil {
diff --git a/pkg/bean/app.go b/pkg/bean/app.go
index 047c50330..207ff5a8b 100644
--- a/pkg/bean/app.go
+++ b/pkg/bean/app.go
@@ -19,6 +19,7 @@ package bean
 
 import (
 	"encoding/json"
+	"github.com/devtron-labs/devtron/internal/sql/repository/helper"
 	"github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig"
 	"github.com/devtron-labs/devtron/pkg/chartRepo/repository"
 	"github.com/devtron-labs/devtron/pkg/pipeline/bean"
@@ -38,13 +39,15 @@ type SourceTypeConfig struct {
 }
 
 type CreateAppDTO struct {
-	Id         int            `json:"id,omitempty" validate:"number"`
-	AppName    string         `json:"appName" validate:"name-component,max=100"`
-	UserId     int32          `json:"-"` //not exposed to UI
-	Material   []*GitMaterial `json:"material" validate:"dive,min=1"`
-	TeamId     int            `json:"teamId,omitempty" validate:"number,required"`
-	TemplateId int            `json:"templateId"`
-	AppLabels  []*Label       `json:"labels,omitempty" validate:"dive"`
+	Id          int            `json:"id,omitempty" validate:"number"`
+	AppName     string         `json:"appName" validate:"name-component,max=100"`
+	UserId      int32          `json:"-"` //not exposed to UI
+	Material    []*GitMaterial `json:"material" validate:"dive,min=1"`
+	TeamId      int            `json:"teamId,omitempty" validate:"number,required"`
+	TemplateId  int            `json:"templateId"`
+	AppLabels   []*Label       `json:"labels,omitempty" validate:"dive"`
+	Description string         `json:"description"`
+	AppType     helper.AppType `json:"appType" validate:"gt=-1,lt=3"` //TODO: Change Validation if new AppType is introduced
 }
 
 type CreateMaterialDTO struct {
@@ -289,6 +292,7 @@ type CiConfigRequest struct {
 	CreatedBy         int32                   `sql:"created_by,type:integer"`
 	UpdatedOn         time.Time               `sql:"updated_on,type:timestamptz"`
 	UpdatedBy         int32                   `sql:"updated_by,type:integer"`
+	IsJob             bool                    `json:"-"`
 }
 
 type TestExecutorImageProperties struct {
@@ -602,21 +606,23 @@ type Rollback struct {
 }
 
 type CiArtifactBean struct {
-	Id                            int             `json:"id"`
-	Image                         string          `json:"image,notnull"`
-	ImageDigest                   string          `json:"image_digest,notnull"`
-	MaterialInfo                  json.RawMessage `json:"material_info"` //git material metadata json array string
-	DataSource                    string          `json:"data_source,notnull"`
-	DeployedTime                  string          `json:"deployed_time"`
-	Deployed                      bool            `json:"deployed,notnull"`
-	Latest                        bool            `json:"latest,notnull"`
-	LastSuccessfulTriggerOnParent bool            `json:"lastSuccessfulTriggerOnParent,notnull"`
-	RunningOnParentCd             bool            `json:"runningOnParentCd,omitempty"`
-	IsVulnerable                  bool            `json:"vulnerable,notnull"`
-	ScanEnabled                   bool            `json:"scanEnabled,notnull"`
-	Scanned                       bool            `json:"scanned,notnull"`
-	WfrId                         int             `json:"wfrId"`
-	DeployedBy                    string          `json:"deployedBy"`
+	Id                            int                       `json:"id"`
+	Image                         string                    `json:"image,notnull"`
+	ImageDigest                   string                    `json:"image_digest,notnull"`
+	MaterialInfo                  json.RawMessage           `json:"material_info"` //git material metadata json array string
+	DataSource                    string                    `json:"data_source,notnull"`
+	DeployedTime                  string                    `json:"deployed_time"`
+	Deployed                      bool                      `json:"deployed,notnull"`
+	Latest                        bool                      `json:"latest,notnull"`
+	LastSuccessfulTriggerOnParent bool                      `json:"lastSuccessfulTriggerOnParent,notnull"`
+	RunningOnParentCd             bool                      `json:"runningOnParentCd,omitempty"`
+	IsVulnerable                  bool                      `json:"vulnerable,notnull"`
+	ScanEnabled                   bool                      `json:"scanEnabled,notnull"`
+	Scanned                       bool                      `json:"scanned,notnull"`
+	WfrId                         int                       `json:"wfrId"`
+	DeployedBy                    string                    `json:"deployedBy"`
+	CiConfigureSourceType         pipelineConfig.SourceType `json:"ciConfigureSourceType"`
+	CiConfigureSourceValue        string                    `json:"ciConfigureSourceValue"`
 }
 
 type CiArtifactResponse struct {
@@ -656,6 +662,7 @@ type AppMetaInfoDto struct {
 	CreatedOn   time.Time `json:"createdOn"`
 	Active      bool      `json:"active,notnull"`
 	Labels      []*Label  `json:"labels"`
+	Description string    `json:"description"`
 	UserId      int32     `json:"-"`
 }
 
diff --git a/pkg/chartRepo/ChartRepositoryService.go b/pkg/chartRepo/ChartRepositoryService.go
index e45c14cd2..a057b5add 100644
--- a/pkg/chartRepo/ChartRepositoryService.go
+++ b/pkg/chartRepo/ChartRepositoryService.go
@@ -44,7 +44,7 @@ import (
 
 type ChartRepositoryService interface {
 	CreateChartRepo(request *ChartRepoDto) (*chartRepoRepository.ChartRepo, error)
-	UpdateChartRepo(request *ChartRepoDto) (*chartRepoRepository.ChartRepo, error)
+	UpdateDataInArgocdCm(request *ChartRepoDto) (*chartRepoRepository.ChartRepo, error)
 	GetChartRepoById(id int) (*ChartRepoDto, error)
 	GetChartRepoByName(name string) (*ChartRepoDto, error)
 	GetChartRepoList() ([]*ChartRepoDto, error)
@@ -52,7 +52,7 @@ type ChartRepositoryService interface {
 	ValidateAndCreateChartRepo(request *ChartRepoDto) (*chartRepoRepository.ChartRepo, error, *DetailedErrorHelmRepoValidation)
 	ValidateAndUpdateChartRepo(request *ChartRepoDto) (*chartRepoRepository.ChartRepo, error, *DetailedErrorHelmRepoValidation)
 	TriggerChartSyncManual() error
-	DeleteChartRepo(request *ChartRepoDto) error
+	DeleteChartRepoFromArgocdCM(request *ChartRepoDto) error
 }
 
 type ChartRepositoryServiceImpl struct {
@@ -127,7 +127,11 @@ func (impl *ChartRepositoryServiceImpl) CreateChartRepo(request *ChartRepoDto) (
 		if err != nil {
 			return nil, err
 		}
-		data := impl.updateData(cm.Data, request)
+		data, err := impl.updateRepoData(cm.Data, request)
+		if err != nil {
+			impl.logger.Warnw(" config map update failed", "err", err)
+			continue
+		}
 		cm.Data = data
 		_, err = impl.K8sUtil.UpdateConfigMap(impl.aCDAuthConfig.ACDConfigMapNamespace, cm, client)
 		if err != nil {
@@ -148,7 +152,7 @@ func (impl *ChartRepositoryServiceImpl) CreateChartRepo(request *ChartRepoDto) (
 	return chartRepo, nil
 }
 
-func (impl *ChartRepositoryServiceImpl) UpdateChartRepo(request *ChartRepoDto) (*chartRepoRepository.ChartRepo, error) {
+func (impl *ChartRepositoryServiceImpl) UpdateDataInArgocdCm(request *ChartRepoDto) (*chartRepoRepository.ChartRepo, error) {
 	dbConnection := impl.repoRepository.GetConnection()
 	tx, err := dbConnection.Begin()
 	if err != nil {
@@ -160,8 +164,10 @@ func (impl *ChartRepositoryServiceImpl) UpdateChartRepo(request *ChartRepoDto) (
 	if err != nil && !util.IsErrNoRows(err) {
 		return nil, err
 	}
+	previousName := chartRepo.Name
 
 	chartRepo.Url = request.Url
+	chartRepo.Name = request.Name
 	chartRepo.AuthMode = request.AuthMode
 	chartRepo.UserName = request.UserName
 	chartRepo.Password = request.Password
@@ -186,7 +192,6 @@ func (impl *ChartRepositoryServiceImpl) UpdateChartRepo(request *ChartRepoDto) (
 	if err != nil {
 		return nil, err
 	}
-
 	client, err := impl.K8sUtil.GetClient(cfg)
 	if err != nil {
 		return nil, err
@@ -200,7 +205,18 @@ func (impl *ChartRepositoryServiceImpl) UpdateChartRepo(request *ChartRepoDto) (
 		if err != nil {
 			return nil, err
 		}
-		data := impl.updateData(cm.Data, request)
+		var data map[string]string
+		// if the repo name has been updated then, create a new repo
+		data, err = impl.updateRepoData(cm.Data, request)
+		// if the repo name has been updated then, delete the previous repo
+		if previousName != request.Name {
+			data, err = impl.removeRepoData(cm.Data, previousName)
+		}
+		if err != nil {
+			impl.logger.Warnw(" config map update failed", "err", err)
+			continue
+		}
+
 		cm.Data = data
 		_, err = impl.K8sUtil.UpdateConfigMap(impl.aCDAuthConfig.ACDConfigMapNamespace, cm, client)
 		if err != nil {
@@ -223,6 +239,88 @@ func (impl *ChartRepositoryServiceImpl) UpdateChartRepo(request *ChartRepoDto) (
 	return chartRepo, nil
 }
 
+// DeleteChartRepoFromArgocdCM update the active state from DB and modify the argo-cm with repo URL to null
+func (impl *ChartRepositoryServiceImpl) DeleteChartRepoFromArgocdCM(request *ChartRepoDto) error {
+	dbConnection := impl.repoRepository.GetConnection()
+	tx, err := dbConnection.Begin()
+	if err != nil {
+		impl.logger.Errorw("error in establishing db connection, DeleteChartRepo", "err", err)
+		return err
+	}
+	// Rollback tx on error.
+	defer tx.Rollback()
+
+	chartRepo, err := impl.repoRepository.FindById(request.Id)
+	if err != nil && !util.IsErrNoRows(err) {
+		impl.logger.Errorw("error in finding chart repo by id", "err", err, "id", request.Id)
+		return err
+	}
+	chartRepo.Url = request.Url
+	chartRepo.AuthMode = request.AuthMode
+	chartRepo.UserName = request.UserName
+	chartRepo.Password = request.Password
+	chartRepo.Active = request.Active
+	chartRepo.AccessToken = request.AccessToken
+	chartRepo.SshKey = request.SshKey
+	chartRepo.Active = request.Active
+	chartRepo.UpdatedBy = request.UserId
+	chartRepo.UpdatedOn = time.Now()
+	err = impl.repoRepository.MarkChartRepoDeleted(chartRepo, tx)
+	if err != nil {
+		impl.logger.Errorw("error in deleting chart repo", "err", err)
+		return err
+	}
+
+	// modify configmap
+	clusterBean, err := impl.clusterService.FindOne(cluster.DefaultClusterName)
+	if err != nil {
+		return err
+	}
+	cfg, err := impl.clusterService.GetClusterConfig(clusterBean)
+	if err != nil {
+		return err
+	}
+	client, err := impl.K8sUtil.GetClient(cfg)
+	if err != nil {
+		return err
+	}
+	updateSuccess := false
+	retryCount := 0
+	//request.Url = ""
+	for !updateSuccess && retryCount < 3 {
+		retryCount = retryCount + 1
+
+		cm, err := impl.K8sUtil.GetConfigMap(impl.aCDAuthConfig.ACDConfigMapNamespace, impl.aCDAuthConfig.ACDConfigMapName, client)
+		if err != nil {
+			return err
+		}
+		data, err := impl.removeRepoData(cm.Data, request.Name)
+		if err != nil {
+			impl.logger.Warnw(" config map update failed", "err", err)
+			continue
+		}
+		cm.Data = data
+		_, err = impl.K8sUtil.UpdateConfigMap(impl.aCDAuthConfig.ACDConfigMapNamespace, cm, client)
+		if err != nil {
+			impl.logger.Warnw(" config map failed", "err", err)
+			continue
+		}
+		if err == nil {
+			impl.logger.Warnw(" config map apply succeeded", "on retryCount", retryCount)
+			updateSuccess = true
+		}
+	}
+	if !updateSuccess {
+		return fmt.Errorf("resouce version not matched with config map attempted 3 times")
+	}
+	err = tx.Commit()
+	if err != nil {
+		impl.logger.Errorw("error in tx commit, DeleteChartRepo", "err", err)
+		return err
+	}
+	return nil
+}
+
 func (impl *ChartRepositoryServiceImpl) GetChartRepoById(id int) (*ChartRepoDto, error) {
 	model, err := impl.repoRepository.FindById(id)
 	if err != nil && !util.IsErrNoRows(err) {
@@ -357,7 +455,7 @@ func (impl *ChartRepositoryServiceImpl) ValidateAndUpdateChartRepo(request *Char
 	if validationResult.CustomErrMsg != ValidationSuccessMsg {
 		return nil, nil, validationResult
 	}
-	chartRepo, err := impl.UpdateChartRepo(request)
+	chartRepo, err := impl.UpdateDataInArgocdCm(request)
 	if err != nil {
 		return nil, err, validationResult
 	}
@@ -465,25 +563,30 @@ func (impl *ChartRepositoryServiceImpl) createRepoElement(request *ChartRepoDto)
 	return repoData
 }
 
-func (impl *ChartRepositoryServiceImpl) updateData(data map[string]string, request *ChartRepoDto) map[string]string {
+// updateRepoData update the request field in the argo-cm
+func (impl *ChartRepositoryServiceImpl) updateRepoData(data map[string]string, request *ChartRepoDto) (map[string]string, error) {
 	helmRepoStr := data["helm.repositories"]
 	helmRepoByte, err := yaml.YAMLToJSON([]byte(helmRepoStr))
 	if err != nil {
-		panic(err)
+		impl.logger.Errorw("error in json patch", "err", err)
+		return nil, err
 	}
 	var helmRepositories []*AcdConfigMapRepositoriesDto
 	err = json.Unmarshal(helmRepoByte, &helmRepositories)
 	if err != nil {
-		panic(err)
+		impl.logger.Errorw("error in unmarshal", "err", err)
+		return nil, err
 	}
 
 	rb, err := json.Marshal(helmRepositories)
 	if err != nil {
-		panic(err)
+		impl.logger.Errorw("error in marshal", "err", err)
+		return nil, err
 	}
 	helmRepositoriesYamlByte, err := yaml.JSONToYAML(rb)
 	if err != nil {
-		panic(err)
+		impl.logger.Errorw("error in yaml patch", "err", err)
+		return nil, err
 	}
 
 	//SETUP for repositories
@@ -491,16 +594,18 @@ func (impl *ChartRepositoryServiceImpl) updateData(data map[string]string, reque
 	repoStr := data["repositories"]
 	repoByte, err := yaml.YAMLToJSON([]byte(repoStr))
 	if err != nil {
-		panic(err)
+		impl.logger.Errorw("error in json patch", "err", err)
+		return nil, err
 	}
 	err = json.Unmarshal(repoByte, &repositories)
 	if err != nil {
-		panic(err)
+		impl.logger.Errorw("error in unmarshal", "err", err)
+		return nil, err
 	}
 
 	found := false
 	for _, item := range repositories {
-		//if request chart repo found, than update its values
+		//if request chart repo found, then update its values
 		if item.Name == request.Name {
 			if request.AuthMode == repository.AUTH_MODE_USERNAME_PASSWORD {
 				usernameSecret := &KeyDto{Name: request.UserName, Key: "username"}
@@ -526,11 +631,13 @@ func (impl *ChartRepositoryServiceImpl) updateData(data map[string]string, reque
 
 	rb, err = json.Marshal(repositories)
 	if err != nil {
-		panic(err)
+		impl.logger.Errorw("error in marshal", "err", err)
+		return nil, err
 	}
 	repositoriesYamlByte, err := yaml.JSONToYAML(rb)
 	if err != nil {
-		panic(err)
+		impl.logger.Errorw("error in yaml patch", "err", err)
+		return nil, err
 	}
 
 	if len(helmRepositoriesYamlByte) > 0 {
@@ -542,44 +649,84 @@ func (impl *ChartRepositoryServiceImpl) updateData(data map[string]string, reque
 	//dex config copy as it is
 	dexConfigStr := data["dex.config"]
 	data["dex.config"] = string([]byte(dexConfigStr))
-	return data
+	return data, nil
 }
 
-func (impl *ChartRepositoryServiceImpl) DeleteChartRepo(request *ChartRepoDto) error {
-	dbConnection := impl.repoRepository.GetConnection()
-	tx, err := dbConnection.Begin()
+// removeRepoData delete the request field from the argo-cm
+func (impl *ChartRepositoryServiceImpl) removeRepoData(data map[string]string, name string) (map[string]string, error) {
+	helmRepoStr := data["helm.repositories"]
+	helmRepoByte, err := yaml.YAMLToJSON([]byte(helmRepoStr))
 	if err != nil {
-		impl.logger.Errorw("error in establishing db connection, DeleteChartRepo", "err", err)
-		return err
+		impl.logger.Errorw("error in json patch", "err", err)
+		return nil, err
+	}
+	var helmRepositories []*AcdConfigMapRepositoriesDto
+	err = json.Unmarshal(helmRepoByte, &helmRepositories)
+	if err != nil {
+		impl.logger.Errorw("error in unmarshal", "err", err)
+		return nil, err
 	}
-	// Rollback tx on error.
-	defer tx.Rollback()
 
-	chartRepo, err := impl.repoRepository.FindById(request.Id)
-	if err != nil && !util.IsErrNoRows(err) {
-		impl.logger.Errorw("error in finding chart repo by id", "err", err, "id", request.Id)
-		return err
+	rb, err := json.Marshal(helmRepositories)
+	if err != nil {
+		impl.logger.Errorw("error in marshal", "err", err)
+		return nil, err
+	}
+	helmRepositoriesYamlByte, err := yaml.JSONToYAML(rb)
+	if err != nil {
+		impl.logger.Errorw("error in yaml patch", "err", err)
+		return nil, err
 	}
 
-	chartRepo.Url = request.Url
-	chartRepo.AuthMode = request.AuthMode
-	chartRepo.UserName = request.UserName
-	chartRepo.Password = request.Password
-	chartRepo.Active = request.Active
-	chartRepo.AccessToken = request.AccessToken
-	chartRepo.SshKey = request.SshKey
-	chartRepo.Active = false
-	chartRepo.UpdatedBy = request.UserId
-	chartRepo.UpdatedOn = time.Now()
-	err = impl.repoRepository.MarkChartRepoDeleted(chartRepo, tx)
+	//SETUP for repositories
+	var repositories []*AcdConfigMapRepositoriesDto
+	repoStr := data["repositories"]
+	repoByte, err := yaml.YAMLToJSON([]byte(repoStr))
 	if err != nil {
-		impl.logger.Errorw("error in deleting chart repo", "err", err)
-		return err
+		impl.logger.Errorw("error in json patch", "err", err)
+		return nil, err
 	}
-	err = tx.Commit()
+	err = json.Unmarshal(repoByte, &repositories)
 	if err != nil {
-		impl.logger.Errorw("error in tx commit, DeleteChartRepo", "err", err)
-		return err
+		impl.logger.Errorw("error in unmarshal", "err", err)
+		return nil, err
 	}
-	return nil
+
+	found := false
+	for index, item := range repositories {
+		//if request chart repo found, then delete its values
+		if item.Name == name {
+			repositories = append(repositories[:index], repositories[index+1:]...)
+			found = true
+			break
+		}
+	}
+
+	// if request chart repo not found, add new one
+	if !found {
+		impl.logger.Errorw("Repo not found", "err", err)
+		return nil, fmt.Errorf("Repo not found in config-map")
+	}
+
+	rb, err = json.Marshal(repositories)
+	if err != nil {
+		impl.logger.Errorw("error in marshal", "err", err)
+		return nil, err
+	}
+	repositoriesYamlByte, err := yaml.JSONToYAML(rb)
+	if err != nil {
+		impl.logger.Errorw("error in yaml patch", "err", err)
+		return nil, err
+	}
+
+	if len(helmRepositoriesYamlByte) > 0 {
+		data["helm.repositories"] = string(helmRepositoriesYamlByte)
+	}
+	if len(repositoriesYamlByte) > 0 {
+		data["repositories"] = string(repositoriesYamlByte)
+	}
+	//dex config copy as it is
+	dexConfigStr := data["dex.config"]
+	data["dex.config"] = string([]byte(dexConfigStr))
+	return data, nil
 }
diff --git a/pkg/clusterTerminalAccess/UserTerminalAccessService.go b/pkg/clusterTerminalAccess/UserTerminalAccessService.go
index a61ccda96..03febb210 100644
--- a/pkg/clusterTerminalAccess/UserTerminalAccessService.go
+++ b/pkg/clusterTerminalAccess/UserTerminalAccessService.go
@@ -532,7 +532,7 @@ func replaceTemplateData(templateData string, podNameVar string, namespace strin
 	return templateData, nil
 }
 
-//template data use kubernetes object
+// template data use kubernetes object
 func (impl *UserTerminalAccessServiceImpl) applyTemplateData(ctx context.Context, request *models.UserTerminalSessionRequest, podNameVar string,
 	terminalTemplate *models.TerminalAccessTemplates, isUpdate bool, isAutoSelect bool) error {
 	templateName := terminalTemplate.TemplateName
diff --git a/pkg/delete/DeleteService.go b/pkg/delete/DeleteService.go
index 43abf7fd0..d91db95ec 100644
--- a/pkg/delete/DeleteService.go
+++ b/pkg/delete/DeleteService.go
@@ -78,7 +78,7 @@ func (impl DeleteServiceImpl) DeleteChartRepo(deleteRequest *chartRepo.ChartRepo
 		impl.logger.Errorw("err in deleting repo, found charts deployed using this repo", "deleteRequest", deployedCharts)
 		return fmt.Errorf("cannot delete repo, found charts deployed in this repo")
 	}
-	err = impl.chartRepositoryService.DeleteChartRepo(deleteRequest)
+	err = impl.chartRepositoryService.DeleteChartRepoFromArgocdCM(deleteRequest)
 	if err != nil {
 		impl.logger.Errorw("error in deleting chart repo", "err", err, "deleteRequest", deleteRequest)
 		return err
diff --git a/pkg/delete/DeleteServiceExtended.go b/pkg/delete/DeleteServiceExtended.go
index 0ffc6987a..d9f08be5c 100644
--- a/pkg/delete/DeleteServiceExtended.go
+++ b/pkg/delete/DeleteServiceExtended.go
@@ -127,7 +127,7 @@ func (impl DeleteServiceExtendedImpl) DeleteChartRepo(deleteRequest *chartRepo.C
 		impl.logger.Errorw("err in deleting repo, found charts deployed using this repo", "deleteRequest", deployedCharts)
 		return fmt.Errorf("cannot delete repo, found charts deployed in this repo")
 	}
-	err = impl.chartRepositoryService.DeleteChartRepo(deleteRequest)
+	err = impl.chartRepositoryService.DeleteChartRepoFromArgocdCM(deleteRequest)
 	if err != nil {
 		impl.logger.Errorw("error in deleting chart repo", "err", err, "deleteRequest", deleteRequest)
 		return err
diff --git a/pkg/dockerRegistry/DockerRegistryIpsConfigService.go b/pkg/dockerRegistry/DockerRegistryIpsConfigService.go
index a7bd18b1e..3a028b690 100644
--- a/pkg/dockerRegistry/DockerRegistryIpsConfigService.go
+++ b/pkg/dockerRegistry/DockerRegistryIpsConfigService.go
@@ -105,12 +105,12 @@ func (impl DockerRegistryIpsConfigServiceImpl) HandleImagePullSecretOnApplicatio
 	}
 
 	dockerRegistryId := ciPipeline.CiTemplate.DockerRegistryId
-	if len(dockerRegistryId) == 0 {
+	if len(*dockerRegistryId) == 0 {
 		impl.logger.Warn("returning as dockerRegistryId is found empty")
 		return valuesFileContent, nil
 	}
 
-	dockerRegistryBean, err := impl.dockerArtifactStoreRepository.FindOne(dockerRegistryId)
+	dockerRegistryBean, err := impl.dockerArtifactStoreRepository.FindOne(*dockerRegistryId)
 	if err != nil {
 		impl.logger.Errorw("error in getting docker registry", "dockerRegistryId", dockerRegistryId, "error", err)
 		if err == pg.ErrNoRows {
@@ -134,7 +134,7 @@ func (impl DockerRegistryIpsConfigServiceImpl) HandleImagePullSecretOnApplicatio
 	}
 
 	ipsCredentialType := string(ipsConfig.CredentialType)
-	ipsName := BuildIpsName(dockerRegistryId, ipsCredentialType, ipsConfig.CredentialValue)
+	ipsName := BuildIpsName(*dockerRegistryId, ipsCredentialType, ipsConfig.CredentialValue)
 
 	// Create or update secret of credential type is not of NAME type
 	if ipsCredentialType != IPS_CREDENTIAL_TYPE_NAME {
diff --git a/pkg/pipeline/CdHandler.go b/pkg/pipeline/CdHandler.go
index 735a2c620..ec00cac6a 100644
--- a/pkg/pipeline/CdHandler.go
+++ b/pkg/pipeline/CdHandler.go
@@ -61,7 +61,7 @@ type CdHandler interface {
 	CancelStage(workflowRunnerId int, userId int32) (int, error)
 	FetchAppWorkflowStatusForTriggerView(appId int) ([]*pipelineConfig.CdWorkflowStatus, error)
 	CheckHelmAppStatusPeriodicallyAndUpdateInDb(helmPipelineStatusCheckEligibleTime int) error
-	CheckArgoAppStatusPeriodicallyAndUpdateInDb(timeForDegradation int) error
+	CheckArgoAppStatusPeriodicallyAndUpdateInDb(getPipelineDeployedBeforeMinutes int, getPipelineDeployedWithinHours int) error
 	CheckArgoPipelineTimelineStatusPeriodicallyAndUpdateInDb(pendingSinceSeconds int, timeForDegradation int) error
 	UpdatePipelineTimelineAndStatusByLiveApplicationFetch(pipeline *pipelineConfig.Pipeline, userId int32) (err error, isTimelineUpdated bool)
 	CheckAndSendArgoPipelineStatusSyncEventIfNeeded(pipelineId int, userId int32)
@@ -164,8 +164,8 @@ const WorklowTypeDeploy = "DEPLOY"
 const WorklowTypePre = "PRE"
 const WorklowTypePost = "POST"
 
-func (impl *CdHandlerImpl) CheckArgoAppStatusPeriodicallyAndUpdateInDb(deployedBeforeMinutes int) error {
-	pipelines, err := impl.pipelineRepository.GetArgoPipelinesHavingLatestTriggerStuckInNonTerminalStatuses(deployedBeforeMinutes)
+func (impl *CdHandlerImpl) CheckArgoAppStatusPeriodicallyAndUpdateInDb(getPipelineDeployedBeforeMinutes int, getPipelineDeployedWithinHours int) error {
+	pipelines, err := impl.pipelineRepository.GetArgoPipelinesHavingLatestTriggerStuckInNonTerminalStatuses(getPipelineDeployedBeforeMinutes, getPipelineDeployedWithinHours)
 	if err != nil {
 		impl.Logger.Errorw("error in getting pipelines having latest trigger stuck in non terminal statuses", "err", err)
 		return err
@@ -320,11 +320,20 @@ func (impl *CdHandlerImpl) CheckHelmAppStatusPeriodicallyAndUpdateInDb(helmPipel
 			//return err
 			//skip this error and continue for next workflow status
 			impl.Logger.Warnw("found error, skipping helm apps status update for this trigger", "appIdentifier", appIdentifier, "err", err)
-			continue
+
+			// Handle release not found errors
+			if !strings.Contains(err.Error(), "release: not found") {
+				continue
+			}
 		}
 		if helmAppStatus == application.Healthy {
 			wfr.Status = pipelineConfig.WorkflowSucceeded
 			wfr.FinishedOn = time.Now()
+
+		} else if err != nil && strings.Contains(err.Error(), "release: not found") {
+			// If release not found, mark the deployment as failure
+			wfr.Status = pipelineConfig.WorkflowFailed
+
 		} else {
 			wfr.Status = pipelineConfig.WorkflowInProgress
 		}
diff --git a/pkg/pipeline/CdWorkflowService.go b/pkg/pipeline/CdWorkflowService.go
index aa9272dd9..5ccecf5fb 100644
--- a/pkg/pipeline/CdWorkflowService.go
+++ b/pkg/pipeline/CdWorkflowService.go
@@ -20,11 +20,14 @@ package pipeline
 import (
 	"context"
 	"encoding/json"
+	"fmt"
 	blob_storage "github.com/devtron-labs/common-lib/blob-storage"
+	repository2 "github.com/devtron-labs/devtron/internal/sql/repository"
 	"github.com/devtron-labs/devtron/pkg/cluster/repository"
 	"k8s.io/apimachinery/pkg/util/intstr"
 	"net/url"
 	"strconv"
+	"strings"
 	"time"
 
 	"github.com/argoproj/argo-workflows/v3/pkg/apis/workflow/v1alpha1"
@@ -51,14 +54,18 @@ type CdWorkflowService interface {
 	TerminateWorkflow(name string, namespace string, url string, token string, isExtRun bool) error
 }
 
-const CD_WORKFLOW_NAME = "cd"
+const (
+	CD_WORKFLOW_NAME        = "cd"
+	CD_WORKFLOW_WITH_STAGES = "cd-stages-with-env"
+)
 
 type CdWorkflowServiceImpl struct {
-	Logger        *zap.SugaredLogger
-	config        *rest.Config
-	cdConfig      *CdConfig
-	appService    app.AppService
-	envRepository repository.EnvironmentRepository
+	Logger            *zap.SugaredLogger
+	config            *rest.Config
+	cdConfig          *CdConfig
+	appService        app.AppService
+	envRepository     repository.EnvironmentRepository
+	globalCMCSService GlobalCMCSService
 }
 
 type CdWorkflowRequest struct {
@@ -110,9 +117,17 @@ type CdWorkflowRequest struct {
 const PRE = "PRE"
 const POST = "POST"
 
-func NewCdWorkflowServiceImpl(Logger *zap.SugaredLogger, envRepository repository.EnvironmentRepository, cdConfig *CdConfig, appService app.AppService) *CdWorkflowServiceImpl {
-	return &CdWorkflowServiceImpl{Logger: Logger, config: cdConfig.ClusterConfig,
-		cdConfig: cdConfig, appService: appService, envRepository: envRepository}
+func NewCdWorkflowServiceImpl(Logger *zap.SugaredLogger,
+	envRepository repository.EnvironmentRepository,
+	cdConfig *CdConfig,
+	appService app.AppService,
+	globalCMCSService GlobalCMCSService) *CdWorkflowServiceImpl {
+	return &CdWorkflowServiceImpl{Logger: Logger,
+		config:            cdConfig.ClusterConfig,
+		cdConfig:          cdConfig,
+		appService:        appService,
+		envRepository:     envRepository,
+		globalCMCSService: globalCMCSService}
 }
 
 func (impl *CdWorkflowServiceImpl) SubmitWorkflow(workflowRequest *CdWorkflowRequest, pipeline *pipelineConfig.Pipeline, env *repository.Environment) (*v1alpha1.Workflow, error) {
@@ -144,8 +159,33 @@ func (impl *CdWorkflowServiceImpl) SubmitWorkflow(workflowRequest *CdWorkflowReq
 	reqMem := impl.cdConfig.ReqMem
 	ttl := int32(impl.cdConfig.BuildLogTTLValue)
 
-	var volumes []v12.Volume
-	var steps []v1alpha1.ParallelSteps
+	entryPoint := CD_WORKFLOW_NAME
+
+	steps := make([]v1alpha1.ParallelSteps, 0)
+	volumes := make([]v12.Volume, 0)
+	templates := make([]v1alpha1.Template, 0)
+
+	var globalCmCsConfigs []*GlobalCMCSDto
+
+	if !workflowRequest.IsExtRun {
+		globalCmCsConfigs, err = impl.globalCMCSService.FindAllActiveByPipelineType(repository2.PIPELINE_TYPE_CD)
+		// inject global variables only if IsExtRun is false
+		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
+		}
+		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)
+		if err != nil {
+			impl.Logger.Errorw("error in creating templates for global secrets", "err", err)
+		}
+	}
 
 	preStageConfigMapSecretsJson := pipeline.PreStageConfigMapSecretNames
 	postStageConfigMapSecretsJson := pipeline.PostStageConfigMapSecretNames
@@ -222,9 +262,8 @@ func (impl *CdWorkflowServiceImpl) SubmitWorkflow(workflowRequest *CdWorkflowReq
 	configsMapping := make(map[string]string)
 	secretsMapping := make(map[string]string)
 
-	entryPoint := CD_WORKFLOW_NAME
 	if len(configMaps.Maps) > 0 {
-		entryPoint = "cd-stages-with-env"
+		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 {
@@ -280,7 +319,7 @@ func (impl *CdWorkflowServiceImpl) SubmitWorkflow(workflowRequest *CdWorkflowReq
 	}
 
 	if len(secrets.Secrets) > 0 {
-		entryPoint = "cd-stages-with-env"
+		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 {
@@ -333,7 +372,6 @@ func (impl *CdWorkflowServiceImpl) SubmitWorkflow(workflowRequest *CdWorkflowReq
 		}
 	}
 
-	var templates []v1alpha1.Template
 	if len(configsMapping) > 0 {
 		for i, cm := range configMaps.Maps {
 			templates = append(templates, v1alpha1.Template{
@@ -367,7 +405,7 @@ func (impl *CdWorkflowServiceImpl) SubmitWorkflow(workflowRequest *CdWorkflowReq
 		},
 	})
 	templates = append(templates, v1alpha1.Template{
-		Name:  "cd-stages-with-env",
+		Name:  CD_WORKFLOW_WITH_STAGES,
 		Steps: steps,
 	})
 
@@ -468,6 +506,35 @@ func (impl *CdWorkflowServiceImpl) SubmitWorkflow(workflowRequest *CdWorkflowReq
 		cdTemplate.ArchiveLocation.GCS = gcsArtifact
 	}
 
+	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,
+							},
+						},
+					})
+				}
+			}
+		}
+	}
+
 	for _, cm := range configMaps.Maps {
 		if cm.Type == "environment" {
 			cdTemplate.Container.EnvFrom = append(cdTemplate.Container.EnvFrom, v12.EnvFromSource{
diff --git a/pkg/pipeline/CiCdPipelineOrchestrator.go b/pkg/pipeline/CiCdPipelineOrchestrator.go
index 244be6730..839984506 100644
--- a/pkg/pipeline/CiCdPipelineOrchestrator.go
+++ b/pkg/pipeline/CiCdPipelineOrchestrator.go
@@ -27,6 +27,7 @@ import (
 	"fmt"
 	app2 "github.com/devtron-labs/devtron/internal/sql/repository/app"
 	dockerRegistryRepository "github.com/devtron-labs/devtron/internal/sql/repository/dockerRegistry"
+	"github.com/devtron-labs/devtron/internal/sql/repository/helper"
 	repository2 "github.com/devtron-labs/devtron/pkg/cluster/repository"
 	bean2 "github.com/devtron-labs/devtron/pkg/pipeline/bean"
 	history3 "github.com/devtron-labs/devtron/pkg/pipeline/history"
@@ -813,7 +814,7 @@ func (impl CiCdPipelineOrchestratorImpl) CreateApp(createRequest *bean.CreateApp
 	}
 	// Rollback tx on error.
 	defer tx.Rollback()
-	app, err := impl.createAppGroup(createRequest.AppName, createRequest.UserId, createRequest.TeamId, tx)
+	app, err := impl.createAppGroup(createRequest.AppName, createRequest.UserId, createRequest.TeamId, createRequest.AppType, createRequest.Description, tx)
 	if err != nil {
 		return nil, err
 	}
@@ -840,6 +841,9 @@ func (impl CiCdPipelineOrchestratorImpl) CreateApp(createRequest *bean.CreateApp
 		return nil, err
 	}
 	createRequest.Id = app.Id
+	if createRequest.AppType == helper.Job {
+		createRequest.AppName = app.DisplayName
+	}
 	return createRequest, nil
 }
 
@@ -995,25 +999,50 @@ func (impl CiCdPipelineOrchestratorImpl) addRepositoryToGitSensor(materials []*b
 }
 
 // FIXME: not thread safe
-func (impl CiCdPipelineOrchestratorImpl) createAppGroup(name string, userId int32, teamId int, tx *pg.Tx) (*app2.App, error) {
+func (impl CiCdPipelineOrchestratorImpl) createAppGroup(name string, userId int32, teamId int, appType helper.AppType, description string, tx *pg.Tx) (*app2.App, error) {
 	app, err := impl.appRepository.FindActiveByName(name)
 	if err != nil && err != pg.ErrNoRows {
 		return nil, err
 	}
-	if app != nil && app.Id > 0 {
-		impl.logger.Warnw("app already exists", "name", name)
-		err = &util.ApiError{
-			Code:            constants.AppAlreadyExists.Code,
-			InternalMessage: "app already exists",
-			UserMessage:     constants.AppAlreadyExists.UserMessage(name),
+	if appType != helper.Job {
+		if app != nil && app.Id > 0 {
+			impl.logger.Warnw("app already exists", "name", name)
+			err = &util.ApiError{
+				Code:            constants.AppAlreadyExists.Code,
+				InternalMessage: "app already exists",
+				UserMessage:     constants.AppAlreadyExists.UserMessage(name),
+			}
+			return nil, err
 		}
-		return nil, err
+	} else {
+		job, err := impl.appRepository.FindJobByDisplayName(name)
+		if err != nil && err != pg.ErrNoRows {
+			return nil, err
+		}
+		if job != nil && job.Id > 0 {
+			impl.logger.Warnw("job already exists", "name", name)
+			err = &util.ApiError{
+				Code:            constants.AppAlreadyExists.Code,
+				InternalMessage: "job already exists",
+				UserMessage:     constants.AppAlreadyExists.UserMessage(name),
+			}
+			return nil, err
+		}
+	}
+
+	displayName := name
+	appName := name
+	if appType == helper.Job {
+		appName = name + "/" + util2.Generate(8) + "J"
 	}
 	pg := &app2.App{
-		Active:   true,
-		AppName:  name,
-		TeamId:   teamId,
-		AuditLog: sql.AuditLog{UpdatedBy: userId, CreatedBy: userId, UpdatedOn: time.Now(), CreatedOn: time.Now()},
+		Active:      true,
+		AppName:     appName,
+		DisplayName: displayName,
+		TeamId:      teamId,
+		AppType:     appType,
+		Description: description,
+		AuditLog:    sql.AuditLog{UpdatedBy: userId, CreatedBy: userId, UpdatedOn: time.Now(), CreatedOn: time.Now()},
 	}
 	err = impl.appRepository.SaveWithTxn(pg, tx)
 	if err != nil {
diff --git a/pkg/pipeline/CiHandler.go b/pkg/pipeline/CiHandler.go
index 6c961096e..346ee6e6b 100644
--- a/pkg/pipeline/CiHandler.go
+++ b/pkg/pipeline/CiHandler.go
@@ -157,6 +157,7 @@ type WorkflowResponse struct {
 	TriggeredByEmail   string                           `json:"triggeredByEmail"`
 	Stage              string                           `json:"stage"`
 	ArtifactId         int                              `json:"artifactId"`
+	IsArtifactUploaded bool                             `json:"isArtifactUploaded"`
 }
 
 type GitTriggerInfoResponse struct {
@@ -397,6 +398,7 @@ func (impl *CiHandlerImpl) GetBuildHistory(pipelineId int, offset int, size int)
 			TriggeredByEmail:   w.EmailId,
 			ArtifactId:         w.CiArtifactId,
 			BlobStorageEnabled: w.BlobStorageEnabled,
+			IsArtifactUploaded: w.IsArtifactUploaded,
 		}
 		ciWorkLowResponses = append(ciWorkLowResponses, wfResponse)
 	}
@@ -494,6 +496,8 @@ func (impl *CiHandlerImpl) FetchWorkflowDetails(appId int, pipelineId int, build
 		TriggeredBy:        workflow.TriggeredBy,
 		TriggeredByEmail:   triggeredByUser.EmailId,
 		Artifact:           ciArtifact.Image,
+		ArtifactId:         ciArtifact.Id,
+		IsArtifactUploaded: ciArtifact.IsArtifactUploaded,
 	}
 	return workflowResponse, nil
 }
diff --git a/pkg/pipeline/CiService.go b/pkg/pipeline/CiService.go
index 81d09356b..51d4d4b5a 100644
--- a/pkg/pipeline/CiService.go
+++ b/pkg/pipeline/CiService.go
@@ -157,7 +157,7 @@ func (impl *CiServiceImpl) TriggerCiPipeline(trigger Trigger) (int, error) {
 	}
 	impl.Logger.Debugw("ci triggered", "wf name ", createdWf.Name, " pipeline ", trigger.PipelineId)
 
-	middleware.CiTriggerCounter.WithLabelValues(pipeline.App.AppName).Inc()
+	middleware.CiTriggerCounter.WithLabelValues(pipeline.App.AppName, pipeline.Name).Inc()
 	go impl.WriteCITriggerEvent(trigger, pipeline, workflowRequest)
 	return savedCiWf.Id, err
 }
@@ -446,19 +446,6 @@ func (impl *CiServiceImpl) buildWfRequestForCiPipeline(pipeline *pipelineConfig.
 		WorkflowNamePrefix:         strconv.Itoa(savedWf.Id) + "-" + savedWf.Name,
 		PipelineName:               pipeline.Name,
 		PipelineId:                 pipeline.Id,
-		DockerRegistryId:           dockerRegistry.Id,
-		DockerRegistryType:         string(dockerRegistry.RegistryType),
-		DockerImageTag:             dockerImageTag,
-		DockerRegistryURL:          dockerRegistry.RegistryURL,
-		DockerRepository:           dockerRepository,
-		CheckoutPath:               checkoutPath,
-		DockerUsername:             dockerRegistry.Username,
-		DockerPassword:             dockerRegistry.Password,
-		AwsRegion:                  dockerRegistry.AWSRegion,
-		AccessKey:                  dockerRegistry.AWSAccessKeyId,
-		SecretKey:                  dockerRegistry.AWSSecretAccessKey,
-		DockerConnection:           dockerRegistry.Connection,
-		DockerCert:                 dockerRegistry.Cert,
 		CiCacheFileName:            pipeline.Name + "-" + strconv.Itoa(pipeline.Id) + ".tar.gz",
 		CiProjectDetails:           ciProjectDetails,
 		Namespace:                  ciWorkflowConfig.Namespace,
@@ -484,7 +471,23 @@ func (impl *CiServiceImpl) buildWfRequestForCiPipeline(pipeline *pipelineConfig.
 		CacheInvalidate:            trigger.InvalidateCache,
 		ExtraEnvironmentVariables:  trigger.ExtraEnvironmentVariables,
 	}
+	if dockerRegistry != nil {
 
+		workflowRequest.DockerRegistryId = dockerRegistry.Id
+		workflowRequest.DockerRegistryType = string(dockerRegistry.RegistryType)
+		workflowRequest.DockerImageTag = dockerImageTag
+		workflowRequest.DockerRegistryURL = dockerRegistry.RegistryURL
+		workflowRequest.DockerRepository = dockerRepository
+		workflowRequest.CheckoutPath = checkoutPath
+		workflowRequest.DockerUsername = dockerRegistry.Username
+		workflowRequest.DockerPassword = dockerRegistry.Password
+		workflowRequest.AwsRegion = dockerRegistry.AWSRegion
+		workflowRequest.AccessKey = dockerRegistry.AWSAccessKeyId
+		workflowRequest.SecretKey = dockerRegistry.AWSSecretAccessKey
+		workflowRequest.DockerConnection = dockerRegistry.Connection
+		workflowRequest.DockerCert = dockerRegistry.Cert
+
+	}
 	if ciWorkflowConfig.LogsBucket == "" {
 		ciWorkflowConfig.LogsBucket = impl.ciConfig.DefaultBuildLogsBucket
 	}
diff --git a/pkg/pipeline/GlobalCMCSService.go b/pkg/pipeline/GlobalCMCSService.go
index affbd5485..4fd24be07 100644
--- a/pkg/pipeline/GlobalCMCSService.go
+++ b/pkg/pipeline/GlobalCMCSService.go
@@ -3,16 +3,25 @@ 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/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)
+	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
+	DeleteById(id int) error
 }
 
 type GlobalCMCSServiceImpl struct {
@@ -34,46 +43,66 @@ type GlobalCMCSDto struct {
 	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:"-"`
+	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 (impl *GlobalCMCSServiceImpl) Create(config *GlobalCMCSDto) (*GlobalCMCSDto, error) {
-	//checking if same name config is present for this type
+type GlobalCMCSDataUpdateDto struct {
+	Id                 int               `json:"id"`
+	Data               map[string]string `json:"data"  validate:"required"`
+	SecretIngestionFor string            `json:"SecretIngestionFor"` // value can be one of [ci, cd, ci/cd]
+	UserId             int32             `json:"-"`
+}
+
+func (impl *GlobalCMCSServiceImpl) validateGlobalCMCSData(config *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)
-		return nil, err
+		return err
 	}
 	if config.Type == repository.VOLUME_CONFIG {
 		//checking if same mountPath config is present for any type
 		sameMountPathConfig, err := impl.globalCMCSRepository.FindByMountPath(config.MountPath)
 		if err != nil && err != pg.ErrNoRows {
 			impl.logger.Errorw("error in getting global cm/cs config by mountPath and configType", "err", err, "mountPath", config.MountPath)
-			return nil, err
+			return err
 		}
 		if (sameMountPathConfig != nil && sameMountPathConfig.Id > 0) && (sameNameConfig != nil && sameNameConfig.Id > 0) {
 			impl.logger.Errorw("found global cm/cs config with same name and same mountPath", "configName", config.Name)
-			return nil, fmt.Errorf("found configs with same name & mount path, please update the name & mountPath and try again")
+			return fmt.Errorf("found configs with same name & mount path, please update the name & mountPath and try again")
 		} else if sameMountPathConfig != nil && sameMountPathConfig.Id > 0 {
 			impl.logger.Errorw("found global cm/cs config with same mountPath", "configName", config.Name)
-			return nil, fmt.Errorf("found configs with same mount path, please update the mount path and try again")
+			return fmt.Errorf("found configs with same mount path, please update the mount path and try again")
 		}
 	}
 	if sameNameConfig != nil && sameNameConfig.Id > 0 {
 		impl.logger.Errorw("found global cm/cs config with same name", "configName", config.Name)
-		return nil, fmt.Errorf("found %s with same name, please update the name and try again", config.ConfigType)
+		return fmt.Errorf("found %s with same name, please update the name and try again", config.ConfigType)
+	}
+	return nil
+}
+
+func (impl *GlobalCMCSServiceImpl) Create(config *GlobalCMCSDto) (*GlobalCMCSDto, error) {
+
+	err := impl.validateGlobalCMCSData(config)
+	if err != nil {
+		return nil, err
 	}
+	//checking if same name config is present for this type
 	dataByte, err := json.Marshal(config.Data)
 	if err != nil {
 		impl.logger.Errorw("error in marshaling cm/cs data", "err", err)
 		return nil, err
 	}
+	if config.SecretIngestionFor == "" {
+		config.SecretIngestionFor = "CI/CD"
+	}
 	model := &repository.GlobalCMCS{
 		ConfigType: config.ConfigType,
-		Data:       json.RawMessage(dataByte),
+		Data:       string(dataByte),
 		Name:       config.Name,
 		MountPath:  config.MountPath,
 		Type:       config.Type,
@@ -84,6 +113,7 @@ func (impl *GlobalCMCSServiceImpl) Create(config *GlobalCMCSDto) (*GlobalCMCSDto
 			UpdatedBy: config.UserId,
 			UpdatedOn: time.Now(),
 		},
+		SecretIngestionFor: config.SecretIngestionFor,
 	}
 	model, err = impl.globalCMCSRepository.Save(model)
 	if err != nil {
@@ -94,16 +124,39 @@ func (impl *GlobalCMCSServiceImpl) Create(config *GlobalCMCSDto) (*GlobalCMCSDto
 	return config, nil
 }
 
-func (impl *GlobalCMCSServiceImpl) FindAllActive() ([]*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)
+func (impl *GlobalCMCSServiceImpl) UpdateDataById(config *GlobalCMCSDataUpdateDto) (*GlobalCMCSDataUpdateDto, error) {
+
+	model, err := impl.globalCMCSRepository.FindById(config.Id)
+	if err != nil {
+		impl.logger.Errorw("error in fetching data from global cm cs")
+		return nil, err
+	}
+	//checking if same name config is present for this type
+	dataByte, err := json.Marshal(config.Data)
+	if err != nil {
+		impl.logger.Errorw("error in marshaling cm/cs data", "err", err)
+		return nil, err
+	}
+	model.Data = string(dataByte)
+	if config.SecretIngestionFor != "" {
+		model.SecretIngestionFor = config.SecretIngestionFor
+	}
+	model.UpdatedBy = config.UserId
+	model.UpdatedOn = time.Now()
+	model, err = impl.globalCMCSRepository.Update(model)
+	if err != nil {
+		impl.logger.Errorw("err on creating global cm/cs config ", "err", err)
 		return nil, err
 	}
+	config.Id = model.Id
+	return config, nil
+}
+
+func (impl *GlobalCMCSServiceImpl) ConvertGlobalCmcsDbObjectToGlobalCmcsDto(GlobalCMCSDBObject []*repository.GlobalCMCS) []*GlobalCMCSDto {
 	var configDtos []*GlobalCMCSDto
-	for _, model := range models {
+	for _, model := range GlobalCMCSDBObject {
 		data := make(map[string]string)
-		err = json.Unmarshal([]byte(model.Data), &data)
+		err := json.Unmarshal([]byte(model.Data), &data)
 		if err != nil {
 			impl.logger.Errorw("error in un-marshaling cm/cs data", "err", err)
 		}
@@ -117,6 +170,186 @@ func (impl *GlobalCMCSServiceImpl) FindAllActive() ([]*GlobalCMCSDto, error) {
 		}
 		configDtos = append(configDtos, configDto)
 	}
+	return configDtos
+}
+
+func (impl *GlobalCMCSServiceImpl) FindAllActiveByPipelineType(pipelineType string) ([]*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)
+		return nil, err
+	}
+	configDtos := impl.ConvertGlobalCmcsDbObjectToGlobalCmcsDto(models)
+	return configDtos, nil
+}
 
+func (impl *GlobalCMCSServiceImpl) FindAllActive() ([]*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)
+		return nil, err
+	}
+	configDtos := impl.ConvertGlobalCmcsDbObjectToGlobalCmcsDto(models)
 	return configDtos, nil
 }
+
+func (impl *GlobalCMCSServiceImpl) GetGlobalCMCSDataByConfigTypeAndName(configName string, configType string) (*GlobalCMCSDto, error) {
+
+	model, err := impl.globalCMCSRepository.FindByConfigTypeAndName(configType, configName)
+	if err != nil {
+		impl.logger.Errorw("error in fetching data from ")
+		return nil, err
+	}
+	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)
+	}
+	GlobalCMCSDto := &GlobalCMCSDto{
+		Id:                 model.Id,
+		ConfigType:         model.ConfigType,
+		Name:               model.Name,
+		Type:               model.Type,
+		Data:               data,
+		MountPath:          model.MountPath,
+		Deleted:            model.Deleted,
+		SecretIngestionFor: model.SecretIngestionFor,
+	}
+	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)
+	if err != nil {
+		impl.logger.Errorw("error in fetching model by id", "err", err)
+		return err
+	}
+	err = impl.globalCMCSRepository.Delete(model)
+	if err != nil {
+		impl.logger.Errorw("error in deleting model")
+		return err
+	}
+	return nil
+}
diff --git a/pkg/pipeline/PipelineBuilder.go b/pkg/pipeline/PipelineBuilder.go
index 24172b1e5..086a11a4c 100644
--- a/pkg/pipeline/PipelineBuilder.go
+++ b/pkg/pipeline/PipelineBuilder.go
@@ -25,6 +25,7 @@ import (
 	client "github.com/devtron-labs/devtron/api/helm-app"
 	app2 "github.com/devtron-labs/devtron/internal/sql/repository/app"
 	"github.com/devtron-labs/devtron/internal/sql/repository/appStatus"
+	"github.com/devtron-labs/devtron/internal/sql/repository/helper"
 	"github.com/devtron-labs/devtron/internal/sql/repository/security"
 	"github.com/devtron-labs/devtron/pkg/chart"
 	chartRepoRepository "github.com/devtron-labs/devtron/pkg/chartRepo/repository"
@@ -125,7 +126,7 @@ type PipelineBuilder interface {
 	GetCiPipelineById(pipelineId int) (ciPipeline *bean.CiPipeline, err error)
 
 	GetMaterialsForAppId(appId int) []*bean.GitMaterial
-	FindAllMatchesByAppName(appName string) ([]*AppBean, error)
+	FindAllMatchesByAppName(appName string, appType helper.AppType) ([]*AppBean, error)
 	GetEnvironmentByCdPipelineId(pipelineId int) (int, error)
 	PatchRegexCiPipeline(request *bean.CiRegexPatchRequest) (err error)
 
@@ -182,6 +183,7 @@ type PipelineBuilderImpl struct {
 	helmAppService                   client.HelmAppService
 	deploymentGroupRepository        repository.DeploymentGroupRepository
 	ciPipelineMaterialRepository     pipelineConfig.CiPipelineMaterialRepository
+	ciWorkflowRepository             pipelineConfig.CiWorkflowRepository
 	//ciTemplateOverrideRepository     pipelineConfig.CiTemplateOverrideRepository
 	//ciBuildConfigService CiBuildConfigService
 	ciTemplateService                               CiTemplateService
@@ -244,7 +246,8 @@ func NewPipelineBuilderImpl(logger *zap.SugaredLogger,
 	globalStrategyMetadataChartRefMappingRepository chartRepoRepository.GlobalStrategyMetadataChartRefMappingRepository,
 	deploymentConfig *DeploymentServiceTypeConfig, appStatusRepository appStatus.AppStatusRepository,
 	workflowDagExecutor WorkflowDagExecutor,
-	enforcerUtil rbac.EnforcerUtil, ArgoUserService argo.ArgoUserService) *PipelineBuilderImpl {
+	enforcerUtil rbac.EnforcerUtil, ArgoUserService argo.ArgoUserService,
+	ciWorkflowRepository pipelineConfig.CiWorkflowRepository) *PipelineBuilderImpl {
 	return &PipelineBuilderImpl{
 		logger:                        logger,
 		ciCdPipelineOrchestrator:      ciCdPipelineOrchestrator,
@@ -300,6 +303,7 @@ func NewPipelineBuilderImpl(logger *zap.SugaredLogger,
 		ArgoUserService:                                 ArgoUserService,
 		workflowDagExecutor:                             workflowDagExecutor,
 		enforcerUtil:                                    enforcerUtil,
+		ciWorkflowRepository:                            ciWorkflowRepository,
 	}
 }
 
@@ -323,6 +327,7 @@ func formatDate(t time.Time, layout string) string {
 
 func (impl PipelineBuilderImpl) CreateApp(request *bean.CreateAppDTO) (*bean.CreateAppDTO, error) {
 	impl.logger.Debugw("app create request received", "req", request)
+
 	res, err := impl.ciCdPipelineOrchestrator.CreateApp(request)
 	if err != nil {
 		impl.logger.Errorw("error in saving create app req", "req", request, "err", err)
@@ -399,13 +404,17 @@ func (impl PipelineBuilderImpl) GetApp(appId int) (application *bean.CreateAppDT
 		impl.logger.Errorw("error in fetching app", "id", appId, "err", err)
 		return nil, err
 	}
-	gitMaterials := impl.GetMaterialsForAppId(appId)
 
+	gitMaterials := impl.GetMaterialsForAppId(appId)
+	if app.AppType == helper.Job {
+		app.AppName = app.DisplayName
+	}
 	application = &bean.CreateAppDTO{
 		Id:       app.Id,
 		AppName:  app.AppName,
 		Material: gitMaterials,
 		TeamId:   app.TeamId,
+		AppType:  app.AppType,
 	}
 	return application, nil
 }
@@ -450,6 +459,7 @@ func (impl PipelineBuilderImpl) GetMaterialsForAppId(appId int) []*bean.GitMater
 */
 
 func (impl PipelineBuilderImpl) getDefaultArtifactStore(id string) (store *dockerRegistryRepository.DockerArtifactStore, err error) {
+
 	if id == "" {
 		impl.logger.Debugw("docker repo is empty adding default repo")
 		store, err = impl.dockerArtifactStoreRepository.FindActiveDefaultStore()
@@ -499,17 +509,21 @@ func (impl PipelineBuilderImpl) getCiTemplateVariables(appId int) (ciConfig *bea
 	//	impl.logger.Debugw("error in json unmarshal", "app", appId, "err", err)
 	//	return nil, err
 	//}
-	regHost, err := template.DockerRegistry.GetRegistryLocation()
-	if err != nil {
-		impl.logger.Errorw("invalid reg url", "err", err)
-		return nil, err
+	var regHost string
+	dockerRegistry := template.DockerRegistry
+	if dockerRegistry != nil {
+		regHost, err = dockerRegistry.GetRegistryLocation()
+		if err != nil {
+			impl.logger.Errorw("invalid reg url", "err", err)
+			return nil, err
+		}
 	}
 	ciConfig = &bean.CiConfigRequest{
-		Id:                template.Id,
-		AppId:             template.AppId,
-		AppName:           template.App.AppName,
-		DockerRepository:  template.DockerRepository,
-		DockerRegistry:    template.DockerRegistry.Id,
+		Id:               template.Id,
+		AppId:            template.AppId,
+		AppName:          template.App.AppName,
+		DockerRepository: template.DockerRepository,
+		//DockerRegistry:    dockerRegistry.Id,
 		DockerRegistryUrl: regHost,
 		CiBuildConfig:     ciTemplateBean.CiBuildConfig,
 		//DockerBuildConfig: &bean.DockerBuildConfig{DockerfilePath: template.DockerfilePath, Args: dockerArgs, GitMaterialId: template.GitMaterialId, TargetPlatform: template.TargetPlatform},
@@ -521,6 +535,9 @@ func (impl PipelineBuilderImpl) getCiTemplateVariables(appId int) (ciConfig *bea
 		CreatedBy:      template.CreatedBy,
 		CreatedOn:      template.CreatedOn,
 	}
+	if dockerRegistry != nil {
+		ciConfig.DockerRegistry = dockerRegistry.Id
+	}
 	return ciConfig, err
 }
 
@@ -923,7 +940,7 @@ func (impl PipelineBuilderImpl) UpdateCiTemplate(updateRequest *bean.CiConfigReq
 		Version:           originalCiConf.Version,
 		Id:                originalCiConf.Id,
 		DockerRepository:  originalCiConf.DockerRepository,
-		DockerRegistryId:  originalCiConf.DockerRegistry,
+		DockerRegistryId:  &originalCiConf.DockerRegistry,
 		Active:            true,
 		AuditLog: sql.AuditLog{
 			CreatedOn: originalCiConf.CreatedOn,
@@ -966,35 +983,37 @@ func (impl PipelineBuilderImpl) CreateCiPipeline(createRequest *bean.CiConfigReq
 	}
 	//--ecr config
 	createRequest.AppName = app.AppName
-	store, err := impl.getDefaultArtifactStore(createRequest.DockerRegistry)
-	if err != nil {
-		impl.logger.Errorw("error in fetching docker store ", "id", createRequest.DockerRepository, "err", err)
-		return nil, err
-	}
-	regHost, err := store.GetRegistryLocation()
-	if err != nil {
-		impl.logger.Errorw("invalid reg url", "err", err)
-		return nil, err
-	}
-	createRequest.DockerRegistryUrl = regHost
-	createRequest.DockerRegistry = store.Id
-
-	var repo string
-	if createRequest.DockerRepository != "" {
-		repo = createRequest.DockerRepository
-	} else {
-		repo = impl.ecrConfig.EcrPrefix + app.AppName
-	}
+	if !createRequest.IsJob {
+		store, err := impl.getDefaultArtifactStore(createRequest.DockerRegistry)
+		if err != nil {
+			impl.logger.Errorw("error in fetching docker store ", "id", createRequest.DockerRepository, "err", err)
+			return nil, err
+		}
 
-	if store.RegistryType == dockerRegistryRepository.REGISTRYTYPE_ECR {
-		err := impl.ciCdPipelineOrchestrator.CreateEcrRepo(repo, store.AWSRegion, store.AWSAccessKeyId, store.AWSSecretAccessKey)
+		regHost, err := store.GetRegistryLocation()
 		if err != nil {
-			impl.logger.Errorw("ecr repo creation failed while creating ci pipeline", "repo", repo, "err", err)
+			impl.logger.Errorw("invalid reg url", "err", err)
 			return nil, err
 		}
-	}
-	createRequest.DockerRepository = repo
+		createRequest.DockerRegistryUrl = regHost
+		createRequest.DockerRegistry = store.Id
+
+		var repo string
+		if createRequest.DockerRepository != "" {
+			repo = createRequest.DockerRepository
+		} else {
+			repo = impl.ecrConfig.EcrPrefix + app.AppName
+		}
 
+		if store.RegistryType == dockerRegistryRepository.REGISTRYTYPE_ECR {
+			err := impl.ciCdPipelineOrchestrator.CreateEcrRepo(repo, store.AWSRegion, store.AWSAccessKeyId, store.AWSSecretAccessKey)
+			if err != nil {
+				impl.logger.Errorw("ecr repo creation failed while creating ci pipeline", "repo", repo, "err", err)
+				return nil, err
+			}
+		}
+		createRequest.DockerRepository = repo
+	}
 	//--ecr config	end
 	//-- template config start
 
@@ -1012,9 +1031,9 @@ func (impl PipelineBuilderImpl) CreateCiPipeline(createRequest *bean.CiConfigReq
 	}
 	buildConfig := createRequest.CiBuildConfig
 	ciTemplate := &pipelineConfig.CiTemplate{
-		DockerRegistryId: createRequest.DockerRegistry,
-		DockerRepository: createRequest.DockerRepository,
-		GitMaterialId:    buildConfig.GitMaterialId,
+		//DockerRegistryId: createRequest.DockerRegistry,
+		//DockerRepository: createRequest.DockerRepository,
+		GitMaterialId: buildConfig.GitMaterialId,
 		//DockerfilePath:    createRequest.DockerBuildConfig.DockerfilePath,
 		//Args:              string(argByte),
 		//TargetPlatform:    createRequest.DockerBuildConfig.TargetPlatform,
@@ -1026,6 +1045,10 @@ func (impl PipelineBuilderImpl) CreateCiPipeline(createRequest *bean.CiConfigReq
 		BeforeDockerBuild: string(beforeByte),
 		AuditLog:          sql.AuditLog{CreatedOn: time.Now(), UpdatedOn: time.Now(), CreatedBy: createRequest.UserId, UpdatedBy: createRequest.UserId},
 	}
+	if !createRequest.IsJob {
+		ciTemplate.DockerRegistryId = &createRequest.DockerRegistry
+		ciTemplate.DockerRepository = createRequest.DockerRepository
+	}
 
 	ciTemplateBean := &bean3.CiTemplateBean{
 		CiTemplate:    ciTemplate,
@@ -2716,6 +2739,30 @@ func (impl PipelineBuilderImpl) GetArtifactsForCdStage(cdPipelineId int, parentI
 			return ciArtifacts[i].Id > ciArtifacts[j].Id
 		})
 	}
+	for i, artifact := range ciArtifacts {
+		artifactBean, err := impl.ciArtifactRepository.Get(artifact.Id)
+		if err != nil {
+			impl.logger.Errorw("error in getting artifactBean for one ci_artifact", "err", err, "parentStage", parentType, "stage", stage)
+			return ciArtifactsResponse, err
+		}
+		var ciWorkflow *pipelineConfig.CiWorkflow
+		if artifactBean.ParentCiArtifact != 0 {
+			ciWorkflow, err = impl.ciWorkflowRepository.FindLastTriggeredWorkflowByArtifactId(artifactBean.ParentCiArtifact)
+			if err != nil {
+				impl.logger.Errorw("error in getting ci_workflow for artifacts", "err", err, "artifact", artifact, "parentStage", parentType, "stage", stage)
+				return ciArtifactsResponse, err
+			}
+		} else {
+			ciWorkflow, err = impl.ciWorkflowRepository.FindById(*artifactBean.WorkflowId)
+			if err != nil {
+				impl.logger.Errorw("error in getting ci_workflow for artifacts", "err", err, "artifact", artifact, "parentStage", parentType, "stage", stage)
+				return ciArtifactsResponse, err
+			}
+		}
+		ciArtifacts[i].CiConfigureSourceType = ciWorkflow.GitTriggers[ciWorkflow.CiPipelineId].CiConfigureSourceType
+		ciArtifacts[i].CiConfigureSourceValue = ciWorkflow.GitTriggers[ciWorkflow.CiPipelineId].CiConfigureSourceValue
+	}
+
 	ciArtifactsResponse.CdPipelineId = cdPipelineId
 	ciArtifactsResponse.LatestWfArtifactId = latestWfArtifactId
 	ciArtifactsResponse.LatestWfArtifactStatus = latestWfArtifactStatus
@@ -3286,21 +3333,25 @@ func (impl PipelineBuilderImpl) GetCiPipelineById(pipelineId int) (ciPipeline *b
 	return ciPipeline, err
 }
 
-func (impl PipelineBuilderImpl) FindAllMatchesByAppName(appName string) ([]*AppBean, error) {
+func (impl PipelineBuilderImpl) FindAllMatchesByAppName(appName string, appType helper.AppType) ([]*AppBean, error) {
 	var appsRes []*AppBean
 	var apps []*app2.App
 	var err error
 	if len(appName) == 0 {
 		apps, err = impl.appRepo.FindAll()
 	} else {
-		apps, err = impl.appRepo.FindAllMatchesByAppName(appName)
+		apps, err = impl.appRepo.FindAllMatchesByAppName(appName, appType)
 	}
 	if err != nil {
 		impl.logger.Errorw("error while fetching app", "err", err)
 		return nil, err
 	}
 	for _, app := range apps {
-		appsRes = append(appsRes, &AppBean{Id: app.Id, Name: app.AppName})
+		name := app.AppName
+		if appType == helper.Job {
+			name = app.DisplayName
+		}
+		appsRes = append(appsRes, &AppBean{Id: app.Id, Name: name})
 	}
 	return appsRes, err
 }
diff --git a/pkg/pipeline/PipelineStageService.go b/pkg/pipeline/PipelineStageService.go
index 520cf92f6..bb34cd720 100644
--- a/pkg/pipeline/PipelineStageService.go
+++ b/pkg/pipeline/PipelineStageService.go
@@ -240,7 +240,7 @@ func (impl *PipelineStageServiceImpl) BuildVariableAndConditionDataByStepIdDeepC
 	return inputVariablesDto, outputVariablesDto, conditionsDto, nil
 }
 
-//GetCiPipelineStageData and related methods starts
+// GetCiPipelineStageData and related methods starts
 func (impl *PipelineStageServiceImpl) GetCiPipelineStageData(ciPipelineId int) (*bean.PipelineStageDto, *bean.PipelineStageDto, error) {
 
 	//getting all stages by ci pipeline id
@@ -452,7 +452,7 @@ func (impl *PipelineStageServiceImpl) BuildVariableAndConditionDataByStepId(step
 
 //GetCiPipelineStageData and related methods ends
 
-//CreateCiStage and related methods starts
+// CreateCiStage and related methods starts
 func (impl *PipelineStageServiceImpl) CreateCiStage(stageReq *bean.PipelineStageDto, stageType repository.PipelineStageType, ciPipelineId int, userId int32) error {
 	stage := &repository.PipelineStage{
 		Name:         stageReq.Name,
@@ -805,7 +805,7 @@ func (impl *PipelineStageServiceImpl) CreateConditionsEntryInDb(stepId int, cond
 
 //CreateCiStage and related methods ends
 
-//UpdateCiStage and related methods starts
+// UpdateCiStage and related methods starts
 func (impl *PipelineStageServiceImpl) UpdateCiStage(stageReq *bean.PipelineStageDto, stageType repository.PipelineStageType, ciPipelineId int, userId int32) error {
 	//getting stage by stageType and ciPipelineId
 	stageOld, err := impl.pipelineStageRepository.GetCiStageByCiPipelineIdAndStageType(ciPipelineId, stageType)
@@ -1341,7 +1341,7 @@ func (impl *PipelineStageServiceImpl) UpdatePipelineStageStepConditions(stepId i
 
 //UpdateCiStage and related methods ends
 
-//DeleteCiStage and related methods starts
+// DeleteCiStage and related methods starts
 func (impl *PipelineStageServiceImpl) DeleteCiStage(stageReq *bean.PipelineStageDto, userId int32, tx *pg.Tx) error {
 	//marking stage deleted
 	err := impl.pipelineStageRepository.MarkCiStageDeletedById(stageReq.Id, userId, tx)
@@ -1416,7 +1416,7 @@ func (impl *PipelineStageServiceImpl) DeleteCiStage(stageReq *bean.PipelineStage
 
 //DeleteCiStage and related methods starts
 
-//BuildPrePostAndRefPluginStepsDataForWfRequest and related methods starts
+// BuildPrePostAndRefPluginStepsDataForWfRequest and related methods starts
 func (impl *PipelineStageServiceImpl) BuildPrePostAndRefPluginStepsDataForWfRequest(ciPipelineId int) ([]*bean.StepObject, []*bean.StepObject, []*bean.RefPluginObject, error) {
 	//get all stages By ciPipelineId
 	ciStages, err := impl.pipelineStageRepository.GetAllCiStagesByCiPipelineId(ciPipelineId)
diff --git a/pkg/pipeline/WebhookService.go b/pkg/pipeline/WebhookService.go
index db2b81611..cd918fc49 100644
--- a/pkg/pipeline/WebhookService.go
+++ b/pkg/pipeline/WebhookService.go
@@ -38,13 +38,14 @@ import (
 )
 
 type CiArtifactWebhookRequest struct {
-	Image        string          `json:"image"`
-	ImageDigest  string          `json:"imageDigest"`
-	MaterialInfo json.RawMessage `json:"materialInfo"`
-	DataSource   string          `json:"dataSource"`
-	PipelineName string          `json:"pipelineName"`
-	WorkflowId   *int            `json:"workflowId"`
-	UserId       int32           `json:"userId"`
+	Image              string          `json:"image"`
+	ImageDigest        string          `json:"imageDigest"`
+	MaterialInfo       json.RawMessage `json:"materialInfo"`
+	DataSource         string          `json:"dataSource"`
+	PipelineName       string          `json:"pipelineName"`
+	WorkflowId         *int            `json:"workflowId"`
+	UserId             int32           `json:"userId"`
+	IsArtifactUploaded bool            `json:"isArtifactUploaded"`
 }
 
 type WebhookService interface {
@@ -154,15 +155,16 @@ func (impl WebhookServiceImpl) HandleCiSuccessEvent(ciPipelineId int, request *C
 	}
 	materialJson = dst.Bytes()
 	artifact := &repository.CiArtifact{
-		Image:        request.Image,
-		ImageDigest:  request.ImageDigest,
-		MaterialInfo: string(materialJson),
-		DataSource:   request.DataSource,
-		PipelineId:   pipeline.Id,
-		WorkflowId:   request.WorkflowId,
-		ScanEnabled:  pipeline.ScanEnabled,
-		Scanned:      false,
-		AuditLog:     sql.AuditLog{CreatedBy: request.UserId, UpdatedBy: request.UserId, CreatedOn: time.Now(), UpdatedOn: time.Now()},
+		Image:              request.Image,
+		ImageDigest:        request.ImageDigest,
+		MaterialInfo:       string(materialJson),
+		DataSource:         request.DataSource,
+		PipelineId:         pipeline.Id,
+		WorkflowId:         request.WorkflowId,
+		ScanEnabled:        pipeline.ScanEnabled,
+		Scanned:            false,
+		IsArtifactUploaded: request.IsArtifactUploaded,
+		AuditLog:           sql.AuditLog{CreatedBy: request.UserId, UpdatedBy: request.UserId, CreatedOn: time.Now(), UpdatedOn: time.Now()},
 	}
 	if pipeline.ScanEnabled {
 		artifact.Scanned = true
@@ -181,15 +183,16 @@ func (impl WebhookServiceImpl) HandleCiSuccessEvent(ciPipelineId int, request *C
 	var ciArtifactArr []*repository.CiArtifact
 	for _, ci := range childrenCi {
 		ciArtifact := &repository.CiArtifact{
-			Image:            request.Image,
-			ImageDigest:      request.ImageDigest,
-			MaterialInfo:     string(materialJson),
-			DataSource:       request.DataSource,
-			PipelineId:       ci.Id,
-			ParentCiArtifact: artifact.Id,
-			ScanEnabled:      ci.ScanEnabled,
-			Scanned:          false,
-			AuditLog:         sql.AuditLog{CreatedBy: request.UserId, UpdatedBy: request.UserId, CreatedOn: time.Now(), UpdatedOn: time.Now()},
+			Image:              request.Image,
+			ImageDigest:        request.ImageDigest,
+			MaterialInfo:       string(materialJson),
+			DataSource:         request.DataSource,
+			PipelineId:         ci.Id,
+			ParentCiArtifact:   artifact.Id,
+			ScanEnabled:        ci.ScanEnabled,
+			Scanned:            false,
+			IsArtifactUploaded: request.IsArtifactUploaded,
+			AuditLog:           sql.AuditLog{CreatedBy: request.UserId, UpdatedBy: request.UserId, CreatedOn: time.Now(), UpdatedOn: time.Now()},
 		}
 		if ci.ScanEnabled {
 			ciArtifact.Scanned = true
@@ -261,6 +264,7 @@ func (impl WebhookServiceImpl) HandleExternalCiWebhook(externalCiId int, request
 		ExternalCiPipelineId: externalCiId,
 		ScanEnabled:          false,
 		Scanned:              false,
+		IsArtifactUploaded:   request.IsArtifactUploaded,
 		AuditLog:             sql.AuditLog{CreatedBy: request.UserId, UpdatedBy: request.UserId, CreatedOn: time.Now(), UpdatedOn: time.Now()},
 	}
 	if err = impl.ciArtifactRepository.Save(artifact); err != nil {
diff --git a/pkg/pipeline/WorkflowDagExecutor.go b/pkg/pipeline/WorkflowDagExecutor.go
index c87db8df2..833677075 100644
--- a/pkg/pipeline/WorkflowDagExecutor.go
+++ b/pkg/pipeline/WorkflowDagExecutor.go
@@ -1037,7 +1037,9 @@ func (impl *WorkflowDagExecutorImpl) TriggerDeployment(cdWf *pipelineConfig.CdWo
 	if err != nil {
 		return err
 	}
-
+	runner.CdWorkflow = &pipelineConfig.CdWorkflow{
+		Pipeline: pipeline,
+	}
 	// creating cd pipeline status timeline for deployment initialisation
 	timeline := &pipelineConfig.PipelineStatusTimeline{
 		CdWorkflowRunnerId: runner.Id,
@@ -1380,6 +1382,9 @@ func (impl *WorkflowDagExecutorImpl) ManualCdTrigger(overrideRequest *bean.Value
 			impl.logger.Errorw("err", "err", err)
 			return 0, err
 		}
+		runner.CdWorkflow = &pipelineConfig.CdWorkflow{
+			Pipeline: cdPipeline,
+		}
 		overrideRequest.CdWorkflowId = cdWorkflowId
 		// creating cd pipeline status timeline for deployment initialisation
 		timeline := &pipelineConfig.PipelineStatusTimeline{
@@ -1452,6 +1457,9 @@ func (impl *WorkflowDagExecutorImpl) ManualCdTrigger(overrideRequest *bean.Value
 				impl.logger.Errorw("err", "err", err)
 				return 0, err
 			}
+			runner.CdWorkflow = &pipelineConfig.CdWorkflow{
+				Pipeline: cdPipeline,
+			}
 			cdMetrics := util4.CDMetrics{
 				AppName:         runner.CdWorkflow.Pipeline.DeploymentAppName,
 				Status:          runner.Status,
diff --git a/pkg/pipeline/WorkflowService.go b/pkg/pipeline/WorkflowService.go
index 96b2230a3..12e659858 100644
--- a/pkg/pipeline/WorkflowService.go
+++ b/pkg/pipeline/WorkflowService.go
@@ -239,161 +239,29 @@ func (impl *WorkflowServiceImpl) SubmitWorkflow(workflowRequest *WorkflowRequest
 	reqMem := impl.ciConfig.ReqMem
 	ttl := int32(impl.ciConfig.BuildLogTTLValue)
 
+	entryPoint := CI_WORKFLOW_NAME // template name from where worklow execution will start
 	//getting all cm/cs to be used by default
-	globalCmCsConfigs, err := impl.globalCMCSService.FindAllActive()
+	globalCmCsConfigs, err := impl.globalCMCSService.FindAllActiveByPipelineType(repository.PIPELINE_TYPE_CI)
 	if err != nil {
 		impl.Logger.Errorw("error in getting all global cm/cs config", "err", err)
 		return nil, err
 	}
-	for i := range globalCmCsConfigs {
-		globalCmCsConfigs[i].Name = globalCmCsConfigs[i].Name + "-" + strconv.Itoa(workflowRequest.WorkflowId)
-	}
-
-	configsMapping := make(map[string]string)
-	secretsMapping := make(map[string]string)
-
-	var volumes []v12.Volume
-	var steps []v1alpha1.ParallelSteps
-
-	cmIndex := 0
-	csIndex := 0
-
-	entryPoint := CI_WORKFLOW_NAME
 	if len(globalCmCsConfigs) > 0 {
 		entryPoint = CI_WORKFLOW_WITH_STAGES
-		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 nil, err
-				}
-				configsMapping[config.Name] = string(cmJson)
-
-				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-" + strconv.Itoa(cmIndex),
-							Template: "cm-" + strconv.Itoa(cmIndex),
-						},
-					},
-				})
-				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 nil, err
-				}
-				secretsMapping[config.Name] = string(secretJson)
-				if config.Type == repository.VOLUME_CONFIG {
-					volumes = append(volumes, v12.Volume{
-						Name: config.Name + "-vol",
-						VolumeSource: v12.VolumeSource{
-							Secret: &v12.SecretVolumeSource{
-								SecretName: config.Name,
-							},
-						},
-					})
-				}
+	}
+	for i := range globalCmCsConfigs {
+		globalCmCsConfigs[i].Name = strings.ToLower(globalCmCsConfigs[i].Name) + "-" + strconv.Itoa(workflowRequest.WorkflowId) + "-" + CI_WORKFLOW_NAME
+	}
 
-				steps = append(steps, v1alpha1.ParallelSteps{
-					Steps: []v1alpha1.WorkflowStep{
-						{
-							Name:     "create-env-sec-" + strconv.Itoa(csIndex),
-							Template: "sec-" + strconv.Itoa(csIndex),
-						},
-					},
-				})
-				csIndex++
-			}
+	steps := make([]v1alpha1.ParallelSteps, 0)
+	volumes := make([]v12.Volume, 0)
+	templates := make([]v1alpha1.Template, 0)
 
-		}
+	err = impl.globalCMCSService.AddTemplatesForGlobalSecretsInWorkflowTemplate(globalCmCsConfigs, &steps, &volumes, &templates)
+	if err != nil {
+		impl.Logger.Errorw("error in creating templates for global secrets", "err", err)
 	}
 
-	var templates []v1alpha1.Template
-	cmIndex = 0
-	csIndex = 0
-	if len(configsMapping) > 0 {
-		for _, manifest := range configsMapping {
-			templates = append(templates, v1alpha1.Template{
-				Name: "cm-" + strconv.Itoa(cmIndex),
-				Resource: &v1alpha1.ResourceTemplate{
-					Action:            "create",
-					SetOwnerReference: true,
-					Manifest:          manifest,
-				},
-			})
-			cmIndex++
-		}
-	}
-	if len(secretsMapping) > 0 {
-		for _, manifest := range secretsMapping {
-			templates = append(templates, v1alpha1.Template{
-				Name: "sec-" + strconv.Itoa(csIndex),
-				Resource: &v1alpha1.ResourceTemplate{
-					Action:            "create",
-					SetOwnerReference: true,
-					Manifest:          manifest,
-				},
-			})
-			csIndex++
-		}
-	}
 	steps = append(steps, v1alpha1.ParallelSteps{
 		Steps: []v1alpha1.WorkflowStep{
 			{
diff --git a/pkg/pipeline/history/repository/ciTemplateHistoryRepository.go b/pkg/pipeline/history/repository/ciTemplateHistoryRepository.go
index 07f53b367..aafc0aed9 100644
--- a/pkg/pipeline/history/repository/ciTemplateHistoryRepository.go
+++ b/pkg/pipeline/history/repository/ciTemplateHistoryRepository.go
@@ -13,7 +13,7 @@ type CiTemplateHistory struct {
 	Id                 int      `sql:"id,pk"`
 	CiTemplateId       int      `sql:"ci_template_id"`
 	AppId              int      `sql:"app_id"`             //foreign key of app
-	DockerRegistryId   string   `sql:"docker_registry_id"` //foreign key of registry
+	DockerRegistryId   *string  `sql:"docker_registry_id"` //foreign key of registry
 	DockerRepository   string   `sql:"docker_repository"`
 	DockerfilePath     string   `sql:"dockerfile_path"`
 	Args               string   `sql:"args"` //json string format of map[string]string
diff --git a/pkg/security/ImageScanService.go b/pkg/security/ImageScanService.go
index 83a9d7806..014497b77 100644
--- a/pkg/security/ImageScanService.go
+++ b/pkg/security/ImageScanService.go
@@ -18,7 +18,8 @@
 package security
 
 import (
-	"github.com/devtron-labs/devtron/internal/sql/repository/app"
+	repository1 "github.com/devtron-labs/devtron/internal/sql/repository/app"
+	"github.com/devtron-labs/devtron/internal/sql/repository/helper"
 	repository2 "github.com/devtron-labs/devtron/pkg/team"
 	"time"
 
@@ -48,7 +49,7 @@ type ImageScanServiceImpl struct {
 	imageScanDeployInfoRepository security.ImageScanDeployInfoRepository
 	userService                   user.UserService
 	teamRepository                repository2.TeamRepository
-	appRepository                 app.AppRepository
+	appRepository                 repository1.AppRepository
 	envService                    cluster.EnvironmentService
 	ciArtifactRepository          repository.CiArtifactRepository
 	policyService                 PolicyService
@@ -123,7 +124,7 @@ func NewImageScanServiceImpl(Logger *zap.SugaredLogger, scanHistoryRepository se
 	scanResultRepository security.ImageScanResultRepository, scanObjectMetaRepository security.ImageScanObjectMetaRepository,
 	cveStoreRepository security.CveStoreRepository, imageScanDeployInfoRepository security.ImageScanDeployInfoRepository,
 	userService user.UserService, teamRepository repository2.TeamRepository,
-	appRepository app.AppRepository,
+	appRepository repository1.AppRepository,
 	envService cluster.EnvironmentService, ciArtifactRepository repository.CiArtifactRepository, policyService PolicyService,
 	pipelineRepository pipelineConfig.PipelineRepository, ciPipelineRepository pipelineConfig.CiPipelineRepository) *ImageScanServiceImpl {
 	return &ImageScanServiceImpl{Logger: Logger, scanHistoryRepository: scanHistoryRepository, scanResultRepository: scanResultRepository,
@@ -409,7 +410,7 @@ func (impl ImageScanServiceImpl) FetchExecutionDetailResult(request *ImageScanRe
 		imageScanResponse.EnvId = request.EnvId
 		imageScanResponse.EnvName = env.Environment
 
-		blockCveList, err := impl.policyService.GetBlockedCVEList(cveStores, env.ClusterId, env.Id, request.AppId, app.AppStore)
+		blockCveList, err := impl.policyService.GetBlockedCVEList(cveStores, env.ClusterId, env.Id, request.AppId, app.AppType == helper.ChartStoreApp)
 		if err != nil {
 			impl.Logger.Errorw("error while fetching env", "err", err)
 			//return nil, err
diff --git a/pkg/security/policyService.go b/pkg/security/policyService.go
index 0b2591ae9..8d2e3ace4 100644
--- a/pkg/security/policyService.go
+++ b/pkg/security/policyService.go
@@ -21,7 +21,8 @@ import (
 	"bytes"
 	"encoding/json"
 	"fmt"
-	"github.com/devtron-labs/devtron/internal/sql/repository/app"
+	repository1 "github.com/devtron-labs/devtron/internal/sql/repository/app"
+	"github.com/devtron-labs/devtron/internal/sql/repository/helper"
 	"github.com/devtron-labs/devtron/pkg/sql"
 	"net/http"
 	"strings"
@@ -52,7 +53,7 @@ type PolicyService interface {
 type PolicyServiceImpl struct {
 	environmentService            cluster.EnvironmentService
 	logger                        *zap.SugaredLogger
-	apRepository                  app.AppRepository
+	apRepository                  repository1.AppRepository
 	pipelineOverride              chartConfig.PipelineOverrideRepository
 	cvePolicyRepository           security.CvePolicyRepository
 	clusterService                cluster.ClusterService
@@ -70,7 +71,7 @@ type PolicyServiceImpl struct {
 
 func NewPolicyServiceImpl(environmentService cluster.EnvironmentService,
 	logger *zap.SugaredLogger,
-	apRepository app.AppRepository,
+	apRepository repository1.AppRepository,
 	pipelineOverride chartConfig.PipelineOverrideRepository,
 	cvePolicyRepository security.CvePolicyRepository,
 	clusterService cluster.ClusterService,
@@ -190,7 +191,7 @@ func (impl *PolicyServiceImpl) VerifyImage(verifyImageRequest *VerifyImageReques
 		return nil, err
 	} else if app != nil {
 		appId = app.Id
-		isAppStore = app.AppStore
+		isAppStore = app.AppType == helper.ChartStoreApp
 	} else {
 		//np app do nothing
 	}
@@ -327,7 +328,7 @@ func (impl *PolicyServiceImpl) VerifyImage(verifyImageRequest *VerifyImageReques
 	return imageBlockedCves, nil
 }
 
-//image(cve), appId, envId
+// image(cve), appId, envId
 func (impl *PolicyServiceImpl) enforceCvePolicy(cves []*security.CveStore, cvePolicy map[string]*security.CvePolicy, severityPolicy map[security.Severity]*security.CvePolicy) (blockedCVE []*security.CveStore) {
 
 	for _, cve := range cves {
@@ -497,8 +498,8 @@ func (impl *PolicyServiceImpl) SavePolicy(request bean.CreateVulnerabilityPolicy
 }
 
 /*
-  1. policy id
-  2. action
+1. policy id
+2. action
 */
 func (impl *PolicyServiceImpl) UpdatePolicy(updatePolicyParams bean.UpdatePolicyParams, userId int32) (*bean.IdVulnerabilityPolicyResult, error) {
 	policyAction, err := impl.parsePolicyAction(updatePolicyParams.Action)
@@ -550,13 +551,12 @@ func (impl *PolicyServiceImpl) DeletePolicy(id int, userId int32) (*bean.IdVulne
 }
 
 /*
- global: na
- cluster: clusterId
- environment: environmentId
- application : appId, envId
+	global: na
+	cluster: clusterId
+	environment: environmentId
+	application : appId, envId
 
 res:
-
 */
 func (impl *PolicyServiceImpl) GetPolicies(policyLevel security.PolicyLevel, clusterId, environmentId, appId int) (*bean.GetVulnerabilityPolicyResult, error) {
 
diff --git a/pkg/sql/connection.go b/pkg/sql/connection.go
index 0e5e97afc..fe9dc52aa 100644
--- a/pkg/sql/connection.go
+++ b/pkg/sql/connection.go
@@ -18,6 +18,7 @@
 package sql
 
 import (
+	"github.com/devtron-labs/devtron/internal/middleware"
 	"go.uber.org/zap"
 	"reflect"
 	"time"
@@ -35,6 +36,7 @@ type Config struct {
 	ApplicationName        string `env:"APP" envDefault:"orchestrator"`
 	LogQuery               bool   `env:"PG_LOG_QUERY" envDefault:"true"`
 	LogAllQuery            bool   `env:"PG_LOG_ALL_QUERY" envDefault:"false"`
+	ExportPromMetrics      bool   `env:"PG_EXPORT_PROM_METRICS" envDefault:"false"`
 	QueryDurationThreshold int64  `env:"PG_QUERY_DUR_THRESHOLD" envDefault:"5000"`
 }
 
@@ -65,25 +67,28 @@ func NewDbConnection(cfg *Config, logger *zap.SugaredLogger) (*pg.DB, error) {
 	}
 
 	//--------------
-	if cfg.LogQuery || cfg.LogAllQuery {
+	dbConnection.OnQueryProcessed(func(event *pg.QueryProcessedEvent) {
+		queryDuration := time.Since(event.StartTime)
 
-		dbConnection.OnQueryProcessed(func(event *pg.QueryProcessedEvent) {
-			query, err := event.FormattedQuery()
-			if err != nil {
-				logger.Errorw("Error formatting query",
-					"err", err)
-				return
-			}
+		// Expose prom metrics
+		if cfg.ExportPromMetrics {
+			middleware.PgQueryDuration.WithLabelValues("value").Observe(queryDuration.Seconds())
+		}
 
-			queryDuration := time.Since(event.StartTime)
+		query, err := event.FormattedQuery()
+		if err != nil {
+			logger.Errorw("Error formatting query",
+				"err", err)
+			return
+		}
 
-			if cfg.LogAllQuery || queryDuration.Milliseconds() > cfg.QueryDurationThreshold {
-				logger.Debugw("query time",
-					"duration", queryDuration.Seconds(),
-					"query", query)
-			}
-		})
-	}
+		// Log pg query if enabled
+		if cfg.LogAllQuery || (cfg.LogQuery && queryDuration.Milliseconds() > cfg.QueryDurationThreshold) {
+			logger.Debugw("query time",
+				"duration", queryDuration.Seconds(),
+				"query", query)
+		}
+	})
 	return dbConnection, err
 }
 
diff --git a/scripts/sql/121_alter_global_config.down.sql b/scripts/sql/121_alter_global_config.down.sql
new file mode 100644
index 000000000..8d41145ef
--- /dev/null
+++ b/scripts/sql/121_alter_global_config.down.sql
@@ -0,0 +1,1 @@
+ALTER TABLE global_cm_cs DROP COLUMN secret_ingestion_for;
\ No newline at end of file
diff --git a/scripts/sql/121_alter_global_config.up.sql b/scripts/sql/121_alter_global_config.up.sql
new file mode 100644
index 000000000..ebccf063b
--- /dev/null
+++ b/scripts/sql/121_alter_global_config.up.sql
@@ -0,0 +1,3 @@
+ALTER table global_cm_cs ADD secret_ingestion_for VARCHAR(50);
+--setting type as CI/CD because secrets until this release should be available in both CI and CD pipelines
+UPDATE global_cm_cs SET secret_ingestion_for='CI/CD';
\ No newline at end of file
diff --git a/scripts/sql/122_jobs.down.sql b/scripts/sql/122_jobs.down.sql
new file mode 100644
index 000000000..2b4a77e8e
--- /dev/null
+++ b/scripts/sql/122_jobs.down.sql
@@ -0,0 +1,16 @@
+UPDATE ci_pipeline_material SET  active = false FROM git_material JOIN app ON app.id = git_material.app_id WHERE app.app_type = 2 AND ci_pipeline_material.git_material_id = git_material.id;
+
+UPDATE ci_pipeline SET active = false WHERE app_id IN (SELECT id FROM app WHERE app_type = 2);
+
+UPDATE ci_template SET active = false WHERE app_id IN (SELECT id FROM app WHERE app_type = 2);
+
+UPDATE git_material SET active = false WHERE app_id IN (SELECT id FROM app WHERE app_type = 2);
+
+UPDATE app_workflow_mapping SET active = false FROM app_workflow JOIN app ON app_workflow.app_id = app.id WHERE app.app_type = 2 AND app_workflow_mapping.app_workflow_id = app_workflow.id;
+
+UPDATE app_workflow SET active = false WHERE app_id IN (SELECT id FROM app WHERE app_type = 2);
+
+UPDATE app SET active = false WHERE app_type = 2;
+
+
+
diff --git a/scripts/sql/122_jobs.up.sql b/scripts/sql/122_jobs.up.sql
new file mode 100644
index 000000000..32a68ee7e
--- /dev/null
+++ b/scripts/sql/122_jobs.up.sql
@@ -0,0 +1,8 @@
+ALTER TABLE app ADD COLUMN IF NOT EXISTS app_type integer not null DEFAULT 0;
+UPDATE app SET app_type = CASE WHEN app_store = false THEN 0 WHEN app_store = true THEN 1 ELSE app_type  END;
+ALTER TABLE app ADD COLUMN IF NOT EXISTS description text;
+ALTER TABLE app ADD COLUMN IF NOT EXISTS display_name varchar(250);
+ALTER TABLE ci_artifact ADD COLUMN IF NOT EXISTS is_artifact_uploaded BOOLEAN DEFAULT FALSE;
+UPDATE ci_artifact SET is_artifact_uploaded = true;
+
+
diff --git a/scripts/sql/1_insert.up.sql b/scripts/sql/1_insert.up.sql
index ffa7476e7..663fab9a7 100644
--- a/scripts/sql/1_insert.up.sql
+++ b/scripts/sql/1_insert.up.sql
@@ -5987,4 +5987,4 @@ INSERT INTO "public"."environment" ("id", "environment_name", "cluster_id", "act
 
 --
 -- PostgreSQL database dump complete
---
\ No newline at end of file
+--
diff --git a/specs/jobs.yaml b/specs/jobs.yaml
new file mode 100644
index 000000000..635136ad5
--- /dev/null
+++ b/specs/jobs.yaml
@@ -0,0 +1,194 @@
+openapi: "3.0.0"
+info:
+  title: Jobs
+  version: "1.0"
+paths:
+  /orchestrator/job:
+    post:
+      description: Create and clones a job
+      requestBody:
+        required: true
+        content:
+            application/json:
+              schema:
+                items:
+                  $ref: "#/components/schemas/CreateJob"
+      responses:
+        "200 OK":
+          description: Used to give response once a job is created
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/ActionResponse"
+  /orchestrator/job/list:
+    post:
+      description: Get the list of all the jobs by applying filter
+      requestBody:
+        required: true
+        content:
+          application/json:
+            schema:
+              items:
+                $ref: "#/components/schemas/JobList"
+      response:
+        description: Used to give response of list of jobs
+        content:
+          application/json:
+            schema:
+              items:
+                $ref: "#/components/schemas/JobListResponse"
+  /orchestrator/job/ci-pipeline/list/{jobId}:
+    get:
+      description: fetch details of job ci-pipelines for the overview page
+      parameters:
+        - name: jobId
+          in: path
+          required: true
+          schema:
+            type: integer
+#components
+components:
+  schemas:
+    CreateJob:
+      type: object
+      properties:
+         appName:
+           type: string
+           description: Used to give the name of the job
+           example: "my-job-1"
+         isJob:
+           type: boolean
+           description: States whether its a job or an app
+           example: true
+         teamId:
+           type: integer
+           description: Used to give team id
+           example: 1
+         templateId:
+           type: integer
+           description: Used to give the id of the job it wants to clone
+           example: 18
+         labels:
+           type: []label
+             label:
+               key:
+                 type: string
+                 example: "hello"
+               value:
+                 type: string
+                 example: "world"
+               propogate:
+                  type: bool
+                  example: false
+         description:
+           type: string
+           description: Used to give the description of the job once it is made.
+           example: "This is my first Job"
+    ActionResponse:
+      name: result
+      type: object
+      properties:
+        id:
+          type:  integer
+          description: Used to give the id of job once its created
+          example: 25
+        appName:
+          type: string
+          description: Used to give the name of job once its created
+          example: "my-job-1"
+        material:
+          type: []gitMaterial
+            gitMaterial:
+              name:
+                type: string
+              url:
+                type: string
+              id:
+                type: integer
+              gitProviderId:
+                type: integer
+              checkoutPath:
+                type: string
+              fetchSubmodules:
+                type: bool
+              isUsedInCiConfig:
+                type: bool
+          teamId:
+            type: integer
+            description: Used to give the team id
+            example: 1
+          templateId:
+            type: integer
+            description: Used to give the templateId
+            example: 0
+          description:
+            type: string
+            description: Used to give the description of the job once it is made.
+            example: "This is my first Job"
+          isJob:
+            type: boolean
+            description: used to tell whether it is a job or an app
+            example: true
+    JobList:
+      type: object
+      properties:
+        teams:
+          type: [] integer
+          description: used to give the project id
+          example: [1,2]
+        appStatuses:
+          type: [] string
+          description: used to give the filter of app ci-build status
+          example: ["Succeeded", "Starting"]
+        sortBy:
+          type: string
+          description: used to give the sort by constraint
+          example: "appNameSort"
+        sortOrder:
+          type: string
+          description: used to give the sort order
+          example: "ASC"
+        offset:
+          type: integer
+          description: used to give the number from which we want our job (if the offset is 20 means we want list of jobs from 20)
+          example: 0
+        size:
+          type: integer
+          description: used to give the number of jobs we want
+          example: 20
+
+    JobListResponse:
+      type: object
+      properties:
+        jobContainers:
+          type: [] jobContainer
+            jobContainer:
+              properties:
+                jobId:
+                  type: integer
+                jobName:
+                  type: string
+                description:
+                  type: string
+                ciPipelines:
+                  type: []jobCiPipeline
+                    jobCiPipeline:
+                      properties:
+                        ciPipelineId:
+                         type: integer
+                        status:
+                          type: string
+                        lastRunAt:
+                          type: time.Time
+                        lastSuccessAt:
+                          type: time.Time
+        jobCount:
+          type: integer
+
+
+
+
+
+
+
+
diff --git a/util/helper.go b/util/helper.go
index fa98b43c4..c1718d62c 100644
--- a/util/helper.go
+++ b/util/helper.go
@@ -45,6 +45,21 @@ type CDMetrics struct {
 	Time            float64
 }
 
+type CIMetrics struct {
+	CacheDownDuration  float64   `json:"cacheDownDuration"`
+	PreCiDuration      float64   `json:"preCiDuration"`
+	BuildDuration      float64   `json:"buildDuration"`
+	PostCiDuration     float64   `json:"postCiDuration"`
+	CacheUpDuration    float64   `json:"cacheUpDuration"`
+	TotalDuration      float64   `json:"totalDuration"`
+	CacheDownStartTime time.Time `json:"cacheDownStartTime"`
+	PreCiStartTime     time.Time `json:"preCiStart"`
+	BuildStartTime     time.Time `json:"buildStartTime"`
+	PostCiStartTime    time.Time `json:"postCiStartTime"`
+	CacheUpStartTime   time.Time `json:"cacheUpStartTime"`
+	TotalStartTime     time.Time `json:"totalStartTime"`
+}
+
 func ContainsString(list []string, element string) bool {
 	if len(list) == 0 {
 		return false
@@ -226,3 +241,20 @@ func TriggerCDMetrics(wfr CDMetrics, exposeCDMetrics bool) {
 		middleware.CdDuration.WithLabelValues(wfr.AppName, wfr.Status, wfr.EnvironmentName, wfr.DeploymentType).Observe(wfr.Time)
 	}
 }
+
+func TriggerCIMetrics(Metrics CIMetrics, exposeCIMetrics bool, PipelineName string, AppName string) {
+	if exposeCIMetrics {
+		middleware.CacheDownloadDuration.WithLabelValues(PipelineName, AppName).Observe(Metrics.CacheDownDuration)
+		middleware.CiDuration.WithLabelValues(PipelineName, AppName).Observe(Metrics.TotalDuration)
+		if Metrics.CacheUpDuration != 0 {
+			middleware.CacheUploadDuration.WithLabelValues(PipelineName, AppName).Observe(Metrics.CacheUpDuration)
+		}
+		if Metrics.PostCiDuration != 0 {
+			middleware.PostCiDuration.WithLabelValues(PipelineName, AppName).Observe(Metrics.PostCiDuration)
+		}
+		if Metrics.PreCiDuration != 0 {
+			middleware.PreCiDuration.WithLabelValues(PipelineName, AppName).Observe(Metrics.PreCiDuration)
+		}
+		middleware.BuildDuration.WithLabelValues(PipelineName, AppName).Observe(Metrics.BuildDuration)
+	}
+}
diff --git a/util/k8s/k8sCapacityService.go b/util/k8s/k8sCapacityService.go
index 5659c4e47..bace795ee 100644
--- a/util/k8s/k8sCapacityService.go
+++ b/util/k8s/k8sCapacityService.go
@@ -53,7 +53,7 @@ const (
 	KopsNodeGroupLabel  = "kops.k8s.io/instancegroup"
 )
 
-//TODO: add any new nodeGrouplabel in this array
+// TODO: add any new nodeGrouplabel in this array
 var NodeGroupLabels = [4]string{AWSNodeGroupLabel, AzureNodeGroupLabel, GcpNodeGroupLabel, KopsNodeGroupLabel}
 
 // below const set is used for pod delete status
diff --git a/wire_gen.go b/wire_gen.go
index b3667df75..ba2da806e 100644
--- a/wire_gen.go
+++ b/wire_gen.go
@@ -1,6 +1,6 @@
 // Code generated by Wire. DO NOT EDIT.
 
-//go:generate go run github.com/google/wire/cmd/wire
+//go:generate wire
 //go:build !wireinject
 // +build !wireinject
 
@@ -358,7 +358,9 @@ func InitializeApp() (*App, error) {
 	if err != nil {
 		return nil, err
 	}
-	cdWorkflowServiceImpl := pipeline.NewCdWorkflowServiceImpl(sugaredLogger, environmentRepositoryImpl, cdConfig, appServiceImpl)
+	globalCMCSRepositoryImpl := repository.NewGlobalCMCSRepositoryImpl(sugaredLogger, db)
+	globalCMCSServiceImpl := pipeline.NewGlobalCMCSServiceImpl(sugaredLogger, globalCMCSRepositoryImpl)
+	cdWorkflowServiceImpl := pipeline.NewCdWorkflowServiceImpl(sugaredLogger, environmentRepositoryImpl, cdConfig, appServiceImpl, globalCMCSServiceImpl)
 	materialRepositoryImpl := pipelineConfig.NewMaterialRepositoryImpl(db)
 	deploymentGroupRepositoryImpl := repository.NewDeploymentGroupRepositoryImpl(sugaredLogger, db)
 	cvePolicyRepositoryImpl := security.NewPolicyRepositoryImpl(db)
@@ -413,10 +415,8 @@ func InitializeApp() (*App, error) {
 	if err != nil {
 		return nil, err
 	}
-	pipelineBuilderImpl := pipeline.NewPipelineBuilderImpl(sugaredLogger, ciCdPipelineOrchestratorImpl, dockerArtifactStoreRepositoryImpl, materialRepositoryImpl, appRepositoryImpl, pipelineRepositoryImpl, propertiesConfigServiceImpl, ciTemplateRepositoryImpl, ciPipelineRepositoryImpl, applicationServiceClientImpl, chartRepositoryImpl, ciArtifactRepositoryImpl, ecrConfig, envConfigOverrideRepositoryImpl, environmentRepositoryImpl, pipelineConfigRepositoryImpl, utilMergeUtil, appWorkflowRepositoryImpl, ciConfig, cdWorkflowRepositoryImpl, appServiceImpl, imageScanResultRepositoryImpl, argoK8sClientImpl, gitFactory, attributesServiceImpl, acdAuthConfig, gitOpsConfigRepositoryImpl, pipelineStrategyHistoryServiceImpl, prePostCiScriptHistoryServiceImpl, prePostCdScriptHistoryServiceImpl, deploymentTemplateHistoryServiceImpl, appLevelMetricsRepositoryImpl, pipelineStageServiceImpl, chartRefRepositoryImpl, chartTemplateServiceImpl, chartServiceImpl, helmAppServiceImpl, deploymentGroupRepositoryImpl, ciPipelineMaterialRepositoryImpl, userServiceImpl, ciTemplateServiceImpl, ciTemplateOverrideRepositoryImpl, gitMaterialHistoryServiceImpl, ciTemplateHistoryServiceImpl, ciPipelineHistoryServiceImpl, globalStrategyMetadataRepositoryImpl, globalStrategyMetadataChartRefMappingRepositoryImpl, pipelineDeploymentServiceTypeConfig, appStatusRepositoryImpl, workflowDagExecutorImpl, enforcerUtilImpl, argoUserServiceImpl)
+	pipelineBuilderImpl := pipeline.NewPipelineBuilderImpl(sugaredLogger, ciCdPipelineOrchestratorImpl, dockerArtifactStoreRepositoryImpl, materialRepositoryImpl, appRepositoryImpl, pipelineRepositoryImpl, propertiesConfigServiceImpl, ciTemplateRepositoryImpl, ciPipelineRepositoryImpl, applicationServiceClientImpl, chartRepositoryImpl, ciArtifactRepositoryImpl, ecrConfig, envConfigOverrideRepositoryImpl, environmentRepositoryImpl, pipelineConfigRepositoryImpl, utilMergeUtil, appWorkflowRepositoryImpl, ciConfig, cdWorkflowRepositoryImpl, appServiceImpl, imageScanResultRepositoryImpl, argoK8sClientImpl, gitFactory, attributesServiceImpl, acdAuthConfig, gitOpsConfigRepositoryImpl, pipelineStrategyHistoryServiceImpl, prePostCiScriptHistoryServiceImpl, prePostCdScriptHistoryServiceImpl, deploymentTemplateHistoryServiceImpl, appLevelMetricsRepositoryImpl, pipelineStageServiceImpl, chartRefRepositoryImpl, chartTemplateServiceImpl, chartServiceImpl, helmAppServiceImpl, deploymentGroupRepositoryImpl, ciPipelineMaterialRepositoryImpl, userServiceImpl, ciTemplateServiceImpl, ciTemplateOverrideRepositoryImpl, gitMaterialHistoryServiceImpl, ciTemplateHistoryServiceImpl, ciPipelineHistoryServiceImpl, globalStrategyMetadataRepositoryImpl, globalStrategyMetadataChartRefMappingRepositoryImpl, pipelineDeploymentServiceTypeConfig, appStatusRepositoryImpl, workflowDagExecutorImpl, enforcerUtilImpl, argoUserServiceImpl, ciWorkflowRepositoryImpl)
 	dbMigrationServiceImpl := pipeline.NewDbMogrationService(sugaredLogger, dbMigrationConfigRepositoryImpl)
-	globalCMCSRepositoryImpl := repository.NewGlobalCMCSRepositoryImpl(sugaredLogger, db)
-	globalCMCSServiceImpl := pipeline.NewGlobalCMCSServiceImpl(sugaredLogger, globalCMCSRepositoryImpl)
 	workflowServiceImpl := pipeline.NewWorkflowServiceImpl(sugaredLogger, ciConfig, globalCMCSServiceImpl)
 	ciServiceImpl := pipeline.NewCiServiceImpl(sugaredLogger, workflowServiceImpl, ciPipelineMaterialRepositoryImpl, ciWorkflowRepositoryImpl, ciConfig, eventRESTClientImpl, eventSimpleFactoryImpl, mergeUtil, ciPipelineRepositoryImpl, prePostCiScriptHistoryServiceImpl, pipelineStageServiceImpl, userServiceImpl, ciTemplateServiceImpl, appCrudOperationServiceImpl)
 	ciLogServiceImpl := pipeline.NewCiLogServiceImpl(sugaredLogger, ciServiceImpl, ciConfig)
@@ -430,7 +430,7 @@ func InitializeApp() (*App, error) {
 	cdHandlerImpl := pipeline.NewCdHandlerImpl(sugaredLogger, cdConfig, userServiceImpl, cdWorkflowRepositoryImpl, cdWorkflowServiceImpl, ciLogServiceImpl, ciArtifactRepositoryImpl, ciPipelineMaterialRepositoryImpl, pipelineRepositoryImpl, environmentRepositoryImpl, ciWorkflowRepositoryImpl, ciConfig, helmAppServiceImpl, pipelineOverrideRepositoryImpl, workflowDagExecutorImpl, appListingServiceImpl, appListingRepositoryImpl, pipelineStatusTimelineRepositoryImpl, applicationServiceClientImpl, argoUserServiceImpl, deploymentEventHandlerImpl, eventRESTClientImpl, pipelineStatusTimelineResourcesServiceImpl, pipelineStatusSyncDetailServiceImpl, pipelineStatusTimelineServiceImpl, appServiceImpl, appStatusServiceImpl, enforcerUtilImpl)
 	configMapServiceImpl := pipeline.NewConfigMapServiceImpl(chartRepositoryImpl, sugaredLogger, chartRepoRepositoryImpl, utilMergeUtil, pipelineConfigRepositoryImpl, configMapRepositoryImpl, envConfigOverrideRepositoryImpl, commonServiceImpl, appRepositoryImpl, configMapHistoryServiceImpl)
 	appWorkflowServiceImpl := appWorkflow2.NewAppWorkflowServiceImpl(sugaredLogger, appWorkflowRepositoryImpl, ciCdPipelineOrchestratorImpl, ciPipelineRepositoryImpl, pipelineRepositoryImpl, enforcerUtilImpl)
-	appCloneServiceImpl := appClone.NewAppCloneServiceImpl(sugaredLogger, pipelineBuilderImpl, materialRepositoryImpl, chartServiceImpl, configMapServiceImpl, appWorkflowServiceImpl, appListingServiceImpl, propertiesConfigServiceImpl, ciTemplateOverrideRepositoryImpl, pipelineStageServiceImpl, ciTemplateServiceImpl)
+	appCloneServiceImpl := appClone.NewAppCloneServiceImpl(sugaredLogger, pipelineBuilderImpl, materialRepositoryImpl, chartServiceImpl, configMapServiceImpl, appWorkflowServiceImpl, appListingServiceImpl, propertiesConfigServiceImpl, ciTemplateOverrideRepositoryImpl, pipelineStageServiceImpl, ciTemplateServiceImpl, appRepositoryImpl)
 	imageScanObjectMetaRepositoryImpl := security.NewImageScanObjectMetaRepositoryImpl(db, sugaredLogger)
 	cveStoreRepositoryImpl := security.NewCveStoreRepositoryImpl(db, sugaredLogger)
 	policyServiceImpl := security2.NewPolicyServiceImpl(environmentServiceImpl, sugaredLogger, appRepositoryImpl, pipelineOverrideRepositoryImpl, cvePolicyRepositoryImpl, clusterServiceImplExtended, pipelineRepositoryImpl, imageScanResultRepositoryImpl, imageScanDeployInfoRepositoryImpl, imageScanObjectMetaRepositoryImpl, httpClient, ciArtifactRepositoryImpl, ciConfig, imageScanHistoryRepositoryImpl, cveStoreRepositoryImpl, ciTemplateRepositoryImpl)
@@ -466,7 +466,11 @@ func InitializeApp() (*App, error) {
 	gitWebhookServiceImpl := git.NewGitWebhookServiceImpl(sugaredLogger, ciHandlerImpl, gitWebhookRepositoryImpl)
 	gitWebhookRestHandlerImpl := restHandler.NewGitWebhookRestHandlerImpl(sugaredLogger, gitWebhookServiceImpl)
 	webhookServiceImpl := pipeline.NewWebhookServiceImpl(ciArtifactRepositoryImpl, sugaredLogger, ciPipelineRepositoryImpl, appServiceImpl, eventRESTClientImpl, eventSimpleFactoryImpl, ciWorkflowRepositoryImpl, workflowDagExecutorImpl, ciHandlerImpl)
-	ciEventHandlerImpl := pubsub.NewCiEventHandlerImpl(sugaredLogger, pubSubClientServiceImpl, webhookServiceImpl)
+	ciEventConfig, err := pubsub.GetCiEventConfig()
+	if err != nil {
+		return nil, err
+	}
+	ciEventHandlerImpl := pubsub.NewCiEventHandlerImpl(sugaredLogger, pubSubClientServiceImpl, webhookServiceImpl, ciEventConfig)
 	externalCiRestHandlerImpl := restHandler.NewExternalCiRestHandlerImpl(sugaredLogger, webhookServiceImpl, ciEventHandlerImpl, validate, userServiceImpl, enforcerImpl, enforcerUtilImpl)
 	pubSubClientRestHandlerImpl := restHandler.NewPubSubClientRestHandlerImpl(pubSubClientServiceImpl, sugaredLogger, cdConfig)
 	webhookRouterImpl := router.NewWebhookRouterImpl(gitWebhookRestHandlerImpl, pipelineConfigRestHandlerImpl, externalCiRestHandlerImpl, pubSubClientRestHandlerImpl)
@@ -678,13 +682,14 @@ func InitializeApp() (*App, error) {
 	}
 	userTerminalAccessRestHandlerImpl := terminal2.NewUserTerminalAccessRestHandlerImpl(sugaredLogger, userTerminalAccessServiceImpl, enforcerImpl, userServiceImpl, validate)
 	userTerminalAccessRouterImpl := terminal2.NewUserTerminalAccessRouterImpl(userTerminalAccessRestHandlerImpl)
+	jobRouterImpl := router.NewJobRouterImpl(pipelineConfigRestHandlerImpl, appListingRestHandlerImpl)
 	ciWorkflowStatusUpdateConfig, err := cron.GetCiWorkflowStatusUpdateConfig()
 	if err != nil {
 		return nil, err
 	}
 	ciStatusUpdateCronImpl := cron.NewCiStatusUpdateCronImpl(sugaredLogger, appServiceImpl, ciWorkflowStatusUpdateConfig, ciPipelineRepositoryImpl, ciHandlerImpl)
 	appGroupingRouterImpl := router.NewAppGroupingRouterImpl(pipelineConfigRestHandlerImpl, appWorkflowRestHandlerImpl)
-	muxRouter := router.NewMuxRouter(sugaredLogger, pipelineTriggerRouterImpl, pipelineConfigRouterImpl, migrateDbRouterImpl, appListingRouterImpl, environmentRouterImpl, clusterRouterImpl, webhookRouterImpl, userAuthRouterImpl, applicationRouterImpl, cdRouterImpl, projectManagementRouterImpl, gitProviderRouterImpl, gitHostRouterImpl, dockerRegRouterImpl, notificationRouterImpl, teamRouterImpl, gitWebhookHandlerImpl, workflowStatusUpdateHandlerImpl, applicationStatusHandlerImpl, ciEventHandlerImpl, pubSubClientServiceImpl, userRouterImpl, chartRefRouterImpl, configMapRouterImpl, appStoreRouterImpl, chartRepositoryRouterImpl, releaseMetricsRouterImpl, deploymentGroupRouterImpl, batchOperationRouterImpl, chartGroupRouterImpl, testSuitRouterImpl, imageScanRouterImpl, policyRouterImpl, gitOpsConfigRouterImpl, dashboardRouterImpl, attributesRouterImpl, userAttributesRouterImpl, commonRouterImpl, grafanaRouterImpl, ssoLoginRouterImpl, telemetryRouterImpl, telemetryEventClientImplExtended, bulkUpdateRouterImpl, webhookListenerRouterImpl, appRouterImpl, coreAppRouterImpl, helmAppRouterImpl, k8sApplicationRouterImpl, pProfRouterImpl, deploymentConfigRouterImpl, dashboardTelemetryRouterImpl, commonDeploymentRouterImpl, externalLinkRouterImpl, globalPluginRouterImpl, moduleRouterImpl, serverRouterImpl, apiTokenRouterImpl, cdApplicationStatusUpdateHandlerImpl, k8sCapacityRouterImpl, webhookHelmRouterImpl, globalCMCSRouterImpl, userTerminalAccessRouterImpl, ciStatusUpdateCronImpl, appGroupingRouterImpl)
+	muxRouter := router.NewMuxRouter(sugaredLogger, pipelineTriggerRouterImpl, pipelineConfigRouterImpl, migrateDbRouterImpl, appListingRouterImpl, environmentRouterImpl, clusterRouterImpl, webhookRouterImpl, userAuthRouterImpl, applicationRouterImpl, cdRouterImpl, projectManagementRouterImpl, gitProviderRouterImpl, gitHostRouterImpl, dockerRegRouterImpl, notificationRouterImpl, teamRouterImpl, gitWebhookHandlerImpl, workflowStatusUpdateHandlerImpl, applicationStatusHandlerImpl, ciEventHandlerImpl, pubSubClientServiceImpl, userRouterImpl, chartRefRouterImpl, configMapRouterImpl, appStoreRouterImpl, chartRepositoryRouterImpl, releaseMetricsRouterImpl, deploymentGroupRouterImpl, batchOperationRouterImpl, chartGroupRouterImpl, testSuitRouterImpl, imageScanRouterImpl, policyRouterImpl, gitOpsConfigRouterImpl, dashboardRouterImpl, attributesRouterImpl, userAttributesRouterImpl, commonRouterImpl, grafanaRouterImpl, ssoLoginRouterImpl, telemetryRouterImpl, telemetryEventClientImplExtended, bulkUpdateRouterImpl, webhookListenerRouterImpl, appRouterImpl, coreAppRouterImpl, helmAppRouterImpl, k8sApplicationRouterImpl, pProfRouterImpl, deploymentConfigRouterImpl, dashboardTelemetryRouterImpl, commonDeploymentRouterImpl, externalLinkRouterImpl, globalPluginRouterImpl, moduleRouterImpl, serverRouterImpl, apiTokenRouterImpl, cdApplicationStatusUpdateHandlerImpl, k8sCapacityRouterImpl, webhookHelmRouterImpl, globalCMCSRouterImpl, userTerminalAccessRouterImpl, jobRouterImpl, ciStatusUpdateCronImpl, appGroupingRouterImpl)
 	mainApp := NewApp(muxRouter, sugaredLogger, sseSSE, syncedEnforcer, db, pubSubClientServiceImpl, sessionManager, posthogClient)
 	return mainApp, nil
 }


Test patch:
diff --git a/pkg/chartRepo/ChartRepositoryService_test.go b/pkg/chartRepo/ChartRepositoryService_test.go
index 871b53f83..221b25823 100644
--- a/pkg/chartRepo/ChartRepositoryService_test.go
+++ b/pkg/chartRepo/ChartRepositoryService_test.go
@@ -1,63 +1,147 @@
 package chartRepo
 
 import (
+	"encoding/json"
+	"testing"
+	"github.com/devtron-labs/devtron/internal/sql/repository"
 	"github.com/devtron-labs/devtron/internal/util"
+	"github.com/ghodss/yaml"
+	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/mock"
-	"testing"
 )
 
 type ChartRepositoryServiceMock struct {
 	mock.Mock
 }
 
-func TestChartRepositoryServiceImpl_ValidateChartDetails(t *testing.T) {
-	sugaredLogger, _ := util.NewSugardLogger()
+func TestChartRepositoryServiceRemoveRepoData(t *testing.T) {
+	sugaredLogger, err := util.NewSugardLogger()
+	assert.Nil(t, err)
+
 	impl := &ChartRepositoryServiceImpl{
-		logger:         sugaredLogger,
-		repoRepository: new(ChartRepoRepositoryImplMock),
-		K8sUtil:        nil,
-		clusterService: new(ClusterServiceImplMock),
-		aCDAuthConfig:  nil,
-		client:         nil,
+		logger: sugaredLogger,
 	}
+	t.Run("Invalid JSON byte array", func(t *testing.T) {
+		data := map[string]string{
+			"helm.repositories": "invalid json",
+		}
+		_, err := impl.removeRepoData(data, "test-repo")
+		if err == nil {
+			t.Errorf("Expected an error but got nil")
+		}
+	})
+
+	t.Run("Error in unmarshal helmRepositories", func(t *testing.T) {
+		data := map[string]string{
+			"helm.repositories": "- name: test-1\n  type: helm\n  url: https://localhost\n- name: test-repo\n  type: helm\n  url: https://localhost\n- name: test-2\n  type: helm\n  url: https://localhost\n",
+		}
+		_, err := impl.removeRepoData(data, "test-repo")
+		if err == nil {
+			t.Errorf("Expected an error but got nil")
+		}
+	})
+
+	t.Run("Error in unmarshal repositories", func(t *testing.T) {
+		data := map[string]string{
+			"helm.repositories": "null\n",
+			"repositories":      "invalid json",
+		}
+		_, err := impl.removeRepoData(data, "test-repo")
+		if err == nil {
+			t.Errorf("Expected an error but got nil")
+		}
+	})
+
+	t.Run("Repository is found and removed from repositories", func(t *testing.T) {
+		data := map[string]string{
+			"helm.repositories": "null\n",
+			"repositories":      "- name: test-1\n  type: helm\n  url: https://localhost\n- name: test-repo\n  type: helm\n  url: https://localhost\n- name: test-2\n  type: helm\n  url: https://localhost\n",
+			"dex.config":        "",
+		}
+		expected := map[string]string{
+			"helm.repositories": "null\n",
+			"repositories":      "- name: test-1\n  type: helm\n  url: https://localhost\n- name: test-2\n  type: helm\n  url: https://localhost\n",
+			"dex.config":        "",
+		}
+		result, err := impl.removeRepoData(data, "test-repo")
+		if err != nil {
+			t.Errorf("Unexpected error: %v", err)
+		}
+		if !assert.Equal(t, result, expected) {
+			t.Errorf("Expected %v, but got %v", expected, result)
+		}
+	})
+
+	t.Run("Repository is not found", func(t *testing.T) {
+		data := map[string]string{
+			"helm.repositories": "null\n",
+			"repositories":      "- name: test-1\n  type: helm\n  url: https://localhost\n- name: test-2\n  type: helm\n  url: https://localhost\n",
+		}
+		_, err := impl.removeRepoData(data, "test-repo")
+		if err == nil {
+			t.Errorf("Expected an error but got nil")
+		}
+	})
+}
 
-	type args struct {
-		FileName     string
-		chartVersion string
+func TestUpdateRepository_NewRepository(t *testing.T) {
+	// setup
+	sugaredLogger, err := util.NewSugardLogger()
+	assert.Nil(t, err)
+	s := ChartRepositoryServiceImpl{logger: sugaredLogger}
+	req := &ChartRepoDto{
+		Name:     "myrepo2",
+		Url:      "https://github.com/devtron/myrepo2/",
+		AuthMode: repository.AUTH_MODE_USERNAME_PASSWORD,
+		UserName: "myuser",
+		Password: "mypass",
 	}
-	tests := []struct {
-		name    string
-		args    args
-		want    string
-		wantErr bool
-	}{
-		{
-			name: "Test file format",
-			args: struct {
-				FileName     string
-				chartVersion string
-			}{FileName: "test.tar.gz", chartVersion: "1.0.0"},
-			want: "test_1-0-0",
-		},
-		{
-			name: "Test file format",
-			args: struct {
-				FileName     string
-				chartVersion string
-			}{FileName: "test.pdf", chartVersion: "1.0.0"},
-			wantErr: true,
-		},
+	oldData := map[string]string{
+		"helm.repositories": "null\n",
+		"repositories":      "- name: myrepo\n  url: https://github.com/devtron/myrepo/\n  username:\n    key: \"username\"\n    name: \"myuser\"\n  password:\n    key: \"password\"\n    name: \"mypass\"",
+		"dex.config":        "",
 	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			got, err := impl.ValidateChartDetails(tt.args.FileName, tt.args.chartVersion)
-			if (err != nil) != tt.wantErr {
-				t.Errorf("ValidateChartDetails() error = %v, wantErr %v", err, tt.wantErr)
-				return
-			}
-			if got != tt.want {
-				t.Errorf("ValidateChartDetails() got = %v, want %v", got, tt.want)
-			}
-		})
+
+	// execute
+	newData, _ := s.updateRepoData(oldData, req)
+	newYaml := newData["repositories"]
+	var newRepositories []*AcdConfigMapRepositoriesDto
+	repoByte, _ := yaml.YAMLToJSON([]byte(newYaml))
+	json.Unmarshal(repoByte, &newRepositories)
+	
+	// verify
+	assert.Equal(t, "https://github.com/devtron/myrepo2/", newRepositories[1].Url)
+	assert.Equal(t, "myuser", newRepositories[1].UsernameSecret.Name)
+	assert.Equal(t, "mypass", newRepositories[1].PasswordSecret.Name)
+}
+
+func TestUpdateRepository_ExistingRepository(t *testing.T) {
+	// setup
+	sugaredLogger, err := util.NewSugardLogger()
+	assert.Nil(t, err)
+	s := ChartRepositoryServiceImpl{logger: sugaredLogger}
+	req := &ChartRepoDto{
+		Name:     "myrepo",
+		Url:      "https://github.com/devtron/myrepo2/",
+		AuthMode: repository.AUTH_MODE_USERNAME_PASSWORD,
+		UserName: "myuser2",
+		Password: "mypass2",
 	}
+	oldData := map[string]string{
+		"helm.repositories": "null\n",
+		"repositories":      "- name: myrepo\n  url: https://github.com/devtron/myrepo/\n  username:\n    key: \"username\"\n    name: \"myuser\"\n  password:\n    key: \"password\"\n    name: \"mypass\"",
+		"dex.config":        "",
+	}
+
+	// execute
+	newData, _ := s.updateRepoData(oldData, req)
+	newYaml := newData["repositories"]
+	var newRepositories []*AcdConfigMapRepositoriesDto
+	repoByte, _ := yaml.YAMLToJSON([]byte(newYaml))
+	json.Unmarshal(repoByte, &newRepositories)
+
+	// verify
+	assert.Equal(t, "https://github.com/devtron/myrepo2/", newRepositories[0].Url)
+	assert.Equal(t, "myuser2", newRepositories[0].UsernameSecret.Name)
+	assert.Equal(t, "mypass2", newRepositories[0].PasswordSecret.Name)
 }
diff --git a/pkg/pipeline/GitopsOrHelmOption_test.go b/pkg/pipeline/GitopsOrHelmOption_test.go
index c82e39141..a2ff3f5ac 100644
--- a/pkg/pipeline/GitopsOrHelmOption_test.go
+++ b/pkg/pipeline/GitopsOrHelmOption_test.go
@@ -24,7 +24,7 @@ func TestGitopsOrHelmOption(t *testing.T) {
 			nil, nil, nil,
 			nil, nil, nil, nil,
 			nil, nil, nil, nil,
-			nil, nil, nil, nil, nil, nil, nil, nil, &DeploymentServiceTypeConfig{IsInternalUse: false}, nil, nil, nil, nil)
+			nil, nil, nil, nil, nil, nil, nil, nil, &DeploymentServiceTypeConfig{IsInternalUse: false}, nil, nil, nil, nil, nil)
 
 		pipelineCreateRequest := &bean.CdPipelines{
 			Pipelines: []*bean.CDPipelineConfigObject{
@@ -77,7 +77,7 @@ func TestGitopsOrHelmOption(t *testing.T) {
 			nil, nil, nil,
 			nil, nil, nil, nil,
 			nil, nil, nil, nil,
-			nil, nil, nil, nil, nil, nil, nil, nil, &DeploymentServiceTypeConfig{IsInternalUse: false}, nil, nil, nil, nil)
+			nil, nil, nil, nil, nil, nil, nil, nil, &DeploymentServiceTypeConfig{IsInternalUse: false}, nil, nil, nil, nil, nil)
 
 		pipelineCreateRequest := &bean.CdPipelines{
 			Pipelines: []*bean.CDPipelineConfigObject{
@@ -130,7 +130,7 @@ func TestGitopsOrHelmOption(t *testing.T) {
 			nil, nil, nil,
 			nil, nil, nil, nil,
 			nil, nil, nil, nil,
-			nil, nil, nil, nil, nil, nil, nil, nil, &DeploymentServiceTypeConfig{IsInternalUse: true}, nil, nil, nil, nil)
+			nil, nil, nil, nil, nil, nil, nil, nil, &DeploymentServiceTypeConfig{IsInternalUse: true}, nil, nil, nil, nil, nil)
 
 		pipelineCreateRequestHelm := &bean.CdPipelines{
 			Pipelines: []*bean.CDPipelineConfigObject{
@@ -221,7 +221,7 @@ func TestGitopsOrHelmOption(t *testing.T) {
 			nil, nil, nil,
 			nil, nil, nil, nil,
 			nil, nil, nil, nil,
-			nil, nil, nil, nil, nil, nil, nil, nil, &DeploymentServiceTypeConfig{IsInternalUse: false}, nil, nil, nil, nil)
+			nil, nil, nil, nil, nil, nil, nil, nil, &DeploymentServiceTypeConfig{IsInternalUse: false}, nil, nil, nil, nil, nil)
 
 		pipelineCreateRequest := &bean.CdPipelines{
 			Pipelines: []*bean.CDPipelineConfigObject{
@@ -278,7 +278,7 @@ func TestGitopsOrHelmOption(t *testing.T) {
 			nil, nil, nil,
 			nil, nil, nil, nil,
 			nil, nil, nil, nil,
-			nil, nil, nil, nil, nil, nil, nil, nil, &DeploymentServiceTypeConfig{IsInternalUse: true}, nil, nil, nil, nil)
+			nil, nil, nil, nil, nil, nil, nil, nil, &DeploymentServiceTypeConfig{IsInternalUse: true}, nil, nil, nil, nil, nil)
 
 		pipelineCreateRequest := &bean.CdPipelines{
 			Pipelines: []*bean.CDPipelineConfigObject{
diff --git a/pkg/pipeline/GlobalCmcsService_test.go b/pkg/pipeline/GlobalCmcsService_test.go
new file mode 100644
index 000000000..0e3a02e7b
--- /dev/null
+++ b/pkg/pipeline/GlobalCmcsService_test.go
@@ -0,0 +1,79 @@
+package pipeline
+
+import (
+	"github.com/argoproj/argo-workflows/v3/pkg/apis/workflow/v1alpha1"
+	"github.com/devtron-labs/devtron/internal/util"
+	"github.com/stretchr/testify/assert"
+	v12 "k8s.io/api/core/v1"
+	"testing"
+)
+
+func TestNewGlobalCMCSServiceImpl(t *testing.T) {
+
+	t.Run("testGetterFunctionForGlobalTemplates", func(t *testing.T) {
+
+		sugaredLogger, err := util.NewSugardLogger()
+		assert.Nil(t, err)
+
+		GlobalCmcsService := NewGlobalCMCSServiceImpl(sugaredLogger, nil)
+
+		var globalCmCsConfigs []*GlobalCMCSDto
+
+		data := make(map[string]string)
+
+		data["a"] = "b"
+		data["b"] = "c"
+
+		globalCmCsConfigs = append(globalCmCsConfigs, &GlobalCMCSDto{
+			Id:                 0,
+			ConfigType:         "SECRET",
+			Name:               "test-secret-4",
+			Type:               "environment",
+			Data:               data,
+			MountPath:          "",
+			Deleted:            false,
+			UserId:             0,
+			SecretIngestionFor: "CI/CD",
+		}, &GlobalCMCSDto{
+			Id:                 0,
+			ConfigType:         "CONFIGMAP",
+			Name:               "test-secret-4",
+			Type:               "environment",
+			Data:               data,
+			MountPath:          "",
+			Deleted:            false,
+			UserId:             0,
+			SecretIngestionFor: "CI/CD",
+		}, &GlobalCMCSDto{
+			Id:                 0,
+			ConfigType:         "SECRET",
+			Name:               "test-secret-4",
+			Type:               "volumne",
+			Data:               data,
+			MountPath:          "",
+			Deleted:            false,
+			UserId:             0,
+			SecretIngestionFor: "CI/CD",
+		},
+		)
+
+		volumeLen := 0
+		for _, gc := range globalCmCsConfigs {
+			if gc.Type == "volume" {
+				volumeLen++
+			}
+		}
+
+		steps := make([]v1alpha1.ParallelSteps, 0)
+		volumes := make([]v12.Volume, 0)
+		templates := make([]v1alpha1.Template, 0)
+
+		err = GlobalCmcsService.AddTemplatesForGlobalSecretsInWorkflowTemplate(globalCmCsConfigs, &steps, &volumes, &templates)
+		assert.Nil(t, err)
+		assert.Equal(t, len(steps), len(globalCmCsConfigs))
+		assert.Equal(t, len(templates), len(globalCmCsConfigs))
+		assert.Equal(t, len(volumes), volumeLen)
+
+	})
+
+}