From eb5eeeb6d4c9b8ef4992c2ca4291292e4a192bd5 Mon Sep 17 00:00:00 2001 From: Ash-exp Date: Thu, 3 Apr 2025 00:45:42 +0530 Subject: [PATCH 01/19] feat: added ucid validation for ci/cd workflow status update event --- App.go | 6 +- Wire.go | 5 +- .../configure/BuildPipelineRestHandler.go | 4 +- client/argocdServer/config/Config.go | 2 +- client/telemetry/TelemetryEventClient.go | 209 ++++++------------ .../telemetry/TelemetryEventClientExtended.go | 77 +------ client/telemetry/bean.go | 139 ++++++++++++ .../telemetry/{ => posthog}/PosthogClient.go | 33 +-- client/telemetry/posthog/bean.go | 34 +++ cmd/external-app/externalApp.go | 5 +- cmd/external-app/wire.go | 5 +- cmd/external-app/wire_gen.go | 7 +- go.mod | 8 +- go.sum | 12 +- .../deployment/InstalledAppArgoCdService.go | 4 +- pkg/chartRepo/ChartRepositoryService.go | 2 +- pkg/cluster/ClusterService.go | 113 +++++----- pkg/cluster/bean/bean.go | 7 +- pkg/cluster/clusterUtil.go | 4 +- pkg/delete/DeleteService.go | 2 +- pkg/eventProcessor/bean/workflowEventBean.go | 6 + .../in/WorkflowEventProcessorService.go | 47 +++- pkg/gitops/GitOpsConfigService.go | 4 +- pkg/pipeline/CdHandler.go | 7 +- pkg/pipeline/CiHandler.go | 13 +- pkg/pipeline/WorkflowService.go | 13 +- pkg/pipeline/bean/WorkflowTemplate.go | 9 +- pkg/pipeline/executors/WorkflowUtils.go | 9 +- pkg/ucid/bean.go | 24 ++ pkg/ucid/ucid.go | 92 ++++++++ pkg/ucid/wire_ucid.go | 8 + util/helper.go | 10 +- .../devtron-labs/common-lib/informer/bean.go | 40 ++++ vendor/github.com/golang-jwt/jwt/v4/parser.go | 36 ++- vendor/modules.txt | 12 +- wire_gen.go | 21 +- 36 files changed, 665 insertions(+), 364 deletions(-) create mode 100644 client/telemetry/bean.go rename client/telemetry/{ => posthog}/PosthogClient.go (71%) create mode 100644 client/telemetry/posthog/bean.go create mode 100644 pkg/ucid/bean.go create mode 100644 pkg/ucid/ucid.go create mode 100644 pkg/ucid/wire_ucid.go create mode 100644 vendor/github.com/devtron-labs/common-lib/informer/bean.go diff --git a/App.go b/App.go index 08b240a8b7..37c38ed9d2 100644 --- a/App.go +++ b/App.go @@ -23,6 +23,7 @@ import ( "fmt" "github.com/devtron-labs/common-lib/middlewares" pubsub "github.com/devtron-labs/common-lib/pubsub-lib" + "github.com/devtron-labs/devtron/client/telemetry/posthog" "github.com/devtron-labs/devtron/pkg/eventProcessor" "github.com/devtron-labs/devtron/pkg/eventProcessor/in" "log" @@ -31,7 +32,6 @@ import ( "time" "github.com/devtron-labs/devtron/api/util" - "github.com/devtron-labs/devtron/client/telemetry" "github.com/devtron-labs/devtron/otel" "github.com/devtron-labs/devtron/pkg/auth/user" @@ -55,7 +55,7 @@ type App struct { EnforcerV2 *casbinv2.SyncedEnforcer server *http.Server db *pg.DB - posthogClient *telemetry.PosthogClient + posthogClient *posthog.PosthogClient // eventProcessor.CentralEventProcessor is used to register event processors centralEventProcessor *eventProcessor.CentralEventProcessor // do not remove this. // used for local dev only @@ -73,7 +73,7 @@ func NewApp(router *router.MuxRouter, enforcer *casbin.SyncedEnforcer, db *pg.DB, sessionManager2 *authMiddleware.SessionManager, - posthogClient *telemetry.PosthogClient, + posthogClient *posthog.PosthogClient, loggingMiddleware util.LoggingMiddleware, centralEventProcessor *eventProcessor.CentralEventProcessor, pubSubClient *pubsub.PubSubClientServiceImpl, diff --git a/Wire.go b/Wire.go index 3401d2d623..f7446f1573 100644 --- a/Wire.go +++ b/Wire.go @@ -97,6 +97,7 @@ import ( "github.com/devtron-labs/devtron/client/lens" "github.com/devtron-labs/devtron/client/proxy" "github.com/devtron-labs/devtron/client/telemetry" + "github.com/devtron-labs/devtron/client/telemetry/posthog" "github.com/devtron-labs/devtron/internal/sql/repository" app2 "github.com/devtron-labs/devtron/internal/sql/repository/app" appStatusRepo "github.com/devtron-labs/devtron/internal/sql/repository/appStatus" @@ -164,6 +165,7 @@ import ( resourceGroup2 "github.com/devtron-labs/devtron/pkg/resourceGroup" "github.com/devtron-labs/devtron/pkg/resourceQualifiers" "github.com/devtron-labs/devtron/pkg/sql" + "github.com/devtron-labs/devtron/pkg/ucid" util3 "github.com/devtron-labs/devtron/pkg/util" "github.com/devtron-labs/devtron/pkg/variables" "github.com/devtron-labs/devtron/pkg/variables/parsers" @@ -692,7 +694,8 @@ func InitializeApp() (*App, error) { wire.Bind(new(router.TelemetryRouter), new(*router.TelemetryRouterImpl)), restHandler.NewTelemetryRestHandlerImpl, wire.Bind(new(restHandler.TelemetryRestHandler), new(*restHandler.TelemetryRestHandlerImpl)), - telemetry.NewPosthogClient, + posthog.NewPosthogClient, + ucid.WireSet, cloudProviderIdentifier.NewProviderIdentifierServiceImpl, wire.Bind(new(cloudProviderIdentifier.ProviderIdentifierService), new(*cloudProviderIdentifier.ProviderIdentifierServiceImpl)), diff --git a/api/restHandler/app/pipeline/configure/BuildPipelineRestHandler.go b/api/restHandler/app/pipeline/configure/BuildPipelineRestHandler.go index 32448e0abf..cb730a93ab 100644 --- a/api/restHandler/app/pipeline/configure/BuildPipelineRestHandler.go +++ b/api/restHandler/app/pipeline/configure/BuildPipelineRestHandler.go @@ -25,6 +25,7 @@ import ( "github.com/devtron-labs/devtron/internal/sql/constants" "github.com/devtron-labs/devtron/pkg/build/artifacts/imageTagging" bean2 "github.com/devtron-labs/devtron/pkg/build/pipeline/bean" + bean3 "github.com/devtron-labs/devtron/pkg/eventProcessor/bean" constants2 "github.com/devtron-labs/devtron/pkg/pipeline/constants" "github.com/devtron-labs/devtron/util/stringsUtil" "golang.org/x/exp/maps" @@ -36,7 +37,6 @@ import ( "github.com/devtron-labs/devtron/util/response/pagination" "github.com/gorilla/schema" - "github.com/argoproj/argo-workflows/v3/pkg/apis/workflow/v1alpha1" "github.com/devtron-labs/devtron/api/restHandler/common" "github.com/devtron-labs/devtron/client/gitSensor" "github.com/devtron-labs/devtron/internal/sql/repository" @@ -1500,7 +1500,7 @@ func (handler *PipelineConfigRestHandlerImpl) DeleteMaterial(w http.ResponseWrit func (handler *PipelineConfigRestHandlerImpl) HandleWorkflowWebhook(w http.ResponseWriter, r *http.Request) { decoder := json.NewDecoder(r.Body) - var wfUpdateReq v1alpha1.WorkflowStatus + var wfUpdateReq bean3.CiCdStatus err := decoder.Decode(&wfUpdateReq) if err != nil { handler.Logger.Errorw("request err, HandleWorkflowWebhook", "err", err, "payload", wfUpdateReq) diff --git a/client/argocdServer/config/Config.go b/client/argocdServer/config/Config.go index 20b622c38e..2027a2257f 100644 --- a/client/argocdServer/config/Config.go +++ b/client/argocdServer/config/Config.go @@ -71,7 +71,7 @@ func (impl *ArgoCDConfigGetterImpl) GetGRPCConfig() (*bean.ArgoGRPCConfig, error } func (impl *ArgoCDConfigGetterImpl) GetK8sConfig() (*bean.ArgoK8sConfig, error) { - clusterBean, err := impl.clusterReadService.FindOne(bean2.DEFAULT_CLUSTER) + clusterBean, err := impl.clusterReadService.FindOne(bean2.DefaultCluster) if err != nil { impl.logger.Errorw("error in fetching cluster bean from db", "err", err) return nil, err diff --git a/client/telemetry/TelemetryEventClient.go b/client/telemetry/TelemetryEventClient.go index f32382a06b..5d3ba4ab25 100644 --- a/client/telemetry/TelemetryEventClient.go +++ b/client/telemetry/TelemetryEventClient.go @@ -24,12 +24,15 @@ import ( cloudProviderIdentifier "github.com/devtron-labs/common-lib/cloud-provider-identifier" "github.com/devtron-labs/common-lib/utils/k8s/commonBean" "github.com/devtron-labs/devtron/api/helm-app/gRPC" + posthogClient "github.com/devtron-labs/devtron/client/telemetry/posthog" installedAppReader "github.com/devtron-labs/devtron/pkg/appStore/installedApp/read" bean2 "github.com/devtron-labs/devtron/pkg/attributes/bean" "github.com/devtron-labs/devtron/pkg/auth/user/bean" bean3 "github.com/devtron-labs/devtron/pkg/cluster/bean" module2 "github.com/devtron-labs/devtron/pkg/module/bean" + ucidService "github.com/devtron-labs/devtron/pkg/ucid" cron3 "github.com/devtron-labs/devtron/util/cron" + "go.opentelemetry.io/otel" "net/http" "time" @@ -43,22 +46,13 @@ import ( util3 "github.com/devtron-labs/devtron/pkg/util" "github.com/devtron-labs/devtron/util" "github.com/go-pg/pg" - "github.com/patrickmn/go-cache" "github.com/posthog/posthog-go" "github.com/robfig/cron/v3" "github.com/tidwall/gjson" "go.uber.org/zap" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - "k8s.io/api/core/v1" - v12 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/version" ) -const LOGIN_COUNT_CONST = "login-count" -const SKIPPED_ONBOARDING_CONST = "SkippedOnboarding" -const ADMIN_EMAIL_ID_CONST = "admin" - type TelemetryEventClientImpl struct { cron *cron.Cron logger *zap.SugaredLogger @@ -69,7 +63,8 @@ type TelemetryEventClientImpl struct { userService user2.UserService attributeRepo repository.AttributesRepository ssoLoginService sso.SSOLoginService - PosthogClient *PosthogClient + posthogClient *posthogClient.PosthogClient + ucid ucidService.Service moduleRepository moduleRepo.ModuleRepository serverDataStore *serverDataStore.ServerDataStore userAuditService user2.UserAuditService @@ -93,9 +88,9 @@ type TelemetryEventClient interface { func NewTelemetryEventClientImpl(logger *zap.SugaredLogger, client *http.Client, clusterService cluster.ClusterService, K8sUtil *k8s.K8sServiceImpl, aCDAuthConfig *util3.ACDAuthConfig, userService user2.UserService, attributeRepo repository.AttributesRepository, ssoLoginService sso.SSOLoginService, - PosthogClient *PosthogClient, moduleRepository moduleRepo.ModuleRepository, - serverDataStore *serverDataStore.ServerDataStore, userAuditService user2.UserAuditService, - helmAppClient gRPC.HelmAppClient, + posthog *posthogClient.PosthogClient, ucid ucidService.Service, + moduleRepository moduleRepo.ModuleRepository, serverDataStore *serverDataStore.ServerDataStore, + userAuditService user2.UserAuditService, helmAppClient gRPC.HelmAppClient, cloudProviderIdentifierService cloudProviderIdentifier.ProviderIdentifierService, cronLogger *cron3.CronLoggerImpl, installedAppReadService installedAppReader.InstalledAppReadServiceEA, envVariables *util.EnvironmentVariables) (*TelemetryEventClientImpl, error) { @@ -112,7 +107,8 @@ func NewTelemetryEventClientImpl(logger *zap.SugaredLogger, client *http.Client, userService: userService, attributeRepo: attributeRepo, ssoLoginService: ssoLoginService, - PosthogClient: PosthogClient, + posthogClient: posthog, + ucid: ucid, moduleRepository: moduleRepository, serverDataStore: serverDataStore, userAuditService: userAuditService, @@ -124,13 +120,13 @@ func NewTelemetryEventClientImpl(logger *zap.SugaredLogger, client *http.Client, } watcher.HeartbeatEventForTelemetry() - _, err := cron.AddFunc(SummaryCronExpr, watcher.SummaryEventForTelemetryEA) + _, err := cron.AddFunc(posthogClient.SummaryCronExpr, watcher.SummaryEventForTelemetryEA) if err != nil { logger.Errorw("error in starting summery event", "err", err) return nil, err } - _, err = cron.AddFunc(HeartbeatCronExpr, watcher.HeartbeatEventForTelemetry) + _, err = cron.AddFunc(posthogClient.HeartbeatCronExpr, watcher.HeartbeatEventForTelemetry) if err != nil { logger.Errorw("error in starting heartbeat event", "err", err) return nil, err @@ -155,59 +151,6 @@ func (impl *TelemetryEventClientImpl) StopCron() { impl.cron.Stop() } -type TelemetryEventEA struct { - UCID string `json:"ucid"` //unique client id - Timestamp time.Time `json:"timestamp"` - EventMessage string `json:"eventMessage,omitempty"` - EventType TelemetryEventType `json:"eventType"` - ServerVersion string `json:"serverVersion,omitempty"` - UserCount int `json:"userCount,omitempty"` - ClusterCount int `json:"clusterCount,omitempty"` - HostURL bool `json:"hostURL,omitempty"` - SSOLogin bool `json:"ssoLogin,omitempty"` - DevtronVersion string `json:"devtronVersion,omitempty"` - DevtronMode string `json:"devtronMode,omitempty"` - InstalledIntegrations []string `json:"installedIntegrations,omitempty"` - InstallFailedIntegrations []string `json:"installFailedIntegrations,omitempty"` - InstallTimedOutIntegrations []string `json:"installTimedOutIntegrations,omitempty"` - LastLoginTime time.Time `json:"LastLoginTime,omitempty"` - InstallingIntegrations []string `json:"installingIntegrations,omitempty"` - DevtronReleaseVersion string `json:"devtronReleaseVersion,omitempty"` - HelmAppAccessCounter string `json:"HelmAppAccessCounter,omitempty"` - HelmAppUpdateCounter string `json:"HelmAppUpdateCounter,omitempty"` - ChartStoreVisitCount string `json:"ChartStoreVisitCount,omitempty"` - SkippedOnboarding bool `json:"SkippedOnboarding"` - HelmChartSuccessfulDeploymentCount int `json:"helmChartSuccessfulDeploymentCount,omitempty"` - ExternalHelmAppClusterCount map[int32]int `json:"ExternalHelmAppClusterCount,omitempty"` - ClusterProvider string `json:"clusterProvider,omitempty"` -} - -const DevtronUniqueClientIdConfigMap = "devtron-ucid" -const DevtronUniqueClientIdConfigMapKey = "UCID" -const InstallEventKey = "installEvent" -const UIEventKey = "uiEventKey" - -type TelemetryEventType string - -const ( - Heartbeat TelemetryEventType = "Heartbeat" - InstallationStart TelemetryEventType = "InstallationStart" - InstallationInProgress TelemetryEventType = "InstallationInProgress" - InstallationInterrupt TelemetryEventType = "InstallationInterrupt" - InstallationSuccess TelemetryEventType = "InstallationSuccess" - InstallationFailure TelemetryEventType = "InstallationFailure" - UpgradeStart TelemetryEventType = "UpgradeStart" - UpgradeInProgress TelemetryEventType = "UpgradeInProgress" - UpgradeInterrupt TelemetryEventType = "UpgradeInterrupt" - UpgradeSuccess TelemetryEventType = "UpgradeSuccess" - UpgradeFailure TelemetryEventType = "UpgradeFailure" - Summary TelemetryEventType = "Summary" - InstallationApplicationError TelemetryEventType = "InstallationApplicationError" - DashboardAccessed TelemetryEventType = "DashboardAccessed" - DashboardLoggedIn TelemetryEventType = "DashboardLoggedIn" - SIG_TERM TelemetryEventType = "SIG_TERM" -) - func (impl *TelemetryEventClientImpl) SummaryDetailsForTelemetry() (cluster []bean3.ClusterBean, user []bean.UserInfo, k8sServerVersion *version.Info, hostURL bool, ssoSetup bool, HelmAppAccessCount string, ChartStoreVisitCount string, SkippedOnboarding bool, HelmAppUpdateCounter string, helmChartSuccessfulDeploymentCount int, ExternalHelmAppClusterCount map[int32]int) { @@ -297,9 +240,9 @@ func (impl *TelemetryEventClientImpl) SummaryDetailsForTelemetry() (cluster []be } //getting userData from emailId - userData, err := impl.userAttributesRepository.GetUserDataByEmailId(ADMIN_EMAIL_ID_CONST) + userData, err := impl.userAttributesRepository.GetUserDataByEmailId(AdminEmailIdConst) - SkippedOnboardingValue := gjson.Get(userData, SKIPPED_ONBOARDING_CONST).Str + SkippedOnboardingValue := gjson.Get(userData, SkippedOnboardingConst).Str if SkippedOnboardingValue == "true" { SkippedOnboarding = true @@ -326,13 +269,13 @@ func (impl *TelemetryEventClientImpl) SummaryEventForTelemetryEA() { func (impl *TelemetryEventClientImpl) SendSummaryEvent(eventType string) error { impl.logger.Infow("sending summary event", "eventType", eventType) - ucid, err := impl.getUCID() + ucid, err := impl.getUCIDAndCheckIsOptedOut(context.Background()) if err != nil { impl.logger.Errorw("exception caught inside telemetry summary event", "err", err) return err } - if IsOptOut { + if posthogClient.IsOptOut { impl.logger.Warnw("client is opt-out for telemetry, there will be no events capture", "ucid", ucid) return err } @@ -404,13 +347,13 @@ func (impl *TelemetryEventClientImpl) EnqueuePostHog(ucid string, eventType Tele } func (impl *TelemetryEventClientImpl) SendGenericTelemetryEvent(eventType string, prop map[string]interface{}) error { - ucid, err := impl.getUCID() + ucid, err := impl.getUCIDAndCheckIsOptedOut(context.Background()) if err != nil { impl.logger.Errorw("exception caught inside telemetry generic event", "err", err) return nil } - if IsOptOut { + if posthogClient.IsOptOut { impl.logger.Warnw("client is opt-out for telemetry, there will be no events capture", "ucid", ucid) return nil } @@ -419,15 +362,15 @@ func (impl *TelemetryEventClientImpl) SendGenericTelemetryEvent(eventType string } func (impl *TelemetryEventClientImpl) EnqueueGenericPostHogEvent(ucid string, eventType string, prop map[string]interface{}) error { - if impl.PosthogClient.Client == nil { + if impl.posthogClient.Client == nil { impl.logger.Warn("no posthog client found, creating new") - client, err := impl.retryPosthogClient(PosthogApiKey, PosthogEndpoint) + client, err := impl.retryPosthogClient(posthogClient.PosthogApiKey, posthogClient.PosthogEndpoint) if err == nil { - impl.PosthogClient.Client = client + impl.posthogClient.Client = client } } - if impl.PosthogClient.Client != nil && !impl.globalEnvVariables.IsAirGapEnvironment { - err := impl.PosthogClient.Client.Enqueue(posthog.Capture{ + if impl.posthogClient.Client != nil && !impl.globalEnvVariables.IsAirGapEnvironment { + err := impl.posthogClient.Client.Enqueue(posthog.Capture{ DistinctId: ucid, Event: eventType, Properties: prop, @@ -441,12 +384,12 @@ func (impl *TelemetryEventClientImpl) EnqueueGenericPostHogEvent(ucid string, ev } func (impl *TelemetryEventClientImpl) HeartbeatEventForTelemetry() { - ucid, err := impl.getUCID() + ucid, err := impl.getUCIDAndCheckIsOptedOut(context.Background()) if err != nil { impl.logger.Errorw("exception caught inside telemetry heartbeat event", "err", err) return } - if IsOptOut { + if posthogClient.IsOptOut { impl.logger.Warnw("client is opt-out for telemetry, there will be no events capture", "ucid", ucid) return } @@ -488,21 +431,21 @@ func (impl *TelemetryEventClientImpl) HeartbeatEventForTelemetry() { } func (impl *TelemetryEventClientImpl) GetTelemetryMetaInfo() (*TelemetryMetaInfo, error) { - ucid, err := impl.getUCID() + ucid, err := impl.getUCIDAndCheckIsOptedOut(context.Background()) if err != nil { impl.logger.Errorw("exception while getting unique client id", "error", err) return nil, err } data := &TelemetryMetaInfo{ - Url: PosthogEndpoint, + Url: posthogClient.PosthogEndpoint, UCID: ucid, - ApiKey: PosthogEncodedApiKey, + ApiKey: posthogClient.PosthogEncodedApiKey, } return data, err } func (impl *TelemetryEventClientImpl) SendTelemetryInstallEventEA() (*TelemetryEventType, error) { - ucid, err := impl.getUCID() + ucid, err := impl.getUCIDAndCheckIsOptedOut(context.Background()) if err != nil { impl.logger.Errorw("exception while getting unique client id", "error", err) return nil, err @@ -546,15 +489,19 @@ func (impl *TelemetryEventClientImpl) SendTelemetryInstallEventEA() (*TelemetryE impl.logger.Errorw("Installation EventForTelemetry EA Mode, payload unmarshal error", "error", err) return nil, nil } - cm, err := impl.K8sUtil.GetConfigMap(impl.aCDAuthConfig.ACDConfigMapNamespace, DevtronUniqueClientIdConfigMap, client) + cm, err := impl.K8sUtil.GetConfigMap(impl.aCDAuthConfig.ACDConfigMapNamespace, ucidService.DevtronUniqueClientIdConfigMap, client) + if err != nil { + impl.logger.Errorw("Installation EventForTelemetry EA Mode, failed to get DevtronUniqueClientIdConfigMap", "error", err) + return nil, err + } datamap := cm.Data - installEventValue, installEventKeyExists := datamap[InstallEventKey] + installEventValue, installEventKeyExists := datamap[ucidService.InstallEventKey] if installEventKeyExists == false || installEventValue == "1" { err = impl.EnqueuePostHog(ucid, InstallationSuccess, prop) if err == nil { - datamap[InstallEventKey] = "2" + datamap[ucidService.InstallEventKey] = "2" cm.Data = datamap _, err = impl.K8sUtil.UpdateConfigMap(impl.aCDAuthConfig.ACDConfigMapNamespace, cm, client) if err != nil { @@ -568,7 +515,7 @@ func (impl *TelemetryEventClientImpl) SendTelemetryInstallEventEA() (*TelemetryE } func (impl *TelemetryEventClientImpl) SendTelemetryDashboardAccessEvent() error { - ucid, err := impl.getUCID() + ucid, err := impl.getUCIDAndCheckIsOptedOut(context.Background()) if err != nil { impl.logger.Errorw("exception while getting unique client id", "error", err) return err @@ -612,19 +559,19 @@ func (impl *TelemetryEventClientImpl) SendTelemetryDashboardAccessEvent() error impl.logger.Errorw("DashboardAccessed EventForTelemetry, payload unmarshal error", "error", err) return err } - cm, err := impl.K8sUtil.GetConfigMap(impl.aCDAuthConfig.ACDConfigMapNamespace, DevtronUniqueClientIdConfigMap, client) + cm, err := impl.K8sUtil.GetConfigMap(impl.aCDAuthConfig.ACDConfigMapNamespace, ucidService.DevtronUniqueClientIdConfigMap, client) if err != nil { impl.logger.Errorw("DashboardAccessed EventForTelemetry,failed to get DevtronUniqueClientIdConfigMap", "error", err) return err } datamap := cm.Data - accessEventValue, installEventKeyExists := datamap[UIEventKey] + accessEventValue, installEventKeyExists := datamap[ucidService.UIEventKey] if installEventKeyExists == false || accessEventValue <= "1" { err = impl.EnqueuePostHog(ucid, DashboardAccessed, prop) if err == nil { - datamap[UIEventKey] = "2" + datamap[ucidService.UIEventKey] = "2" cm.Data = datamap _, err = impl.K8sUtil.UpdateConfigMap(impl.aCDAuthConfig.ACDConfigMapNamespace, cm, client) if err != nil { @@ -638,7 +585,7 @@ func (impl *TelemetryEventClientImpl) SendTelemetryDashboardAccessEvent() error } func (impl *TelemetryEventClientImpl) SendTelemetryDashboardLoggedInEvent() error { - ucid, err := impl.getUCID() + ucid, err := impl.getUCIDAndCheckIsOptedOut(context.Background()) if err != nil { impl.logger.Errorw("exception while getting unique client id", "error", err) return err @@ -682,19 +629,19 @@ func (impl *TelemetryEventClientImpl) SendTelemetryDashboardLoggedInEvent() erro impl.logger.Errorw("DashboardLoggedIn EventForTelemetry, payload unmarshal error", "error", err) return err } - cm, err := impl.K8sUtil.GetConfigMap(impl.aCDAuthConfig.ACDConfigMapNamespace, DevtronUniqueClientIdConfigMap, client) + cm, err := impl.K8sUtil.GetConfigMap(impl.aCDAuthConfig.ACDConfigMapNamespace, ucidService.DevtronUniqueClientIdConfigMap, client) if err != nil { impl.logger.Errorw("DashboardLoggedIn EventForTelemetry,failed to get DevtronUniqueClientIdConfigMap", "error", err) return err } datamap := cm.Data - accessEventValue, installEventKeyExists := datamap[UIEventKey] + accessEventValue, installEventKeyExists := datamap[ucidService.UIEventKey] if installEventKeyExists == false || accessEventValue != "3" { err = impl.EnqueuePostHog(ucid, DashboardLoggedIn, prop) if err == nil { - datamap[UIEventKey] = "3" + datamap[ucidService.UIEventKey] = "3" cm.Data = datamap _, err = impl.K8sUtil.UpdateConfigMap(impl.aCDAuthConfig.ACDConfigMapNamespace, cm, client) if err != nil { @@ -707,57 +654,29 @@ func (impl *TelemetryEventClientImpl) SendTelemetryDashboardLoggedInEvent() erro return nil } -type TelemetryMetaInfo struct { - Url string `json:"url,omitempty"` - UCID string `json:"ucid,omitempty"` - ApiKey string `json:"apiKey,omitempty"` -} - -func (impl *TelemetryEventClientImpl) getUCID() (string, error) { - ucid, found := impl.PosthogClient.cache.Get(DevtronUniqueClientIdConfigMapKey) - if found { - return ucid.(string), nil - } else { - client, err := impl.K8sUtil.GetClientForInCluster() - if err != nil { - impl.logger.Errorw("exception while getting unique client id", "error", err) - return "", err - } - - cm, err := impl.K8sUtil.GetConfigMap(impl.aCDAuthConfig.ACDConfigMapNamespace, DevtronUniqueClientIdConfigMap, client) - if errStatus, ok := status.FromError(err); !ok || errStatus.Code() == codes.NotFound || errStatus.Code() == codes.Unknown { - // if not found, create new cm - cm = &v1.ConfigMap{ObjectMeta: v12.ObjectMeta{Name: DevtronUniqueClientIdConfigMap}} - data := map[string]string{} - data[DevtronUniqueClientIdConfigMapKey] = util.Generate(16) // generate unique random number - data[InstallEventKey] = "1" // used in operator to detect event is install or upgrade - data[UIEventKey] = "1" - cm.Data = data - _, err = impl.K8sUtil.CreateConfigMap(impl.aCDAuthConfig.ACDConfigMapNamespace, cm, client) - if err != nil { - impl.logger.Errorw("exception while getting unique client id", "error", err) - return "", err - } - } - dataMap := cm.Data - ucid = dataMap[DevtronUniqueClientIdConfigMapKey] - impl.PosthogClient.cache.Set(DevtronUniqueClientIdConfigMapKey, ucid, cache.DefaultExpiration) - if cm == nil { - impl.logger.Errorw("configmap not found while getting unique client id", "cm", cm) - return ucid.(string), err - } - flag, err := impl.checkForOptOut(ucid.(string)) +func (impl *TelemetryEventClientImpl) getUCIDAndCheckIsOptedOut(ctx context.Context) (string, error) { + newCtx, span := otel.Tracer("orchestrator").Start(ctx, "TelemetryEventClientImpl.getUCIDAndCheckIsOptedOut") + defer span.End() + ucid, found, err := impl.ucid.GetUCID() + if err != nil { + impl.logger.Errorw("exception while getting unique client id", "error", err) + return "", err + } + if !found { + flag, err := impl.checkForOptOut(newCtx, ucid) if err != nil { impl.logger.Errorw("error sending event to posthog, failed check for opt-out", "err", err) return "", err } - IsOptOut = flag + posthogClient.IsOptOut = flag } - return ucid.(string), nil + return ucid, nil } -func (impl *TelemetryEventClientImpl) checkForOptOut(UCID string) (bool, error) { - decodedUrl, err := base64.StdEncoding.DecodeString(TelemetryOptOutApiBaseUrl) +func (impl *TelemetryEventClientImpl) checkForOptOut(ctx context.Context, UCID string) (bool, error) { + newCtx, span := otel.Tracer("orchestrator").Start(ctx, "TelemetryEventClientImpl.checkForOptOut") + defer span.End() + decodedUrl, err := base64.StdEncoding.DecodeString(posthogClient.TelemetryOptOutApiBaseUrl) if err != nil { impl.logger.Errorw("check opt-out list failed, decode error", "err", err) return false, err @@ -765,13 +684,13 @@ func (impl *TelemetryEventClientImpl) checkForOptOut(UCID string) (bool, error) encodedUrl := string(decodedUrl) url := fmt.Sprintf("%s/%s", encodedUrl, UCID) - response, err := util.HttpRequest(url) + response, err := util.HttpRequest(newCtx, url) if err != nil { - impl.logger.Errorw("check opt-out list failed, rest api error", "err", err) + impl.logger.Errorw("check opt-out list failed, rest api error", "ucid", UCID, "err", err) return false, err } flag := response["result"].(bool) - return flag, err + return flag, nil } func (impl *TelemetryEventClientImpl) retryPosthogClient(PosthogApiKey string, PosthogEndpoint string) (posthog.Client, error) { @@ -783,7 +702,7 @@ func (impl *TelemetryEventClientImpl) retryPosthogClient(PosthogApiKey string, P return client, err } -// returns installedIntegrations, installFailedIntegrations, installTimedOutIntegrations, installingIntegrations +// buildIntegrationsList - returns installedIntegrations, installFailedIntegrations, installTimedOutIntegrations, installingIntegrations func (impl *TelemetryEventClientImpl) buildIntegrationsList() ([]string, []string, []string, []string, error) { impl.logger.Info("building integrations list for telemetry") diff --git a/client/telemetry/TelemetryEventClientExtended.go b/client/telemetry/TelemetryEventClientExtended.go index 830eb6ae52..1670a6b4db 100644 --- a/client/telemetry/TelemetryEventClientExtended.go +++ b/client/telemetry/TelemetryEventClientExtended.go @@ -17,10 +17,12 @@ package telemetry import ( + "context" "encoding/json" cloudProviderIdentifier "github.com/devtron-labs/common-lib/cloud-provider-identifier" util2 "github.com/devtron-labs/common-lib/utils/k8s" client "github.com/devtron-labs/devtron/api/helm-app/gRPC" + posthogClient "github.com/devtron-labs/devtron/client/telemetry/posthog" installedAppReader "github.com/devtron-labs/devtron/pkg/appStore/installedApp/read" "github.com/devtron-labs/devtron/pkg/auth/sso" user2 "github.com/devtron-labs/devtron/pkg/auth/user" @@ -33,6 +35,7 @@ import ( "github.com/devtron-labs/devtron/pkg/deployment/gitOps/config" moduleRepo "github.com/devtron-labs/devtron/pkg/module/repo" serverDataStore "github.com/devtron-labs/devtron/pkg/server/store" + ucidService "github.com/devtron-labs/devtron/pkg/ucid" util3 "github.com/devtron-labs/devtron/pkg/util" cron3 "github.com/devtron-labs/devtron/util/cron" "net/http" @@ -50,8 +53,6 @@ import ( "go.uber.org/zap" ) -const AppsCount int = 50 - type TelemetryEventClientImplExtended struct { environmentService environment.EnvironmentService appListingRepository repository.AppListingRepository @@ -73,7 +74,7 @@ type TelemetryEventClientImplExtended struct { func NewTelemetryEventClientImplExtended(logger *zap.SugaredLogger, client *http.Client, clusterService cluster.ClusterService, K8sUtil *util2.K8sServiceImpl, aCDAuthConfig *util3.ACDAuthConfig, environmentService environment.EnvironmentService, userService user2.UserService, - appListingRepository repository.AppListingRepository, PosthogClient *PosthogClient, + appListingRepository repository.AppListingRepository, posthog *posthogClient.PosthogClient, ucid ucidService.Service, ciPipelineConfigReadService ciConfig.CiPipelineConfigReadService, pipelineRepository pipelineConfig.PipelineRepository, gitProviderRepository repository3.GitProviderRepository, attributeRepo repository.AttributesRepository, ssoLoginService sso.SSOLoginService, appRepository app.AppRepository, @@ -114,7 +115,8 @@ func NewTelemetryEventClientImplExtended(logger *zap.SugaredLogger, client *http userService: userService, attributeRepo: attributeRepo, ssoLoginService: ssoLoginService, - PosthogClient: PosthogClient, + posthogClient: posthog, + ucid: ucid, moduleRepository: moduleRepository, serverDataStore: serverDataStore, userAuditService: userAuditService, @@ -127,13 +129,13 @@ func NewTelemetryEventClientImplExtended(logger *zap.SugaredLogger, client *http } watcher.HeartbeatEventForTelemetry() - _, err := cron.AddFunc(SummaryCronExpr, watcher.SummaryEventForTelemetry) + _, err := cron.AddFunc(posthogClient.SummaryCronExpr, watcher.SummaryEventForTelemetry) if err != nil { logger.Errorw("error in starting summery event", "err", err) return nil, err } - _, err = cron.AddFunc(HeartbeatCronExpr, watcher.HeartbeatEventForTelemetry) + _, err = cron.AddFunc(posthogClient.HeartbeatCronExpr, watcher.HeartbeatEventForTelemetry) if err != nil { logger.Errorw("error in starting heartbeat event", "err", err) return nil, err @@ -141,65 +143,6 @@ func NewTelemetryEventClientImplExtended(logger *zap.SugaredLogger, client *http return watcher, err } -type TelemetryEventDto struct { - UCID string `json:"ucid"` //unique client id - Timestamp time.Time `json:"timestamp"` - EventMessage string `json:"eventMessage,omitempty"` - EventType TelemetryEventType `json:"eventType"` - ProdAppCount int `json:"prodAppCount,omitempty"` - NonProdAppCount int `json:"nonProdAppCount,omitempty"` - UserCount int `json:"userCount,omitempty"` - EnvironmentCount int `json:"environmentCount,omitempty"` - ClusterCount int `json:"clusterCount,omitempty"` - CiCreatedPerDay int `json:"ciCreatedPerDay"` - CdCreatedPerDay int `json:"cdCreatedPerDay"` - CiDeletedPerDay int `json:"ciDeletedPerDay"` - CdDeletedPerDay int `json:"cdDeletedPerDay"` - CiTriggeredPerDay int `json:"ciTriggeredPerDay"` - CdTriggeredPerDay int `json:"cdTriggeredPerDay"` - HelmChartCount int `json:"helmChartCount,omitempty"` - SecurityScanCountPerDay int `json:"securityScanCountPerDay,omitempty"` - GitAccountsCount int `json:"gitAccountsCount,omitempty"` - GitOpsCount int `json:"gitOpsCount,omitempty"` - RegistryCount int `json:"registryCount,omitempty"` - HostURL bool `json:"hostURL,omitempty"` - SSOLogin bool `json:"ssoLogin,omitempty"` - AppCount int `json:"appCount,omitempty"` - AppsWithGitRepoConfigured int `json:"appsWithGitRepoConfigured,omitempty"` - AppsWithDockerConfigured int `json:"appsWithDockerConfigured,omitempty"` - AppsWithDeploymentTemplateConfigured int `json:"appsWithDeploymentTemplateConfigured,omitempty"` - AppsWithCiPipelineConfigured int `json:"appsWithCiPipelineConfigured,omitempty"` - AppsWithCdPipelineConfigured int `json:"appsWithCdPipelineConfigured,omitempty"` - Build bool `json:"build,omitempty"` - Deployment bool `json:"deployment,omitempty"` - ServerVersion string `json:"serverVersion,omitempty"` - DevtronGitVersion string `json:"devtronGitVersion,omitempty"` - DevtronVersion string `json:"devtronVersion,omitempty"` - DevtronMode string `json:"devtronMode,omitempty"` - InstalledIntegrations []string `json:"installedIntegrations,omitempty"` - InstallFailedIntegrations []string `json:"installFailedIntegrations,omitempty"` - InstallTimedOutIntegrations []string `json:"installTimedOutIntegrations,omitempty"` - InstallingIntegrations []string `json:"installingIntegrations,omitempty"` - DevtronReleaseVersion string `json:"devtronReleaseVersion,omitempty"` - LastLoginTime time.Time `json:"LastLoginTime,omitempty"` - SelfDockerfileCount int `json:"selfDockerfileCount"` - ManagedDockerfileCount int `json:"managedDockerfileCount"` - BuildPackCount int `json:"buildPackCount"` - SelfDockerfileSuccessCount int `json:"selfDockerfileSuccessCount"` - SelfDockerfileFailureCount int `json:"selfDockerfileFailureCount"` - ManagedDockerfileSuccessCount int `json:"managedDockerfileSuccessCount"` - ManagedDockerfileFailureCount int `json:"managedDockerfileFailureCount"` - BuildPackSuccessCount int `json:"buildPackSuccessCount"` - BuildPackFailureCount int `json:"buildPackFailureCount"` - HelmAppAccessCounter string `json:"HelmAppAccessCounter,omitempty"` - ChartStoreVisitCount string `json:"ChartStoreVisitCount,omitempty"` - SkippedOnboarding bool `json:"SkippedOnboarding"` - HelmAppUpdateCounter string `json:"HelmAppUpdateCounter,omitempty"` - HelmChartSuccessfulDeploymentCount int `json:"helmChartSuccessfulDeploymentCount,omitempty"` - ExternalHelmAppClusterCount map[int32]int `json:"ExternalHelmAppClusterCount"` - ClusterProvider string `json:"clusterProvider,omitempty"` -} - func (impl *TelemetryEventClientImplExtended) SummaryEventForTelemetry() { err := impl.SendSummaryEvent(string(Summary)) if err != nil { @@ -209,13 +152,13 @@ func (impl *TelemetryEventClientImplExtended) SummaryEventForTelemetry() { func (impl *TelemetryEventClientImplExtended) SendSummaryEvent(eventType string) error { impl.logger.Infow("sending summary event", "eventType", eventType) - ucid, err := impl.getUCID() + ucid, err := impl.getUCIDAndCheckIsOptedOut(context.Background()) if err != nil { impl.logger.Errorw("exception caught inside telemetry summary event while retrieving ucid", "err", err) return err } - if IsOptOut { + if posthogClient.IsOptOut { impl.logger.Warnw("client is opt-out for telemetry, there will be no events capture", "ucid", ucid) return err } diff --git a/client/telemetry/bean.go b/client/telemetry/bean.go new file mode 100644 index 0000000000..f3e95dd0e7 --- /dev/null +++ b/client/telemetry/bean.go @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2020-2024. Devtron Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package telemetry + +import "time" + +type TelemetryMetaInfo struct { + Url string `json:"url,omitempty"` + UCID string `json:"ucid,omitempty"` + ApiKey string `json:"apiKey,omitempty"` +} + +const ( + SkippedOnboardingConst = "SkippedOnboarding" + AdminEmailIdConst = "admin" +) + +type TelemetryEventType string + +const ( + Heartbeat TelemetryEventType = "Heartbeat" + InstallationStart TelemetryEventType = "InstallationStart" + InstallationInProgress TelemetryEventType = "InstallationInProgress" + InstallationInterrupt TelemetryEventType = "InstallationInterrupt" + InstallationSuccess TelemetryEventType = "InstallationSuccess" + InstallationFailure TelemetryEventType = "InstallationFailure" + UpgradeStart TelemetryEventType = "UpgradeStart" + UpgradeInProgress TelemetryEventType = "UpgradeInProgress" + UpgradeInterrupt TelemetryEventType = "UpgradeInterrupt" + UpgradeSuccess TelemetryEventType = "UpgradeSuccess" + UpgradeFailure TelemetryEventType = "UpgradeFailure" + Summary TelemetryEventType = "Summary" + InstallationApplicationError TelemetryEventType = "InstallationApplicationError" + DashboardAccessed TelemetryEventType = "DashboardAccessed" + DashboardLoggedIn TelemetryEventType = "DashboardLoggedIn" + SIG_TERM TelemetryEventType = "SIG_TERM" +) + +type TelemetryEventEA struct { + UCID string `json:"ucid"` //unique client id + Timestamp time.Time `json:"timestamp"` + EventMessage string `json:"eventMessage,omitempty"` + EventType TelemetryEventType `json:"eventType"` + ServerVersion string `json:"serverVersion,omitempty"` + UserCount int `json:"userCount,omitempty"` + ClusterCount int `json:"clusterCount,omitempty"` + HostURL bool `json:"hostURL,omitempty"` + SSOLogin bool `json:"ssoLogin,omitempty"` + DevtronVersion string `json:"devtronVersion,omitempty"` + DevtronMode string `json:"devtronMode,omitempty"` + InstalledIntegrations []string `json:"installedIntegrations,omitempty"` + InstallFailedIntegrations []string `json:"installFailedIntegrations,omitempty"` + InstallTimedOutIntegrations []string `json:"installTimedOutIntegrations,omitempty"` + LastLoginTime time.Time `json:"LastLoginTime,omitempty"` + InstallingIntegrations []string `json:"installingIntegrations,omitempty"` + DevtronReleaseVersion string `json:"devtronReleaseVersion,omitempty"` + HelmAppAccessCounter string `json:"HelmAppAccessCounter,omitempty"` + HelmAppUpdateCounter string `json:"HelmAppUpdateCounter,omitempty"` + ChartStoreVisitCount string `json:"ChartStoreVisitCount,omitempty"` + SkippedOnboarding bool `json:"SkippedOnboarding"` + HelmChartSuccessfulDeploymentCount int `json:"helmChartSuccessfulDeploymentCount,omitempty"` + ExternalHelmAppClusterCount map[int32]int `json:"ExternalHelmAppClusterCount,omitempty"` + ClusterProvider string `json:"clusterProvider,omitempty"` +} + +const AppsCount int = 50 + +type TelemetryEventDto struct { + UCID string `json:"ucid"` //unique client id + Timestamp time.Time `json:"timestamp"` + EventMessage string `json:"eventMessage,omitempty"` + EventType TelemetryEventType `json:"eventType"` + ProdAppCount int `json:"prodAppCount,omitempty"` + NonProdAppCount int `json:"nonProdAppCount,omitempty"` + UserCount int `json:"userCount,omitempty"` + EnvironmentCount int `json:"environmentCount,omitempty"` + ClusterCount int `json:"clusterCount,omitempty"` + CiCreatedPerDay int `json:"ciCreatedPerDay"` + CdCreatedPerDay int `json:"cdCreatedPerDay"` + CiDeletedPerDay int `json:"ciDeletedPerDay"` + CdDeletedPerDay int `json:"cdDeletedPerDay"` + CiTriggeredPerDay int `json:"ciTriggeredPerDay"` + CdTriggeredPerDay int `json:"cdTriggeredPerDay"` + HelmChartCount int `json:"helmChartCount,omitempty"` + SecurityScanCountPerDay int `json:"securityScanCountPerDay,omitempty"` + GitAccountsCount int `json:"gitAccountsCount,omitempty"` + GitOpsCount int `json:"gitOpsCount,omitempty"` + RegistryCount int `json:"registryCount,omitempty"` + HostURL bool `json:"hostURL,omitempty"` + SSOLogin bool `json:"ssoLogin,omitempty"` + AppCount int `json:"appCount,omitempty"` + AppsWithGitRepoConfigured int `json:"appsWithGitRepoConfigured,omitempty"` + AppsWithDockerConfigured int `json:"appsWithDockerConfigured,omitempty"` + AppsWithDeploymentTemplateConfigured int `json:"appsWithDeploymentTemplateConfigured,omitempty"` + AppsWithCiPipelineConfigured int `json:"appsWithCiPipelineConfigured,omitempty"` + AppsWithCdPipelineConfigured int `json:"appsWithCdPipelineConfigured,omitempty"` + Build bool `json:"build,omitempty"` + Deployment bool `json:"deployment,omitempty"` + ServerVersion string `json:"serverVersion,omitempty"` + DevtronGitVersion string `json:"devtronGitVersion,omitempty"` + DevtronVersion string `json:"devtronVersion,omitempty"` + DevtronMode string `json:"devtronMode,omitempty"` + InstalledIntegrations []string `json:"installedIntegrations,omitempty"` + InstallFailedIntegrations []string `json:"installFailedIntegrations,omitempty"` + InstallTimedOutIntegrations []string `json:"installTimedOutIntegrations,omitempty"` + InstallingIntegrations []string `json:"installingIntegrations,omitempty"` + DevtronReleaseVersion string `json:"devtronReleaseVersion,omitempty"` + LastLoginTime time.Time `json:"LastLoginTime,omitempty"` + SelfDockerfileCount int `json:"selfDockerfileCount"` + ManagedDockerfileCount int `json:"managedDockerfileCount"` + BuildPackCount int `json:"buildPackCount"` + SelfDockerfileSuccessCount int `json:"selfDockerfileSuccessCount"` + SelfDockerfileFailureCount int `json:"selfDockerfileFailureCount"` + ManagedDockerfileSuccessCount int `json:"managedDockerfileSuccessCount"` + ManagedDockerfileFailureCount int `json:"managedDockerfileFailureCount"` + BuildPackSuccessCount int `json:"buildPackSuccessCount"` + BuildPackFailureCount int `json:"buildPackFailureCount"` + HelmAppAccessCounter string `json:"HelmAppAccessCounter,omitempty"` + ChartStoreVisitCount string `json:"ChartStoreVisitCount,omitempty"` + SkippedOnboarding bool `json:"SkippedOnboarding"` + HelmAppUpdateCounter string `json:"HelmAppUpdateCounter,omitempty"` + HelmChartSuccessfulDeploymentCount int `json:"helmChartSuccessfulDeploymentCount,omitempty"` + ExternalHelmAppClusterCount map[int32]int `json:"ExternalHelmAppClusterCount"` + ClusterProvider string `json:"clusterProvider,omitempty"` +} diff --git a/client/telemetry/PosthogClient.go b/client/telemetry/posthog/PosthogClient.go similarity index 71% rename from client/telemetry/PosthogClient.go rename to client/telemetry/posthog/PosthogClient.go index 565470dc5c..7e6213864f 100644 --- a/client/telemetry/PosthogClient.go +++ b/client/telemetry/posthog/PosthogClient.go @@ -14,11 +14,13 @@ * limitations under the License. */ -package telemetry +package posthog import ( + "context" "encoding/base64" "encoding/json" + "go.opentelemetry.io/otel" "time" "github.com/devtron-labs/devtron/util" @@ -32,26 +34,13 @@ type PosthogClient struct { cache *cache.Cache } -var ( - PosthogApiKey string = "" - PosthogEndpoint string = "https://app.posthog.com" - SummaryCronExpr string = "0 0 * * *" // Run once a day, midnight - HeartbeatCronExpr string = "0 0/6 * * *" - CacheExpiry int = 1440 - PosthogEncodedApiKey string = "" - IsOptOut bool = false -) - -const ( - TelemetryApiKeyEndpoint string = "aHR0cHM6Ly90ZWxlbWV0cnkuZGV2dHJvbi5haS9kZXZ0cm9uL3RlbGVtZXRyeS9wb3N0aG9nSW5mbw==" - TelemetryOptOutApiBaseUrl string = "aHR0cHM6Ly90ZWxlbWV0cnkuZGV2dHJvbi5haS9kZXZ0cm9uL3RlbGVtZXRyeS9vcHQtb3V0" - ResponseApiKey string = "PosthogApiKey" - ResponseUrlKey string = "PosthogEndpoint" -) +func (p *PosthogClient) GetCache() *cache.Cache { + return p.cache +} func NewPosthogClient(logger *zap.SugaredLogger) (*PosthogClient, error) { if PosthogApiKey == "" { - encodedApiKey, apiKey, posthogUrl, err := getPosthogApiKey(TelemetryApiKeyEndpoint, logger) + encodedApiKey, apiKey, posthogUrl, err := getPosthogApiKey(context.Background(), TelemetryApiKeyEndpoint, logger) if err != nil { logger.Errorw("exception caught while getting api key", "err", err) } else { @@ -75,14 +64,16 @@ func NewPosthogClient(logger *zap.SugaredLogger) (*PosthogClient, error) { return pgClient, nil } -func getPosthogApiKey(encodedPosthogApiKeyUrl string, logger *zap.SugaredLogger) (string, string, string, error) { +func getPosthogApiKey(ctx context.Context, encodedPosthogApiKeyUrl string, logger *zap.SugaredLogger) (string, string, string, error) { + newCtx, span := otel.Tracer("orchestrator").Start(ctx, "telemetry.getPosthogApiKey") + defer span.End() decodedPosthogApiKeyUrl, err := base64.StdEncoding.DecodeString(encodedPosthogApiKeyUrl) if err != nil { logger.Errorw("error fetching posthog api key, decode error", "err", err) return "", "", "", err } apiKeyUrl := string(decodedPosthogApiKeyUrl) - response, err := util.HttpRequest(apiKeyUrl) + response, err := util.HttpRequest(newCtx, apiKeyUrl) if err != nil { logger.Errorw("error fetching posthog api key, http call", "err", err) return "", "", "", err @@ -94,7 +85,7 @@ func getPosthogApiKey(encodedPosthogApiKeyUrl string, logger *zap.SugaredLogger) return "", "", "", err } var datamap map[string]string - if err := json.Unmarshal(posthogInfoByte, &datamap); err != nil { + if err = json.Unmarshal(posthogInfoByte, &datamap); err != nil { logger.Errorw("error while unmarshal data", "err", err) return "", "", "", err } diff --git a/client/telemetry/posthog/bean.go b/client/telemetry/posthog/bean.go new file mode 100644 index 0000000000..8910b7d8fe --- /dev/null +++ b/client/telemetry/posthog/bean.go @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2024. Devtron Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package posthog + +var ( + PosthogApiKey string = "" + PosthogEndpoint string = "https://app.posthog.com" + SummaryCronExpr string = "0 0 * * *" // Run once a day, midnight + HeartbeatCronExpr string = "0 0/6 * * *" + CacheExpiry int = 1440 + PosthogEncodedApiKey string = "" + IsOptOut bool = false +) + +const ( + TelemetryApiKeyEndpoint string = "aHR0cHM6Ly90ZWxlbWV0cnkuZGV2dHJvbi5haS9kZXZ0cm9uL3RlbGVtZXRyeS9wb3N0aG9nSW5mbw==" + TelemetryOptOutApiBaseUrl string = "aHR0cHM6Ly90ZWxlbWV0cnkuZGV2dHJvbi5haS9kZXZ0cm9uL3RlbGVtZXRyeS9vcHQtb3V0" + ResponseApiKey string = "PosthogApiKey" + ResponseUrlKey string = "PosthogEndpoint" +) diff --git a/cmd/external-app/externalApp.go b/cmd/external-app/externalApp.go index b7f90fb2dd..8d5ee62cb7 100644 --- a/cmd/external-app/externalApp.go +++ b/cmd/external-app/externalApp.go @@ -20,6 +20,7 @@ import ( "context" "errors" "fmt" + "github.com/devtron-labs/devtron/client/telemetry/posthog" "net/http" "os" "time" @@ -40,14 +41,14 @@ type App struct { Logger *zap.SugaredLogger server *http.Server telemetry telemetry.TelemetryEventClient - posthogClient *telemetry.PosthogClient + posthogClient *posthog.PosthogClient } func NewApp(db *pg.DB, sessionManager *authMiddleware.SessionManager, MuxRouter *MuxRouter, telemetry telemetry.TelemetryEventClient, - posthogClient *telemetry.PosthogClient, + posthogClient *posthog.PosthogClient, Logger *zap.SugaredLogger) *App { return &App{ db: db, diff --git a/cmd/external-app/wire.go b/cmd/external-app/wire.go index 4d05bdbbda..4dc491cd7f 100644 --- a/cmd/external-app/wire.go +++ b/cmd/external-app/wire.go @@ -60,6 +60,7 @@ import ( "github.com/devtron-labs/devtron/client/argocdServer/session" "github.com/devtron-labs/devtron/client/dashboard" "github.com/devtron-labs/devtron/client/telemetry" + "github.com/devtron-labs/devtron/client/telemetry/posthog" "github.com/devtron-labs/devtron/internal/sql/repository" app2 "github.com/devtron-labs/devtron/internal/sql/repository/app" "github.com/devtron-labs/devtron/internal/sql/repository/appStatus" @@ -86,6 +87,7 @@ import ( "github.com/devtron-labs/devtron/pkg/policyGovernance/security/scanTool" security2 "github.com/devtron-labs/devtron/pkg/policyGovernance/security/scanTool/repository" "github.com/devtron-labs/devtron/pkg/sql" + "github.com/devtron-labs/devtron/pkg/ucid" util2 "github.com/devtron-labs/devtron/pkg/util" util3 "github.com/devtron-labs/devtron/util" "github.com/devtron-labs/devtron/util/commonEnforcementFunctionsUtil" @@ -131,7 +133,8 @@ func InitializeApp() (*App, error) { util.NewSugardLogger, util.IntValidator, util2.GetACDAuthConfig, - telemetry.NewPosthogClient, + posthog.NewPosthogClient, + ucid.WireSet, delete2.NewDeleteServiceImpl, gitMaterial.GitMaterialWireSet, scanTool.ScanToolWireSet, diff --git a/cmd/external-app/wire_gen.go b/cmd/external-app/wire_gen.go index b0a26de083..52ff9e5076 100644 --- a/cmd/external-app/wire_gen.go +++ b/cmd/external-app/wire_gen.go @@ -52,6 +52,7 @@ import ( "github.com/devtron-labs/devtron/client/argocdServer/repoCredsK8sClient" "github.com/devtron-labs/devtron/client/dashboard" "github.com/devtron-labs/devtron/client/telemetry" + "github.com/devtron-labs/devtron/client/telemetry/posthog" repository5 "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/appStatus" @@ -129,6 +130,7 @@ import ( "github.com/devtron-labs/devtron/pkg/team/read" repository2 "github.com/devtron-labs/devtron/pkg/team/repository" "github.com/devtron-labs/devtron/pkg/terminal" + "github.com/devtron-labs/devtron/pkg/ucid" "github.com/devtron-labs/devtron/pkg/userResource" util3 "github.com/devtron-labs/devtron/pkg/util" "github.com/devtron-labs/devtron/pkg/webhook/helm" @@ -384,12 +386,13 @@ func InitializeApp() (*App, error) { chartProviderRouterImpl := chartProvider2.NewChartProviderRouterImpl(chartProviderRestHandlerImpl) dockerRegRestHandlerImpl := restHandler.NewDockerRegRestHandlerImpl(dockerRegistryConfigImpl, sugaredLogger, chartProviderServiceImpl, userServiceImpl, validate, enforcerImpl, teamServiceImpl, deleteServiceImpl) dockerRegRouterImpl := router.NewDockerRegRouterImpl(dockerRegRestHandlerImpl) - posthogClient, err := telemetry.NewPosthogClient(sugaredLogger) + posthogClient, err := posthog.NewPosthogClient(sugaredLogger) if err != nil { return nil, err } + serviceImpl := ucid.NewServiceImpl(sugaredLogger, posthogClient, k8sServiceImpl, acdAuthConfig) providerIdentifierServiceImpl := providerIdentifier.NewProviderIdentifierServiceImpl(sugaredLogger) - telemetryEventClientImpl, err := telemetry.NewTelemetryEventClientImpl(sugaredLogger, httpClient, clusterServiceImpl, k8sServiceImpl, acdAuthConfig, userServiceImpl, attributesRepositoryImpl, ssoLoginServiceImpl, posthogClient, moduleRepositoryImpl, serverDataStoreServerDataStore, userAuditServiceImpl, helmAppClientImpl, providerIdentifierServiceImpl, cronLoggerImpl, installedAppReadServiceEAImpl, environmentVariables) + telemetryEventClientImpl, err := telemetry.NewTelemetryEventClientImpl(sugaredLogger, httpClient, clusterServiceImpl, k8sServiceImpl, acdAuthConfig, userServiceImpl, attributesRepositoryImpl, ssoLoginServiceImpl, posthogClient, serviceImpl, moduleRepositoryImpl, serverDataStoreServerDataStore, userAuditServiceImpl, helmAppClientImpl, providerIdentifierServiceImpl, cronLoggerImpl, installedAppReadServiceEAImpl, environmentVariables) if err != nil { return nil, err } diff --git a/go.mod b/go.mod index baafc62c9e..c9ccd0dd10 100644 --- a/go.mod +++ b/go.mod @@ -32,7 +32,7 @@ require ( github.com/go-pg/pg v6.15.1+incompatible github.com/go-resty/resty/v2 v2.7.0 github.com/gogo/protobuf v1.3.2 - github.com/golang-jwt/jwt/v4 v4.5.1 + github.com/golang-jwt/jwt/v4 v4.5.2 github.com/golang/mock v1.6.0 github.com/golang/protobuf v1.5.4 github.com/google/cel-go v0.17.8 @@ -306,9 +306,9 @@ require ( ) replace ( - github.com/argoproj/argo-workflows/v3 v3.5.13 => github.com/devtron-labs/argo-workflows/v3 v3.5.13 - github.com/devtron-labs/authenticator => github.com/devtron-labs/devtron-services/authenticator v0.0.0-20250402105331-120c20ff29d9 - github.com/devtron-labs/common-lib => github.com/devtron-labs/devtron-services/common-lib v0.0.0-20250402105331-120c20ff29d9 + github.com/argoproj/argo-workflows/v3 => github.com/devtron-labs/argo-workflows/v3 v3.5.13 + github.com/devtron-labs/authenticator => github.com/devtron-labs/devtron-services/authenticator v0.0.0-20250402155428-3fa1ffc068e2 + github.com/devtron-labs/common-lib => github.com/devtron-labs/devtron-services/common-lib v0.0.0-20250402155428-3fa1ffc068e2 github.com/go-check/check => github.com/go-check/check v0.0.0-20180628173108-788fd7840127 github.com/googleapis/gnostic => github.com/googleapis/gnostic v0.5.5 k8s.io/api => k8s.io/api v0.29.7 diff --git a/go.sum b/go.sum index c12064620f..9b29696f0c 100644 --- a/go.sum +++ b/go.sum @@ -829,10 +829,10 @@ github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc h1:VRRKCwnzq github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/devtron-labs/argo-workflows/v3 v3.5.13 h1:3pINq0gXOSeTw2z/vYe+j80lRpSN5Rp/8mfQORh8SmU= github.com/devtron-labs/argo-workflows/v3 v3.5.13/go.mod h1:/vqxcovDPT4zqr4DjR5v7CF8ggpY1l3TSa2CIG3jmjA= -github.com/devtron-labs/devtron-services/authenticator v0.0.0-20250402105331-120c20ff29d9 h1:Imo0tZ6diaOwFzwJZWJkadEgrFO41gcOIGUmhYT4SUc= -github.com/devtron-labs/devtron-services/authenticator v0.0.0-20250402105331-120c20ff29d9/go.mod h1:5lv4Wfj5ERhhvDGXe2IeES6qxjvUVCcohaRwKnWBMNo= -github.com/devtron-labs/devtron-services/common-lib v0.0.0-20250402105331-120c20ff29d9 h1:sMbW7oI9AL40MH9jcz4S4szyGs3LwmgcIU0UrReRZbw= -github.com/devtron-labs/devtron-services/common-lib v0.0.0-20250402105331-120c20ff29d9/go.mod h1:ceFKgQ2qm40PR95g5Xp2EClq7nDBKFTcglJ0JdsgClA= +github.com/devtron-labs/devtron-services/authenticator v0.0.0-20250402155428-3fa1ffc068e2 h1:Ik3LiAVccf6gqrbEwryD/uPYbSV/i7z4UTvYcLgM8jk= +github.com/devtron-labs/devtron-services/authenticator v0.0.0-20250402155428-3fa1ffc068e2/go.mod h1:FfaLDXN1ZXxyRpnskBqVIYkpkWDCzBmDgIO9xqLnxdQ= +github.com/devtron-labs/devtron-services/common-lib v0.0.0-20250402155428-3fa1ffc068e2 h1:k2bWvWk6if6I7k+URmrh1Dp2fleNDNu/pl+ZnImeUGE= +github.com/devtron-labs/devtron-services/common-lib v0.0.0-20250402155428-3fa1ffc068e2/go.mod h1:zkNShlkcHxsmnL0gKNbs0uyRL8lZonGKr5Km63uTLI0= github.com/devtron-labs/go-bitbucket v0.9.60-beta h1:VEx1jvDgdtDPS6A1uUFoaEi0l1/oLhbr+90xOwr6sDU= github.com/devtron-labs/go-bitbucket v0.9.60-beta/go.mod h1:GnuiCesvh8xyHeMCb+twm8lBR/kQzJYSKL28ZfObp1Y= github.com/devtron-labs/protos v0.0.3-0.20250323220609-ecf8a0f7305e h1:U6UdYbW8a7xn5IzFPd8cywjVVPfutGJCudjePAfL/Hs= @@ -993,8 +993,8 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo= -github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI= +github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= diff --git a/pkg/appStore/installedApp/service/FullMode/deployment/InstalledAppArgoCdService.go b/pkg/appStore/installedApp/service/FullMode/deployment/InstalledAppArgoCdService.go index 9b637360f0..05c6b07ef2 100644 --- a/pkg/appStore/installedApp/service/FullMode/deployment/InstalledAppArgoCdService.go +++ b/pkg/appStore/installedApp/service/FullMode/deployment/InstalledAppArgoCdService.go @@ -25,7 +25,7 @@ import ( "github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig/bean/timelineStatus" "github.com/devtron-labs/devtron/internal/util" appStoreBean "github.com/devtron-labs/devtron/pkg/appStore/bean" - cluster2 "github.com/devtron-labs/devtron/pkg/cluster" + bean2 "github.com/devtron-labs/devtron/pkg/cluster/bean" "github.com/devtron-labs/devtron/pkg/cluster/environment/bean" commonBean "github.com/devtron-labs/devtron/pkg/deployment/gitOps/common/bean" util2 "github.com/devtron-labs/devtron/util" @@ -167,7 +167,7 @@ func (impl *FullModeDeploymentServiceImpl) DeleteACD(acdAppName string, ctx cont func (impl *FullModeDeploymentServiceImpl) createInArgo(ctx context.Context, chartGitAttribute *commonBean.ChartGitAttribute, envModel bean.EnvironmentBean, argocdAppName string) error { appNamespace := envModel.Namespace if appNamespace == "" { - appNamespace = cluster2.DEFAULT_NAMESPACE + appNamespace = bean2.DefaultNamespace } appReq := &argocdServer.AppTemplate{ ApplicationName: argocdAppName, diff --git a/pkg/chartRepo/ChartRepositoryService.go b/pkg/chartRepo/ChartRepositoryService.go index 1df2c48e43..8cdef0a9fd 100644 --- a/pkg/chartRepo/ChartRepositoryService.go +++ b/pkg/chartRepo/ChartRepositoryService.go @@ -501,7 +501,7 @@ func (impl *ChartRepositoryServiceImpl) ValidateAndUpdateChartRepo(request *Char } func (impl *ChartRepositoryServiceImpl) TriggerChartSyncManual(chartProviderConfig *ChartProviderConfig) error { - defaultClusterBean, err := impl.clusterReadService.FindOne(bean2.DEFAULT_CLUSTER) + defaultClusterBean, err := impl.clusterReadService.FindOne(bean2.DefaultCluster) if err != nil { impl.logger.Errorw("defaultClusterBean err, TriggerChartSyncManual", "err", err) return err diff --git a/pkg/cluster/ClusterService.go b/pkg/cluster/ClusterService.go index 9bab50066a..1b00c2f84f 100644 --- a/pkg/cluster/ClusterService.go +++ b/pkg/cluster/ClusterService.go @@ -20,6 +20,7 @@ import ( "context" "encoding/json" "fmt" + informerBean "github.com/devtron-labs/common-lib/informer" "github.com/devtron-labs/common-lib/utils/k8s/commonBean" "github.com/devtron-labs/devtron/pkg/cluster/adapter" "github.com/devtron-labs/devtron/pkg/cluster/bean" @@ -28,7 +29,6 @@ import ( cronUtil "github.com/devtron-labs/devtron/util/cron" "github.com/robfig/cron/v3" "log" - "net/http" "net/url" "sync" "time" @@ -38,8 +38,8 @@ import ( casbin2 "github.com/devtron-labs/devtron/pkg/auth/authorisation/casbin" repository3 "github.com/devtron-labs/devtron/pkg/auth/user/repository" "github.com/devtron-labs/devtron/pkg/k8s/informer" - errors1 "github.com/juju/errors" - "k8s.io/apimachinery/pkg/api/errors" + customErr "github.com/juju/errors" + k8sError "k8s.io/apimachinery/pkg/api/errors" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/kubernetes" @@ -56,18 +56,6 @@ import ( "go.uber.org/zap" ) -const ( - DEFAULT_CLUSTER = "default_cluster" - DEFAULT_NAMESPACE = "default" - CLUSTER_MODIFY_EVENT_SECRET_TYPE = "cluster.request/modify" - CLUSTER_ACTION_ADD = "add" - CLUSTER_ACTION_UPDATE = "update" - SECRET_FIELD_CLUSTER_ID = "cluster_id" - SECRET_FIELD_UPDATED_ON = "updated_on" - SECRET_FIELD_ACTION = "action" - TokenFilePath = "/var/run/secrets/kubernetes.io/serviceaccount/token" -) - type ClusterService interface { Save(parent context.Context, bean *bean.ClusterBean, userId int32) (*bean.ClusterBean, error) UpdateClusterDescription(bean *bean.ClusterBean, userId int32) error @@ -195,7 +183,7 @@ func (impl *ClusterServiceImpl) Save(parent context.Context, bean *bean.ClusterB if err != nil { if len(err.Error()) > 2000 { - err = errors.NewBadRequest("unable to connect to cluster") + err = k8sError.NewBadRequest("unable to connect to cluster") } return nil, err } @@ -248,16 +236,16 @@ func (impl *ClusterServiceImpl) Save(parent context.Context, bean *bean.ClusterB secretName := ParseSecretNameForKubelinkInformer(bean.Id) data := make(map[string][]byte) - data[SECRET_FIELD_CLUSTER_ID] = []byte(fmt.Sprintf("%v", bean.Id)) - data[SECRET_FIELD_ACTION] = []byte(CLUSTER_ACTION_ADD) - data[SECRET_FIELD_UPDATED_ON] = []byte(time.Now().String()) // this field will ensure that informer detects change as other fields can be constant even if cluster config changes - _, err = impl.K8sUtil.CreateSecret(DEFAULT_NAMESPACE, data, secretName, CLUSTER_MODIFY_EVENT_SECRET_TYPE, k8sClient, nil, nil) + data[informerBean.SecretFieldClusterId] = []byte(fmt.Sprintf("%v", bean.Id)) + data[informerBean.SecretFieldAction] = []byte(informerBean.ClusterActionAdd) + data[clusterBean.SecretFieldUpdatedOn] = []byte(time.Now().String()) // this field will ensure that informer detects change as other fields can be constant even if cluster config changes + // TODO Asutosh: Why not UPSERT ?? + _, err = impl.K8sUtil.CreateSecret(clusterBean.DefaultNamespace, data, secretName, informerBean.ClusterModifyEventSecretType, k8sClient, nil, nil) if err != nil { - impl.logger.Errorw("error in updating secret for informers") + impl.logger.Errorw("error in creating secret for informers", "secretName", secretName, "err", err) return bean, nil } - - return bean, err + return bean, nil } // UpdateClusterDescription is new api service logic to only update description, this should be done in cluster update operation only @@ -415,7 +403,7 @@ func (impl *ClusterServiceImpl) Update(ctx context.Context, bean *bean.ClusterBe } if bean.ServerUrl != model.ServerUrl || bean.InsecureSkipTLSVerify != model.InsecureSkipTlsVerify || dbConfigBearerToken != requestConfigBearerToken || dbConfigTlsKey != requestConfigTlsKey || dbConfigCertData != requestConfigCertData || dbConfigCAData != requestConfigCAData { - if bean.ClusterName == clusterBean.DEFAULT_CLUSTER { + if bean.ClusterName == clusterBean.DefaultCluster { impl.logger.Errorw("default_cluster is reserved by the system and cannot be updated, default_cluster", "name", bean.ClusterName) return nil, fmt.Errorf("default_cluster is reserved by the system and cannot be updated") } @@ -480,37 +468,47 @@ func (impl *ClusterServiceImpl) Update(ctx context.Context, bean *bean.ClusterBe impl.SyncNsInformer(bean) } impl.logger.Infow("saving secret for cluster informer") + if bean.HasConfigOrUrlChanged { + data := make(map[string][]byte) + data[informerBean.SecretFieldClusterId] = []byte(fmt.Sprintf("%v", bean.Id)) + data[informerBean.SecretFieldAction] = []byte(informerBean.ClusterActionUpdate) + data[clusterBean.SecretFieldUpdatedOn] = []byte(time.Now().String()) // this field will ensure that informer detects change as other fields can be constant even if cluster config changes + if err = impl.upsertClusterSecret(bean, data); err != nil { + impl.logger.Errorw("error upserting cluster secret", "data", data, "err", err) + // TODO Asutosh: why error is not propagated ?? + return bean, nil + } + } + return bean, nil +} + +func (impl *ClusterServiceImpl) upsertClusterSecret(bean *bean.ClusterBean, data map[string][]byte) error { k8sClient, err := impl.K8sUtil.GetCoreV1ClientInCluster() if err != nil { - return bean, nil + impl.logger.Errorw("error in getting k8s client", "err", err) + return err } - // below secret will act as an event for informer running on secret object in kubelink - if bean.HasConfigOrUrlChanged { - secretName := ParseSecretNameForKubelinkInformer(bean.Id) - secret, err := impl.K8sUtil.GetSecret(DEFAULT_NAMESPACE, secretName, k8sClient) - statusError, _ := err.(*errors.StatusError) - if err != nil && statusError.Status().Code != http.StatusNotFound { - impl.logger.Errorw("secret not found", "err", err) - return bean, nil + // below secret will act as an event for informer running on a secret object in kubelink and kubewatch + secretName := ParseSecretNameForKubelinkInformer(bean.Id) + secret, err := impl.K8sUtil.GetSecret(clusterBean.DefaultNamespace, secretName, k8sClient) + if err != nil && !k8sError.IsNotFound(err) { + impl.logger.Errorw("error in getting cluster secret", "secretName", secretName, "err", err) + return err + } else if k8sError.IsNotFound(err) { + _, err = impl.K8sUtil.CreateSecret(clusterBean.DefaultNamespace, data, secretName, informerBean.ClusterModifyEventSecretType, k8sClient, nil, nil) + if err != nil { + impl.logger.Errorw("error in creating secret for informers", "secretName", secretName, "err", err) + return err } - data := make(map[string][]byte) - data[SECRET_FIELD_CLUSTER_ID] = []byte(fmt.Sprintf("%v", bean.Id)) - data[SECRET_FIELD_ACTION] = []byte(CLUSTER_ACTION_UPDATE) - data[SECRET_FIELD_UPDATED_ON] = []byte(time.Now().String()) // this field will ensure that informer detects change as other fields can be constant even if cluster config changes - if secret == nil { - _, err = impl.K8sUtil.CreateSecret(DEFAULT_NAMESPACE, data, secretName, CLUSTER_MODIFY_EVENT_SECRET_TYPE, k8sClient, nil, nil) - if err != nil { - impl.logger.Errorw("error in creating secret for informers") - } - } else { - secret.Data = data - secret, err = impl.K8sUtil.UpdateSecret(DEFAULT_NAMESPACE, secret, k8sClient) - if err != nil { - impl.logger.Errorw("error in updating secret for informers") - } + } else { + secret.Data = data + secret, err = impl.K8sUtil.UpdateSecret(clusterBean.DefaultNamespace, secret, k8sClient) + if err != nil { + impl.logger.Errorw("error in updating secret for informers", "secretName", secretName, "err", err) + return err } } - return bean, nil + return nil } func (impl *ClusterServiceImpl) SyncNsInformer(bean *bean.ClusterBean) { @@ -609,8 +607,9 @@ func (impl *ClusterServiceImpl) DeleteFromDb(bean *bean.ClusterBean, userId int3 impl.logger.Errorw("error in getting in cluster k8s client", "err", err, "clusterName", bean.ClusterName) return "", nil } + // TODO Asutosh: why we maintain this duplicate code ?? secretName := ParseSecretNameForKubelinkInformer(bean.Id) - err = impl.K8sUtil.DeleteSecret(DEFAULT_NAMESPACE, secretName, k8sClient) + err = impl.K8sUtil.DeleteSecret(clusterBean.DefaultNamespace, secretName, k8sClient) impl.logger.Errorw("error in deleting secret", "error", err) return existingCluster.ClusterName, nil } @@ -621,7 +620,7 @@ func (impl *ClusterServiceImpl) CheckIfConfigIsValid(cluster *bean.ClusterBean) if err != nil { if _, ok := err.(*url.Error); ok { return fmt.Errorf("Incorrect server url : %v", err) - } else if statusError, ok := err.(*errors.StatusError); ok { + } else if statusError, ok := err.(*k8sError.StatusError); ok { if statusError != nil { errReason := statusError.ErrStatus.Reason var errMsg string @@ -850,16 +849,16 @@ func (impl *ClusterServiceImpl) ValidateKubeconfig(kubeConfig string) (map[strin err := json.Unmarshal([]byte(kubeConfig), &kubeConfigDataMap) if err != nil { impl.logger.Errorw("error in unmarshalling kubeConfig") - return nil, errors1.New("invalid kubeConfig found , " + err.Error()) + return nil, customErr.New("invalid kubeConfig found , " + err.Error()) } if kubeConfigDataMap["apiVersion"] == nil { impl.logger.Errorw("api version missing from kubeConfig") - return nil, errors1.New("api version missing from kubeConfig") + return nil, customErr.New("api version missing from kubeConfig") } if kubeConfigDataMap["kind"] == nil { impl.logger.Errorw("kind missing from kubeConfig") - return nil, errors1.New("kind missing from kubeConfig") + return nil, customErr.New("kind missing from kubeConfig") } gvk.Version = kubeConfigDataMap["apiVersion"].(string) @@ -909,7 +908,7 @@ func (impl *ClusterServiceImpl) ValidateKubeconfig(kubeConfig string) (map[strin clusterBeanObject.ErrorInConnecting = "cluster name missing from kubeconfig" } - if clusterBeanObject.ClusterName == clusterBean.DEFAULT_CLUSTER { + if clusterBeanObject.ClusterName == clusterBean.DefaultCluster { clusterBeanObject.ErrorInConnecting = "default_cluster is reserved by the system and cannot be updated" } @@ -1000,7 +999,7 @@ func (impl *ClusterServiceImpl) ValidateKubeconfig(kubeConfig string) (map[strin if len(ValidateObjects) == 0 { impl.logger.Errorw("No valid cluster object provided in kubeconfig for context", "context", kubeConfig) - return nil, errors1.New("No valid cluster object provided in kubeconfig for context") + return nil, customErr.New("No valid cluster object provided in kubeconfig for context") } else { return ValidateObjects, nil } @@ -1014,7 +1013,7 @@ func (impl *ClusterServiceImpl) GetAndUpdateConnectionStatusForOneCluster(k8sCli if err != nil { if _, ok := err.(*url.Error); ok { err = fmt.Errorf("Incorrect server url : %v", err) - } else if statusError, ok := err.(*errors.StatusError); ok { + } else if statusError, ok := err.(*k8sError.StatusError); ok { if statusError != nil { errReason := statusError.ErrStatus.Reason var errMsg string diff --git a/pkg/cluster/bean/bean.go b/pkg/cluster/bean/bean.go index 6548613adb..a2438a2b44 100644 --- a/pkg/cluster/bean/bean.go +++ b/pkg/cluster/bean/bean.go @@ -7,7 +7,7 @@ import ( const ( DefaultClusterId = 1 - DEFAULT_CLUSTER = "default_cluster" + DefaultCluster = "default_cluster" ) type PrometheusAuth struct { @@ -81,3 +81,8 @@ type DefaultClusterComponent struct { EnvName string `json:"envName"` Status string `json:"status"` } + +const ( + DefaultNamespace = "default" + SecretFieldUpdatedOn = "updated_on" +) diff --git a/pkg/cluster/clusterUtil.go b/pkg/cluster/clusterUtil.go index 102519ff19..48ed681400 100644 --- a/pkg/cluster/clusterUtil.go +++ b/pkg/cluster/clusterUtil.go @@ -3,9 +3,9 @@ package cluster import "fmt" const ( - SECRET_NAME = "cluster-event" + SecretName = "cluster-event" ) func ParseSecretNameForKubelinkInformer(clusterId int) string { - return fmt.Sprintf("%s-%d", SECRET_NAME, clusterId) + return fmt.Sprintf("%s-%d", SecretName, clusterId) } diff --git a/pkg/delete/DeleteService.go b/pkg/delete/DeleteService.go index e9a53b3922..278d4182d0 100644 --- a/pkg/delete/DeleteService.go +++ b/pkg/delete/DeleteService.go @@ -108,7 +108,7 @@ func (impl DeleteServiceImpl) DeleteClusterSecret(deleteRequest *bean2.ClusterBe return nil } secretName := cluster.ParseSecretNameForKubelinkInformer(deleteRequest.Id) - err = impl.K8sUtil.DeleteSecret(cluster.DEFAULT_NAMESPACE, secretName, k8sClient) + err = impl.K8sUtil.DeleteSecret(bean2.DefaultNamespace, secretName, k8sClient) return err } diff --git a/pkg/eventProcessor/bean/workflowEventBean.go b/pkg/eventProcessor/bean/workflowEventBean.go index 4b33b8cba4..ddf532fd72 100644 --- a/pkg/eventProcessor/bean/workflowEventBean.go +++ b/pkg/eventProcessor/bean/workflowEventBean.go @@ -19,6 +19,7 @@ package bean import ( "context" "encoding/json" + "github.com/argoproj/argo-workflows/v3/pkg/apis/workflow/v1alpha1" "github.com/devtron-labs/common-lib/utils/registry" "github.com/devtron-labs/devtron/api/bean" "github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig" @@ -114,3 +115,8 @@ type DevtronAppReleaseContextType struct { CancelContext context.CancelCauseFunc RunnerId int } + +type CiCdStatus struct { + DevtronAdministratorInstance string `json:"devtronAdministratorInstance"` + *v1alpha1.WorkflowStatus +} diff --git a/pkg/eventProcessor/in/WorkflowEventProcessorService.go b/pkg/eventProcessor/in/WorkflowEventProcessorService.go index d91bd56caf..45ed82b9c2 100644 --- a/pkg/eventProcessor/in/WorkflowEventProcessorService.go +++ b/pkg/eventProcessor/in/WorkflowEventProcessorService.go @@ -18,6 +18,7 @@ package in import ( "context" + "encoding/base64" "encoding/json" "errors" "fmt" @@ -46,6 +47,7 @@ import ( eventProcessorBean "github.com/devtron-labs/devtron/pkg/eventProcessor/out/bean" "github.com/devtron-labs/devtron/pkg/pipeline" "github.com/devtron-labs/devtron/pkg/pipeline/executors" + "github.com/devtron-labs/devtron/pkg/ucid" "github.com/devtron-labs/devtron/pkg/workflow/cd" "github.com/devtron-labs/devtron/pkg/workflow/cd/adapter" cdWorkflowBean "github.com/devtron-labs/devtron/pkg/workflow/cd/bean" @@ -86,6 +88,7 @@ type WorkflowEventProcessorImpl struct { cdWorkflowCommonService cd.CdWorkflowCommonService cdPipelineConfigService pipeline.CdPipelineConfigService userDeploymentRequestService service.UserDeploymentRequestService + ucid ucid.Service devtronAppReleaseContextMap map[int]bean.DevtronAppReleaseContextType devtronAppReleaseContextMapLock *sync.Mutex @@ -115,6 +118,7 @@ func NewWorkflowEventProcessorImpl(logger *zap.SugaredLogger, cdWorkflowCommonService cd.CdWorkflowCommonService, cdPipelineConfigService pipeline.CdPipelineConfigService, userDeploymentRequestService service.UserDeploymentRequestService, + ucid ucid.Service, pipelineRepository pipelineConfig.PipelineRepository, ciArtifactRepository repository.CiArtifactRepository, cdWorkflowRepository pipelineConfig.CdWorkflowRepository, @@ -139,6 +143,7 @@ func NewWorkflowEventProcessorImpl(logger *zap.SugaredLogger, cdWorkflowCommonService: cdWorkflowCommonService, cdPipelineConfigService: cdPipelineConfigService, userDeploymentRequestService: userDeploymentRequestService, + ucid: ucid, devtronAppReleaseContextMap: make(map[int]bean.DevtronAppReleaseContextType), devtronAppReleaseContextMapLock: &sync.Mutex{}, pipelineRepository: pipelineRepository, @@ -387,13 +392,28 @@ func (impl *WorkflowEventProcessorImpl) SubscribeHibernateBulkAction() error { func (impl *WorkflowEventProcessorImpl) SubscribeCIWorkflowStatusUpdate() error { callback := func(msg *model.PubSubMsg) { - wfStatus := v1alpha1.WorkflowStatus{} + wfStatus := bean.CiCdStatus{} err := json.Unmarshal([]byte(msg.Data), &wfStatus) if err != nil { impl.logger.Errorw("error while unmarshalling wf status update", "err", err, "msg", msg.Data) return } - + if len(wfStatus.DevtronAdministratorInstance) != 0 { + devtronUCID, _, err := impl.ucid.GetUCID() + if err != nil { + impl.logger.Errorw("error in getting UCID", "err", err) + return + } + decodedUCID, err := base64.StdEncoding.DecodeString(wfStatus.DevtronAdministratorInstance) + if err != nil { + impl.logger.Errorw("error in decoding UCID", "err", err) + return + } + if string(decodedUCID) != devtronUCID { + impl.logger.Warnw("mis match in UCID. skipping...", "decodedUCID", string(decodedUCID), "devtronUCID", devtronUCID) + return + } + } err = impl.ciHandler.CheckAndReTriggerCI(wfStatus) if err != nil { impl.logger.Errorw("error in checking and re triggering ci", "err", err) @@ -410,7 +430,7 @@ func (impl *WorkflowEventProcessorImpl) SubscribeCIWorkflowStatusUpdate() error // add required logging here var loggerFunc pubsub.LoggerFunc = func(msg model.PubSubMsg) (string, []interface{}) { - wfStatus := v1alpha1.WorkflowStatus{} + wfStatus := bean.CiCdStatus{} err := json.Unmarshal([]byte(msg.Data), &wfStatus) if err != nil { return "error while unmarshalling wf status update", []interface{}{"err", err, "msg", msg.Data} @@ -431,13 +451,28 @@ func (impl *WorkflowEventProcessorImpl) SubscribeCIWorkflowStatusUpdate() error func (impl *WorkflowEventProcessorImpl) SubscribeCDWorkflowStatusUpdate() error { callback := func(msg *model.PubSubMsg) { - wfStatus := v1alpha1.WorkflowStatus{} + wfStatus := bean.CiCdStatus{} err := json.Unmarshal([]byte(msg.Data), &wfStatus) if err != nil { impl.logger.Error("Error while unmarshalling wfStatus json object", "error", err) return } - + if len(wfStatus.DevtronAdministratorInstance) != 0 { + devtronUCID, _, err := impl.ucid.GetUCID() + if err != nil { + impl.logger.Errorw("error in getting UCID", "err", err) + return + } + decodedUCID, err := base64.StdEncoding.DecodeString(wfStatus.DevtronAdministratorInstance) + if err != nil { + impl.logger.Errorw("error in decoding UCID", "err", err) + return + } + if string(decodedUCID) != devtronUCID { + impl.logger.Warnw("mis match in UCID. skipping...", "decodedUCID", string(decodedUCID), "devtronUCID", devtronUCID) + return + } + } wfrId, wfrStatus, stateChanged, err := impl.cdHandler.UpdateWorkflow(wfStatus) impl.logger.Debugw("UpdateWorkflow", "wfrId", wfrId, "wfrStatus", wfrStatus) if err != nil { @@ -492,7 +527,7 @@ func (impl *WorkflowEventProcessorImpl) SubscribeCDWorkflowStatusUpdate() error // add required logging here var loggerFunc pubsub.LoggerFunc = func(msg model.PubSubMsg) (string, []interface{}) { - wfStatus := v1alpha1.WorkflowStatus{} + wfStatus := bean.CiCdStatus{} err := json.Unmarshal([]byte(msg.Data), &wfStatus) if err != nil { return "error while unmarshalling wfStatus json object", []interface{}{"error", err} diff --git a/pkg/gitops/GitOpsConfigService.go b/pkg/gitops/GitOpsConfigService.go index a0776f75b3..f095136674 100644 --- a/pkg/gitops/GitOpsConfigService.go +++ b/pkg/gitops/GitOpsConfigService.go @@ -251,7 +251,7 @@ func (impl *GitOpsConfigServiceImpl) registerGitOpsClientConfig(ctx context.Cont } } else { - clusterBean, err := impl.clusterReadService.FindOne(bean2.DEFAULT_CLUSTER) + clusterBean, err := impl.clusterReadService.FindOne(bean2.DefaultCluster) if err != nil { return nil, err } @@ -538,7 +538,7 @@ func (impl *GitOpsConfigServiceImpl) patchGitOpsClientConfig(model *repository.G } } else { - clusterBean, err := impl.clusterReadService.FindOne(bean2.DEFAULT_CLUSTER) + clusterBean, err := impl.clusterReadService.FindOne(bean2.DefaultCluster) if err != nil { return err } diff --git a/pkg/pipeline/CdHandler.go b/pkg/pipeline/CdHandler.go index ba2618db49..e11c2ca76e 100644 --- a/pkg/pipeline/CdHandler.go +++ b/pkg/pipeline/CdHandler.go @@ -30,6 +30,7 @@ import ( bean3 "github.com/devtron-labs/devtron/pkg/cluster/bean" repository3 "github.com/devtron-labs/devtron/pkg/cluster/environment/repository" common2 "github.com/devtron-labs/devtron/pkg/deployment/common" + bean6 "github.com/devtron-labs/devtron/pkg/eventProcessor/bean" "github.com/devtron-labs/devtron/pkg/pipeline/constants" util2 "github.com/devtron-labs/devtron/pkg/pipeline/util" "github.com/devtron-labs/devtron/pkg/pipeline/workflowStatus" @@ -69,7 +70,7 @@ const ( ) type CdHandler interface { - UpdateWorkflow(workflowStatus v1alpha1.WorkflowStatus) (int, string, bool, error) + UpdateWorkflow(workflowStatus bean6.CiCdStatus) (int, string, bool, error) GetCdBuildHistory(appId int, environmentId int, pipelineId int, offset int, size int) ([]pipelineBean.CdWorkflowWithArtifact, error) GetRunningWorkflowLogs(environmentId int, pipelineId int, workflowId int) (*bufio.Reader, func() error, error) FetchCdWorkflowDetails(appId int, environmentId int, pipelineId int, buildId int) (types.WorkflowResponse, error) @@ -265,7 +266,7 @@ func (impl *CdHandlerImpl) handleForceAbortCaseForCdStage(workflowRunner *pipeli return nil } -func (impl *CdHandlerImpl) UpdateWorkflow(workflowStatus v1alpha1.WorkflowStatus) (int, string, bool, error) { +func (impl *CdHandlerImpl) UpdateWorkflow(workflowStatus bean6.CiCdStatus) (int, string, bool, error) { wfStatusRs := impl.extractWorkfowStatus(workflowStatus) workflowName, status, podStatus, message, podName := wfStatusRs.WorkflowName, wfStatusRs.Status, wfStatusRs.PodStatus, wfStatusRs.Message, wfStatusRs.PodName impl.Logger.Debugw("cd update for ", "wf ", workflowName, "status", status) @@ -320,7 +321,7 @@ func (impl *CdHandlerImpl) UpdateWorkflow(workflowStatus v1alpha1.WorkflowStatus return savedWorkflow.Id, savedWorkflow.Status, false, nil } -func (impl *CdHandlerImpl) extractWorkfowStatus(workflowStatus v1alpha1.WorkflowStatus) *types.WorkflowStatus { +func (impl *CdHandlerImpl) extractWorkfowStatus(workflowStatus bean6.CiCdStatus) *types.WorkflowStatus { workflowName := "" status := string(workflowStatus.Phase) podStatus := "Pending" diff --git a/pkg/pipeline/CiHandler.go b/pkg/pipeline/CiHandler.go index 7cd3503bfa..fa7ee5d455 100644 --- a/pkg/pipeline/CiHandler.go +++ b/pkg/pipeline/CiHandler.go @@ -32,6 +32,7 @@ import ( bean5 "github.com/devtron-labs/devtron/pkg/cluster/bean" "github.com/devtron-labs/devtron/pkg/cluster/environment" repository2 "github.com/devtron-labs/devtron/pkg/cluster/environment/repository" + bean6 "github.com/devtron-labs/devtron/pkg/eventProcessor/bean" constants2 "github.com/devtron-labs/devtron/pkg/pipeline/constants" util3 "github.com/devtron-labs/devtron/pkg/pipeline/util" "github.com/devtron-labs/devtron/pkg/pipeline/workflowStatus" @@ -74,7 +75,7 @@ import ( type CiHandler interface { HandleCIWebhook(gitCiTriggerRequest bean.GitCiTriggerRequest) (int, error) HandleCIManual(ciTriggerRequest bean.CiTriggerRequest) (int, error) - CheckAndReTriggerCI(workflowStatus v1alpha1.WorkflowStatus) error + CheckAndReTriggerCI(workflowStatus bean6.CiCdStatus) error FetchMaterialsByPipelineId(pipelineId int, showAll bool) ([]pipelineConfig.CiPipelineMaterialResponse, error) FetchMaterialsByPipelineIdAndGitMaterialId(pipelineId int, gitMaterialId int, showAll bool) ([]pipelineConfig.CiPipelineMaterialResponse, error) FetchWorkflowDetails(appId int, pipelineId int, buildId int) (types.WorkflowResponse, error) @@ -88,7 +89,7 @@ type CiHandler interface { GetBuildHistory(pipelineId int, appId int, offset int, size int) ([]types.WorkflowResponse, error) DownloadCiWorkflowArtifacts(pipelineId int, buildId int) (*os.File, error) - UpdateWorkflow(workflowStatus v1alpha1.WorkflowStatus) (int, error) + UpdateWorkflow(workflowStatus bean6.CiCdStatus) (int, error) FetchCiStatusForTriggerView(appId int) ([]*pipelineConfig.CiWorkflowStatus, error) FetchCiStatusForTriggerViewV1(appId int) ([]*pipelineConfig.CiWorkflowStatus, error) @@ -171,7 +172,7 @@ func NewCiHandlerImpl(Logger *zap.SugaredLogger, ciService CiService, ciPipeline return cih } -func (impl *CiHandlerImpl) CheckAndReTriggerCI(workflowStatus v1alpha1.WorkflowStatus) error { +func (impl *CiHandlerImpl) CheckAndReTriggerCI(workflowStatus bean6.CiCdStatus) error { //return if re-trigger feature is disabled if !impl.config.WorkflowRetriesEnabled() { @@ -1110,7 +1111,7 @@ func (impl *CiHandlerImpl) GetHistoricBuildLogs(workflowId int, ciWorkflow *pipe return resp, err } -func ExtractWorkflowStatus(workflowStatus v1alpha1.WorkflowStatus) (string, string, string, string, string, string) { +func ExtractWorkflowStatus(workflowStatus bean6.CiCdStatus) (string, string, string, string, string, string) { workflowName := "" status := string(workflowStatus.Phase) podStatus := "" @@ -1140,7 +1141,7 @@ func ExtractWorkflowStatus(workflowStatus v1alpha1.WorkflowStatus) (string, stri return workflowName, status, podStatus, message, logLocation, podName } -func (impl *CiHandlerImpl) extractPodStatusAndWorkflow(workflowStatus v1alpha1.WorkflowStatus) (string, string, *pipelineConfig.CiWorkflow, error) { +func (impl *CiHandlerImpl) extractPodStatusAndWorkflow(workflowStatus bean6.CiCdStatus) (string, string, *pipelineConfig.CiWorkflow, error) { workflowName, status, _, message, _, _ := ExtractWorkflowStatus(workflowStatus) if workflowName == "" { impl.Logger.Errorw("extract workflow status, invalid wf name", "workflowName", workflowName, "status", status, "message", message) @@ -1176,7 +1177,7 @@ func (impl *CiHandlerImpl) getRefWorkflowAndCiRetryCount(savedWorkflow *pipeline return retryCount, savedWorkflow, err } -func (impl *CiHandlerImpl) UpdateWorkflow(workflowStatus v1alpha1.WorkflowStatus) (int, error) { +func (impl *CiHandlerImpl) UpdateWorkflow(workflowStatus bean6.CiCdStatus) (int, error) { workflowName, status, podStatus, message, _, podName := ExtractWorkflowStatus(workflowStatus) if workflowName == "" { impl.Logger.Errorw("extract workflow status, invalid wf name", "workflowName", workflowName, "status", status, "podStatus", podStatus, "message", message) diff --git a/pkg/pipeline/WorkflowService.go b/pkg/pipeline/WorkflowService.go index 3cc2215867..c51c1aab96 100644 --- a/pkg/pipeline/WorkflowService.go +++ b/pkg/pipeline/WorkflowService.go @@ -18,6 +18,7 @@ package pipeline import ( "context" + "encoding/base64" "encoding/json" "errors" "fmt" @@ -38,6 +39,7 @@ import ( "github.com/devtron-labs/devtron/pkg/pipeline/infraProviders" "github.com/devtron-labs/devtron/pkg/pipeline/infraProviders/infraGetters" "github.com/devtron-labs/devtron/pkg/pipeline/types" + "github.com/devtron-labs/devtron/pkg/ucid" "go.uber.org/zap" v12 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" @@ -72,6 +74,7 @@ type WorkflowServiceImpl struct { k8sUtil *k8s.K8sServiceImpl k8sCommonService k8s2.K8sCommonService infraProvider infraProviders.InfraProvider + ucid ucid.Service } // TODO: Move to bean @@ -85,7 +88,8 @@ func NewWorkflowServiceImpl(Logger *zap.SugaredLogger, k8sUtil *k8s.K8sServiceImpl, systemWorkflowExecutor executors.SystemWorkflowExecutor, k8sCommonService k8s2.K8sCommonService, - infraProvider infraProviders.InfraProvider) (*WorkflowServiceImpl, error) { + infraProvider infraProviders.InfraProvider, + ucid ucid.Service) (*WorkflowServiceImpl, error) { commonWorkflowService := &WorkflowServiceImpl{ Logger: Logger, ciCdConfig: ciCdConfig, @@ -97,6 +101,7 @@ func NewWorkflowServiceImpl(Logger *zap.SugaredLogger, systemWorkflowExecutor: systemWorkflowExecutor, k8sCommonService: k8sCommonService, infraProvider: infraProvider, + ucid: ucid, } restConfig, err := k8sUtil.GetK8sInClusterRestConfig() if err != nil { @@ -213,6 +218,12 @@ func (impl *WorkflowServiceImpl) createWorkflowTemplate(workflowRequest *types.W clusterConfig, err := impl.getClusterConfig(workflowRequest) workflowTemplate.ClusterConfig = clusterConfig workflowTemplate.WorkflowType = workflowRequest.GetWorkflowTypeForWorkflowRequest() + devtronUCID, _, err := impl.ucid.GetUCID() + if err != nil { + impl.Logger.Errorw("error in getting UCID", "err", err) + return bean3.WorkflowTemplate{}, err + } + workflowTemplate.DevtronInstanceUID = base64.StdEncoding.EncodeToString([]byte(devtronUCID)) return workflowTemplate, nil } diff --git a/pkg/pipeline/bean/WorkflowTemplate.go b/pkg/pipeline/bean/WorkflowTemplate.go index 55e91e565c..d39968fa2e 100644 --- a/pkg/pipeline/bean/WorkflowTemplate.go +++ b/pkg/pipeline/bean/WorkflowTemplate.go @@ -18,6 +18,7 @@ package bean import ( blob_storage "github.com/devtron-labs/common-lib/blob-storage" + informerBean "github.com/devtron-labs/common-lib/informer" "github.com/devtron-labs/devtron/api/bean" v1 "k8s.io/api/core/v1" v12 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -47,6 +48,7 @@ type WorkflowTemplate struct { RefPlugins []*RefPluginObject TerminationGracePeriod int WorkflowType string + DevtronInstanceUID string } const ( @@ -76,8 +78,11 @@ func (workflowTemplate *WorkflowTemplate) SetActiveDeadlineSeconds(timeout int64 } func (workflowTemplate *WorkflowTemplate) CreateObjectMetadata() *v12.ObjectMeta { - - workflowLabels := map[string]string{WorkflowGenerateNamePrefix: workflowTemplate.WorkflowNamePrefix} + workflowLabels := map[string]string{ + WorkflowGenerateNamePrefix: workflowTemplate.WorkflowNamePrefix, + informerBean.WorkflowTypeLabelKey: workflowTemplate.WorkflowType, + informerBean.DevtronAdministratorInstanceLabelKey: workflowTemplate.DevtronInstanceUID, + } switch workflowTemplate.WorkflowType { case CI_WORKFLOW_NAME: workflowLabels["devtron.ai/workflow-purpose"] = "ci" diff --git a/pkg/pipeline/executors/WorkflowUtils.go b/pkg/pipeline/executors/WorkflowUtils.go index 0c9f18e911..c812f761fe 100644 --- a/pkg/pipeline/executors/WorkflowUtils.go +++ b/pkg/pipeline/executors/WorkflowUtils.go @@ -21,6 +21,7 @@ import ( "github.com/argoproj/argo-workflows/v3/pkg/apis/workflow/v1alpha1" "github.com/argoproj/argo-workflows/v3/pkg/client/clientset/versioned" v1alpha12 "github.com/argoproj/argo-workflows/v3/pkg/client/clientset/versioned/typed/workflow/v1alpha1" + informerBean "github.com/devtron-labs/common-lib/informer" "github.com/devtron-labs/common-lib/utils" bean2 "github.com/devtron-labs/devtron/api/bean" "github.com/devtron-labs/devtron/internal/sql/repository" @@ -294,9 +295,9 @@ func CheckIfReTriggerRequired(status, message, workflowRunnerStatus string) bool func GetWorkflowLabelsForSystemExecutor(workflowTemplate bean.WorkflowTemplate) map[string]string { return map[string]string{ - DEVTRON_WORKFLOW_LABEL_KEY: DEVTRON_WORKFLOW_LABEL_VALUE, - "devtron.ai/purpose": "workflow", - "workflowType": workflowTemplate.WorkflowType, - bean.WorkflowGenerateNamePrefix: workflowTemplate.WorkflowNamePrefix, + DEVTRON_WORKFLOW_LABEL_KEY: DEVTRON_WORKFLOW_LABEL_VALUE, + "devtron.ai/purpose": "workflow", + informerBean.WorkflowTypeLabelKey: workflowTemplate.WorkflowType, + bean.WorkflowGenerateNamePrefix: workflowTemplate.WorkflowNamePrefix, } } diff --git a/pkg/ucid/bean.go b/pkg/ucid/bean.go new file mode 100644 index 0000000000..acd595ad57 --- /dev/null +++ b/pkg/ucid/bean.go @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2024. Devtron Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ucid + +const ( + DevtronUniqueClientIdConfigMap = "devtron-ucid" + DevtronUniqueClientIdConfigMapKey = "UCID" + UIEventKey = "uiEventKey" + InstallEventKey = "installEvent" +) diff --git a/pkg/ucid/ucid.go b/pkg/ucid/ucid.go new file mode 100644 index 0000000000..6dcc5de475 --- /dev/null +++ b/pkg/ucid/ucid.go @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2024. Devtron Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ucid + +import ( + "fmt" + "github.com/devtron-labs/common-lib/utils/k8s" + "github.com/devtron-labs/devtron/client/telemetry/posthog" + util3 "github.com/devtron-labs/devtron/pkg/util" + "github.com/devtron-labs/devtron/util" + "github.com/patrickmn/go-cache" + "go.uber.org/zap" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + v1 "k8s.io/api/core/v1" + v12 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +type Service interface { + GetUCID() (string, bool, error) +} + +type ServiceImpl struct { + logger *zap.SugaredLogger + posthogClient *posthog.PosthogClient + K8sUtil *k8s.K8sServiceImpl + aCDAuthConfig *util3.ACDAuthConfig +} + +func NewServiceImpl( + logger *zap.SugaredLogger, + posthogClient *posthog.PosthogClient, + K8sUtil *k8s.K8sServiceImpl, + aCDAuthConfig *util3.ACDAuthConfig, +) *ServiceImpl { + return &ServiceImpl{ + logger: logger, + posthogClient: posthogClient, + K8sUtil: K8sUtil, + aCDAuthConfig: aCDAuthConfig, + } +} + +func (impl *ServiceImpl) GetUCID() (string, bool, error) { + ucid, found := impl.posthogClient.GetCache().Get(DevtronUniqueClientIdConfigMapKey) + if found { + return ucid.(string), found, nil + } else { + client, err := impl.K8sUtil.GetClientForInCluster() + if err != nil { + impl.logger.Errorw("exception while getting unique client id", "error", err) + return "", found, err + } + cm, err := impl.K8sUtil.GetConfigMap(impl.aCDAuthConfig.ACDConfigMapNamespace, DevtronUniqueClientIdConfigMap, client) + if errStatus, ok := status.FromError(err); !ok || errStatus.Code() == codes.NotFound || errStatus.Code() == codes.Unknown { + // if not found, create new cm + cm = &v1.ConfigMap{ObjectMeta: v12.ObjectMeta{Name: DevtronUniqueClientIdConfigMap}} + data := map[string]string{} + data[DevtronUniqueClientIdConfigMapKey] = util.Generate(16) // generate unique random number + data[InstallEventKey] = "1" // used in operator to detect event is install or upgrade + data[UIEventKey] = "1" + cm.Data = data + _, err = impl.K8sUtil.CreateConfigMap(impl.aCDAuthConfig.ACDConfigMapNamespace, cm, client) + if err != nil { + impl.logger.Errorw("exception while getting unique client id", "error", err) + return "", found, err + } + } + if cm == nil { + impl.logger.Errorw("configmap not found while getting unique client id") + return ucid.(string), found, fmt.Errorf("configmap %q not found while getting unique client id", DevtronUniqueClientIdConfigMap) + } + dataMap := cm.Data + ucid = dataMap[DevtronUniqueClientIdConfigMapKey] + impl.posthogClient.GetCache().Set(DevtronUniqueClientIdConfigMapKey, ucid, cache.DefaultExpiration) + } + return ucid.(string), found, nil +} diff --git a/pkg/ucid/wire_ucid.go b/pkg/ucid/wire_ucid.go new file mode 100644 index 0000000000..f8f4402af2 --- /dev/null +++ b/pkg/ucid/wire_ucid.go @@ -0,0 +1,8 @@ +package ucid + +import "github.com/google/wire" + +var WireSet = wire.NewSet( + NewServiceImpl, + wire.Bind(new(Service), new(*ServiceImpl)), +) diff --git a/util/helper.go b/util/helper.go index c8d3e00c27..50fbbf91ab 100644 --- a/util/helper.go +++ b/util/helper.go @@ -25,8 +25,8 @@ import ( "fmt" "github.com/devtron-labs/devtron/internal/middleware" "github.com/juju/errors" + "go.opentelemetry.io/otel" "io" - "io/ioutil" "math/rand" "net/http" "os" @@ -139,8 +139,10 @@ func GenerateNewWorkflowName(name string) string { return fmt.Sprintf("%s-clone-%s", name, Generate(4)) } -func HttpRequest(url string) (map[string]interface{}, error) { - req, err := http.NewRequest(http.MethodGet, url, nil) +func HttpRequest(ctx context.Context, url string) (map[string]interface{}, error) { + newCtx, span := otel.Tracer("orchestrator").Start(ctx, "util.HttpRequest") + defer span.End() + req, err := http.NewRequestWithContext(newCtx, http.MethodGet, url, nil) if err != nil { return nil, err } @@ -151,7 +153,7 @@ func HttpRequest(url string) (map[string]interface{}, error) { return nil, err } if res.StatusCode >= 200 && res.StatusCode <= 299 { - resBody, err := ioutil.ReadAll(res.Body) + resBody, err := io.ReadAll(res.Body) if err != nil { return nil, err } diff --git a/vendor/github.com/devtron-labs/common-lib/informer/bean.go b/vendor/github.com/devtron-labs/common-lib/informer/bean.go new file mode 100644 index 0000000000..e3b0304328 --- /dev/null +++ b/vendor/github.com/devtron-labs/common-lib/informer/bean.go @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2024. Devtron Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package informer + +const ( + ClusterModifyEventSecretType = "cluster.request/modify" + ClusterActionAdd = "add" + ClusterActionUpdate = "update" + ClusterActionDelete = "delete" + SecretFieldAction = "action" + SecretFieldClusterId = "cluster_id" +) + +const ( + WorkflowTypeLabelKey = "workflowType" + CiWorkflowName = "ci" + CdWorkflowName = "cd" +) + +const ( + DevtronAdministratorInstanceLabelKey = "devtron.ai/administrator-instance" +) + +const ( + PodDeletedMessage = "pod deleted" +) diff --git a/vendor/github.com/golang-jwt/jwt/v4/parser.go b/vendor/github.com/golang-jwt/jwt/v4/parser.go index 9dd36e5a5a..0fc510a0aa 100644 --- a/vendor/github.com/golang-jwt/jwt/v4/parser.go +++ b/vendor/github.com/golang-jwt/jwt/v4/parser.go @@ -7,6 +7,8 @@ import ( "strings" ) +const tokenDelimiter = "." + type Parser struct { // If populated, only these methods will be considered valid. // @@ -122,9 +124,10 @@ func (p *Parser) ParseWithClaims(tokenString string, claims Claims, keyFunc Keyf // It's only ever useful in cases where you know the signature is valid (because it has // been checked previously in the stack) and you want to extract values from it. func (p *Parser) ParseUnverified(tokenString string, claims Claims) (token *Token, parts []string, err error) { - parts = strings.Split(tokenString, ".") - if len(parts) != 3 { - return nil, parts, NewValidationError("token contains an invalid number of segments", ValidationErrorMalformed) + var ok bool + parts, ok = splitToken(tokenString) + if !ok { + return nil, nil, NewValidationError("token contains an invalid number of segments", ValidationErrorMalformed) } token = &Token{Raw: tokenString} @@ -174,3 +177,30 @@ func (p *Parser) ParseUnverified(tokenString string, claims Claims) (token *Toke return token, parts, nil } + +// splitToken splits a token string into three parts: header, claims, and signature. It will only +// return true if the token contains exactly two delimiters and three parts. In all other cases, it +// will return nil parts and false. +func splitToken(token string) ([]string, bool) { + parts := make([]string, 3) + header, remain, ok := strings.Cut(token, tokenDelimiter) + if !ok { + return nil, false + } + parts[0] = header + claims, remain, ok := strings.Cut(remain, tokenDelimiter) + if !ok { + return nil, false + } + parts[1] = claims + // One more cut to ensure the signature is the last part of the token and there are no more + // delimiters. This avoids an issue where malicious input could contain additional delimiters + // causing unecessary overhead parsing tokens. + signature, _, unexpected := strings.Cut(remain, tokenDelimiter) + if unexpected { + return nil, false + } + parts[2] = signature + + return parts, true +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 2834d578cf..7084a09385 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -472,7 +472,7 @@ github.com/davecgh/go-spew/spew # github.com/deckarep/golang-set v1.8.0 ## explicit; go 1.17 github.com/deckarep/golang-set -# github.com/devtron-labs/authenticator v0.4.35-0.20240809073103-6e11da8083f8 => github.com/devtron-labs/devtron-services/authenticator v0.0.0-20250402105331-120c20ff29d9 +# github.com/devtron-labs/authenticator v0.4.35-0.20240809073103-6e11da8083f8 => github.com/devtron-labs/devtron-services/authenticator v0.0.0-20250402155428-3fa1ffc068e2 ## explicit; go 1.21 github.com/devtron-labs/authenticator/apiToken github.com/devtron-labs/authenticator/client @@ -480,7 +480,7 @@ github.com/devtron-labs/authenticator/jwt github.com/devtron-labs/authenticator/middleware github.com/devtron-labs/authenticator/oidc github.com/devtron-labs/authenticator/password -# github.com/devtron-labs/common-lib v0.18.1-0.20241001061923-eda545dc839e => github.com/devtron-labs/devtron-services/common-lib v0.0.0-20250402105331-120c20ff29d9 +# github.com/devtron-labs/common-lib v0.18.1-0.20241001061923-eda545dc839e => github.com/devtron-labs/devtron-services/common-lib v0.0.0-20250402155428-3fa1ffc068e2 ## explicit; go 1.21 github.com/devtron-labs/common-lib/async github.com/devtron-labs/common-lib/blob-storage @@ -492,6 +492,7 @@ github.com/devtron-labs/common-lib/fetchAllEnv github.com/devtron-labs/common-lib/git-manager github.com/devtron-labs/common-lib/git-manager/util github.com/devtron-labs/common-lib/imageScan/bean +github.com/devtron-labs/common-lib/informer github.com/devtron-labs/common-lib/middlewares github.com/devtron-labs/common-lib/pubsub-lib github.com/devtron-labs/common-lib/pubsub-lib/metrics @@ -699,7 +700,7 @@ github.com/gogo/protobuf/jsonpb github.com/gogo/protobuf/proto github.com/gogo/protobuf/sortkeys github.com/gogo/protobuf/types -# github.com/golang-jwt/jwt/v4 v4.5.1 +# github.com/golang-jwt/jwt/v4 v4.5.2 ## explicit; go 1.16 github.com/golang-jwt/jwt/v4 # github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da @@ -2350,8 +2351,9 @@ xorm.io/xorm/log xorm.io/xorm/names xorm.io/xorm/schemas xorm.io/xorm/tags -# github.com/devtron-labs/authenticator => github.com/devtron-labs/devtron-services/authenticator v0.0.0-20250402105331-120c20ff29d9 -# github.com/devtron-labs/common-lib => github.com/devtron-labs/devtron-services/common-lib v0.0.0-20250402105331-120c20ff29d9 +# github.com/argoproj/argo-workflows/v3 => github.com/devtron-labs/argo-workflows/v3 v3.5.13 +# github.com/devtron-labs/authenticator => github.com/devtron-labs/devtron-services/authenticator v0.0.0-20250402155428-3fa1ffc068e2 +# github.com/devtron-labs/common-lib => github.com/devtron-labs/devtron-services/common-lib v0.0.0-20250402155428-3fa1ffc068e2 # github.com/go-check/check => github.com/go-check/check v0.0.0-20180628173108-788fd7840127 # github.com/googleapis/gnostic => github.com/googleapis/gnostic v0.5.5 # k8s.io/api => k8s.io/api v0.29.7 diff --git a/wire_gen.go b/wire_gen.go index b8264c531a..de7e59d8ef 100644 --- a/wire_gen.go +++ b/wire_gen.go @@ -91,6 +91,7 @@ import ( "github.com/devtron-labs/devtron/client/lens" "github.com/devtron-labs/devtron/client/proxy" "github.com/devtron-labs/devtron/client/telemetry" + "github.com/devtron-labs/devtron/client/telemetry/posthog" 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/appStatus" @@ -256,6 +257,7 @@ import ( read4 "github.com/devtron-labs/devtron/pkg/team/read" repository8 "github.com/devtron-labs/devtron/pkg/team/repository" "github.com/devtron-labs/devtron/pkg/terminal" + "github.com/devtron-labs/devtron/pkg/ucid" "github.com/devtron-labs/devtron/pkg/userResource" util3 "github.com/devtron-labs/devtron/pkg/util" "github.com/devtron-labs/devtron/pkg/variables" @@ -623,7 +625,12 @@ func InitializeApp() (*App, error) { } ciInfraGetter := ci.NewCiInfraGetter(sugaredLogger, infraConfigServiceImpl, infraConfigAuditServiceImpl) infraProviderImpl := infraProviders.NewInfraProviderImpl(sugaredLogger, infraGetter, ciInfraGetter) - workflowServiceImpl, err := pipeline.NewWorkflowServiceImpl(sugaredLogger, environmentRepositoryImpl, ciCdConfig, configReadServiceImpl, globalCMCSServiceImpl, argoWorkflowExecutorImpl, k8sServiceImpl, systemWorkflowExecutorImpl, k8sCommonServiceImpl, infraProviderImpl) + posthogClient, err := posthog.NewPosthogClient(sugaredLogger) + if err != nil { + return nil, err + } + serviceImpl := ucid.NewServiceImpl(sugaredLogger, posthogClient, k8sServiceImpl, acdAuthConfig) + workflowServiceImpl, err := pipeline.NewWorkflowServiceImpl(sugaredLogger, environmentRepositoryImpl, ciCdConfig, configReadServiceImpl, globalCMCSServiceImpl, argoWorkflowExecutorImpl, k8sServiceImpl, systemWorkflowExecutorImpl, k8sCommonServiceImpl, infraProviderImpl, serviceImpl) if err != nil { return nil, err } @@ -924,12 +931,8 @@ func InitializeApp() (*App, error) { ssoLoginServiceImpl := sso.NewSSOLoginServiceImpl(sugaredLogger, ssoLoginRepositoryImpl, k8sServiceImpl, environmentVariables, userAuthOidcHelperImpl) ssoLoginRestHandlerImpl := sso2.NewSsoLoginRestHandlerImpl(validate, sugaredLogger, enforcerImpl, userServiceImpl, ssoLoginServiceImpl) ssoLoginRouterImpl := sso2.NewSsoLoginRouterImpl(ssoLoginRestHandlerImpl) - posthogClient, err := telemetry.NewPosthogClient(sugaredLogger) - if err != nil { - return nil, err - } providerIdentifierServiceImpl := providerIdentifier.NewProviderIdentifierServiceImpl(sugaredLogger) - telemetryEventClientImplExtended, err := telemetry.NewTelemetryEventClientImplExtended(sugaredLogger, httpClient, clusterServiceImplExtended, k8sServiceImpl, acdAuthConfig, environmentServiceImpl, userServiceImpl, appListingRepositoryImpl, posthogClient, ciPipelineConfigReadServiceImpl, pipelineRepositoryImpl, gitProviderRepositoryImpl, attributesRepositoryImpl, ssoLoginServiceImpl, appRepositoryImpl, ciWorkflowRepositoryImpl, cdWorkflowRepositoryImpl, dockerArtifactStoreRepositoryImpl, gitMaterialReadServiceImpl, ciTemplateRepositoryImpl, chartRepositoryImpl, userAuditServiceImpl, ciBuildConfigServiceImpl, moduleRepositoryImpl, serverDataStoreServerDataStore, helmAppClientImpl, installedAppReadServiceImpl, userAttributesRepositoryImpl, providerIdentifierServiceImpl, cronLoggerImpl, gitOpsConfigReadServiceImpl) + telemetryEventClientImplExtended, err := telemetry.NewTelemetryEventClientImplExtended(sugaredLogger, httpClient, clusterServiceImplExtended, k8sServiceImpl, acdAuthConfig, environmentServiceImpl, userServiceImpl, appListingRepositoryImpl, posthogClient, serviceImpl, ciPipelineConfigReadServiceImpl, pipelineRepositoryImpl, gitProviderRepositoryImpl, attributesRepositoryImpl, ssoLoginServiceImpl, appRepositoryImpl, ciWorkflowRepositoryImpl, cdWorkflowRepositoryImpl, dockerArtifactStoreRepositoryImpl, gitMaterialReadServiceImpl, ciTemplateRepositoryImpl, chartRepositoryImpl, userAuditServiceImpl, ciBuildConfigServiceImpl, moduleRepositoryImpl, serverDataStoreServerDataStore, helmAppClientImpl, installedAppReadServiceImpl, userAttributesRepositoryImpl, providerIdentifierServiceImpl, cronLoggerImpl, gitOpsConfigReadServiceImpl) if err != nil { return nil, err } @@ -948,8 +951,8 @@ func InitializeApp() (*App, error) { webhookListenerRouterImpl := router.NewWebhookListenerRouterImpl(webhookEventHandlerImpl) appFilteringRestHandlerImpl := appList.NewAppFilteringRestHandlerImpl(sugaredLogger, teamServiceImpl, enforcerImpl, userServiceImpl, clusterServiceImplExtended, environmentServiceImpl, teamReadServiceImpl) appFilteringRouterImpl := appList2.NewAppFilteringRouterImpl(appFilteringRestHandlerImpl) - serviceImpl := resourceTree.NewServiceImpl(sugaredLogger, appListingServiceImpl, appStatusServiceImpl, argoApplicationServiceExtendedImpl, cdApplicationStatusUpdateHandlerImpl, helmAppReadServiceImpl, helmAppServiceImpl, k8sApplicationServiceImpl, k8sCommonServiceImpl, environmentReadServiceImpl) - appListingRestHandlerImpl := appList.NewAppListingRestHandlerImpl(appListingServiceImpl, enforcerImpl, pipelineBuilderImpl, sugaredLogger, enforcerUtilImpl, deploymentGroupServiceImpl, userServiceImpl, k8sCommonServiceImpl, installedAppDBExtendedServiceImpl, installedAppResourceServiceImpl, pipelineRepositoryImpl, k8sApplicationServiceImpl, deploymentConfigServiceImpl, serviceImpl) + resourceTreeServiceImpl := resourceTree.NewServiceImpl(sugaredLogger, appListingServiceImpl, appStatusServiceImpl, argoApplicationServiceExtendedImpl, cdApplicationStatusUpdateHandlerImpl, helmAppReadServiceImpl, helmAppServiceImpl, k8sApplicationServiceImpl, k8sCommonServiceImpl, environmentReadServiceImpl) + appListingRestHandlerImpl := appList.NewAppListingRestHandlerImpl(appListingServiceImpl, enforcerImpl, pipelineBuilderImpl, sugaredLogger, enforcerUtilImpl, deploymentGroupServiceImpl, userServiceImpl, k8sCommonServiceImpl, installedAppDBExtendedServiceImpl, installedAppResourceServiceImpl, pipelineRepositoryImpl, k8sApplicationServiceImpl, deploymentConfigServiceImpl, resourceTreeServiceImpl) appListingRouterImpl := appList2.NewAppListingRouterImpl(appListingRestHandlerImpl) appInfoRestHandlerImpl := appInfo.NewAppInfoRestHandlerImpl(sugaredLogger, appCrudOperationServiceImpl, userServiceImpl, validate, enforcerUtilImpl, enforcerImpl, helmAppServiceImpl, enforcerUtilHelmImpl, genericNoteServiceImpl, commonEnforcementUtilImpl) appInfoRouterImpl := appInfo2.NewAppInfoRouterImpl(sugaredLogger, appInfoRestHandlerImpl) @@ -1078,7 +1081,7 @@ func InitializeApp() (*App, error) { cdWorkflowServiceImpl := cd.NewCdWorkflowServiceImpl(sugaredLogger, cdWorkflowRepositoryImpl) cdWorkflowRunnerReadServiceImpl := read20.NewCdWorkflowRunnerReadServiceImpl(sugaredLogger, cdWorkflowRepositoryImpl) webhookServiceImpl := pipeline.NewWebhookServiceImpl(ciArtifactRepositoryImpl, sugaredLogger, ciPipelineRepositoryImpl, ciWorkflowRepositoryImpl, cdWorkflowCommonServiceImpl, workFlowStageStatusServiceImpl, ciServiceImpl) - workflowEventProcessorImpl, err := in.NewWorkflowEventProcessorImpl(sugaredLogger, pubSubClientServiceImpl, cdWorkflowServiceImpl, cdWorkflowReadServiceImpl, cdWorkflowRunnerServiceImpl, cdWorkflowRunnerReadServiceImpl, workflowDagExecutorImpl, ciHandlerImpl, cdHandlerImpl, eventSimpleFactoryImpl, eventRESTClientImpl, triggerServiceImpl, deployedAppServiceImpl, webhookServiceImpl, validate, environmentVariables, cdWorkflowCommonServiceImpl, cdPipelineConfigServiceImpl, userDeploymentRequestServiceImpl, pipelineRepositoryImpl, ciArtifactRepositoryImpl, cdWorkflowRepositoryImpl, deploymentConfigServiceImpl) + workflowEventProcessorImpl, err := in.NewWorkflowEventProcessorImpl(sugaredLogger, pubSubClientServiceImpl, cdWorkflowServiceImpl, cdWorkflowReadServiceImpl, cdWorkflowRunnerServiceImpl, cdWorkflowRunnerReadServiceImpl, workflowDagExecutorImpl, ciHandlerImpl, cdHandlerImpl, eventSimpleFactoryImpl, eventRESTClientImpl, triggerServiceImpl, deployedAppServiceImpl, webhookServiceImpl, validate, environmentVariables, cdWorkflowCommonServiceImpl, cdPipelineConfigServiceImpl, userDeploymentRequestServiceImpl, serviceImpl, pipelineRepositoryImpl, ciArtifactRepositoryImpl, cdWorkflowRepositoryImpl, deploymentConfigServiceImpl) if err != nil { return nil, err } From 3237725d2eff0abeae810b2755f17eafa6af4991 Mon Sep 17 00:00:00 2001 From: Ash-exp Date: Thu, 3 Apr 2025 11:47:09 +0530 Subject: [PATCH 02/19] telemetry svc refactoring --- client/telemetry/TelemetryEventClient.go | 2 +- .../in/WorkflowEventProcessorService.go | 4 +- pkg/pipeline/WorkflowService.go | 2 +- pkg/ucid/ucid.go | 86 ++++++++++--------- 4 files changed, 49 insertions(+), 45 deletions(-) diff --git a/client/telemetry/TelemetryEventClient.go b/client/telemetry/TelemetryEventClient.go index 5d3ba4ab25..a64196242f 100644 --- a/client/telemetry/TelemetryEventClient.go +++ b/client/telemetry/TelemetryEventClient.go @@ -657,7 +657,7 @@ func (impl *TelemetryEventClientImpl) SendTelemetryDashboardLoggedInEvent() erro func (impl *TelemetryEventClientImpl) getUCIDAndCheckIsOptedOut(ctx context.Context) (string, error) { newCtx, span := otel.Tracer("orchestrator").Start(ctx, "TelemetryEventClientImpl.getUCIDAndCheckIsOptedOut") defer span.End() - ucid, found, err := impl.ucid.GetUCID() + ucid, found, err := impl.ucid.GetUCIDWithCache(impl.posthogClient.GetCache()) if err != nil { impl.logger.Errorw("exception while getting unique client id", "error", err) return "", err diff --git a/pkg/eventProcessor/in/WorkflowEventProcessorService.go b/pkg/eventProcessor/in/WorkflowEventProcessorService.go index 45ed82b9c2..49b127f95a 100644 --- a/pkg/eventProcessor/in/WorkflowEventProcessorService.go +++ b/pkg/eventProcessor/in/WorkflowEventProcessorService.go @@ -399,7 +399,7 @@ func (impl *WorkflowEventProcessorImpl) SubscribeCIWorkflowStatusUpdate() error return } if len(wfStatus.DevtronAdministratorInstance) != 0 { - devtronUCID, _, err := impl.ucid.GetUCID() + devtronUCID, _, err := impl.ucid.GetUCIDWithOutCache() if err != nil { impl.logger.Errorw("error in getting UCID", "err", err) return @@ -458,7 +458,7 @@ func (impl *WorkflowEventProcessorImpl) SubscribeCDWorkflowStatusUpdate() error return } if len(wfStatus.DevtronAdministratorInstance) != 0 { - devtronUCID, _, err := impl.ucid.GetUCID() + devtronUCID, _, err := impl.ucid.GetUCIDWithOutCache() if err != nil { impl.logger.Errorw("error in getting UCID", "err", err) return diff --git a/pkg/pipeline/WorkflowService.go b/pkg/pipeline/WorkflowService.go index c51c1aab96..660350a271 100644 --- a/pkg/pipeline/WorkflowService.go +++ b/pkg/pipeline/WorkflowService.go @@ -218,7 +218,7 @@ func (impl *WorkflowServiceImpl) createWorkflowTemplate(workflowRequest *types.W clusterConfig, err := impl.getClusterConfig(workflowRequest) workflowTemplate.ClusterConfig = clusterConfig workflowTemplate.WorkflowType = workflowRequest.GetWorkflowTypeForWorkflowRequest() - devtronUCID, _, err := impl.ucid.GetUCID() + devtronUCID, _, err := impl.ucid.GetUCIDWithOutCache() if err != nil { impl.Logger.Errorw("error in getting UCID", "err", err) return bean3.WorkflowTemplate{}, err diff --git a/pkg/ucid/ucid.go b/pkg/ucid/ucid.go index 6dcc5de475..65c03e8887 100644 --- a/pkg/ucid/ucid.go +++ b/pkg/ucid/ucid.go @@ -19,74 +19,78 @@ package ucid import ( "fmt" "github.com/devtron-labs/common-lib/utils/k8s" - "github.com/devtron-labs/devtron/client/telemetry/posthog" - util3 "github.com/devtron-labs/devtron/pkg/util" - "github.com/devtron-labs/devtron/util" - "github.com/patrickmn/go-cache" + "github.com/devtron-labs/devtron/pkg/util" + globalUtil "github.com/devtron-labs/devtron/util" + goCache "github.com/patrickmn/go-cache" "go.uber.org/zap" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" v1 "k8s.io/api/core/v1" - v12 "k8s.io/apimachinery/pkg/apis/meta/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) type Service interface { - GetUCID() (string, bool, error) + GetUCIDWithCache(cache *goCache.Cache) (string, bool, error) + GetUCIDWithOutCache() (string, bool, error) } type ServiceImpl struct { logger *zap.SugaredLogger - posthogClient *posthog.PosthogClient K8sUtil *k8s.K8sServiceImpl - aCDAuthConfig *util3.ACDAuthConfig + aCDAuthConfig *util.ACDAuthConfig } func NewServiceImpl( logger *zap.SugaredLogger, - posthogClient *posthog.PosthogClient, K8sUtil *k8s.K8sServiceImpl, - aCDAuthConfig *util3.ACDAuthConfig, + aCDAuthConfig *util.ACDAuthConfig, ) *ServiceImpl { return &ServiceImpl{ logger: logger, - posthogClient: posthogClient, K8sUtil: K8sUtil, aCDAuthConfig: aCDAuthConfig, } } -func (impl *ServiceImpl) GetUCID() (string, bool, error) { - ucid, found := impl.posthogClient.GetCache().Get(DevtronUniqueClientIdConfigMapKey) - if found { - return ucid.(string), found, nil - } else { - client, err := impl.K8sUtil.GetClientForInCluster() +func (impl *ServiceImpl) GetUCIDWithOutCache() (string, bool, error) { + return impl.GetUCIDWithCache(nil) +} + +func (impl *ServiceImpl) GetUCIDWithCache(cache *goCache.Cache) (string, bool, error) { + if cache != nil { + ucid, found := cache.Get(DevtronUniqueClientIdConfigMapKey) + if found { + return ucid.(string), true, nil + } + } + client, err := impl.K8sUtil.GetClientForInCluster() + if err != nil { + impl.logger.Errorw("exception while getting unique client id", "error", err) + return "", false, err + } + cm, err := impl.K8sUtil.GetConfigMap(impl.aCDAuthConfig.ACDConfigMapNamespace, DevtronUniqueClientIdConfigMap, client) + if errStatus, ok := status.FromError(err); !ok || errStatus.Code() == codes.NotFound || errStatus.Code() == codes.Unknown { + // if not found, create new cm + cm = &v1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: DevtronUniqueClientIdConfigMap}} + data := map[string]string{} + data[DevtronUniqueClientIdConfigMapKey] = globalUtil.Generate(16) // generate unique random number + data[InstallEventKey] = "1" // used in operator to detect event is install or upgrade + data[UIEventKey] = "1" + cm.Data = data + _, err = impl.K8sUtil.CreateConfigMap(impl.aCDAuthConfig.ACDConfigMapNamespace, cm, client) if err != nil { impl.logger.Errorw("exception while getting unique client id", "error", err) - return "", found, err + return "", false, err } - cm, err := impl.K8sUtil.GetConfigMap(impl.aCDAuthConfig.ACDConfigMapNamespace, DevtronUniqueClientIdConfigMap, client) - if errStatus, ok := status.FromError(err); !ok || errStatus.Code() == codes.NotFound || errStatus.Code() == codes.Unknown { - // if not found, create new cm - cm = &v1.ConfigMap{ObjectMeta: v12.ObjectMeta{Name: DevtronUniqueClientIdConfigMap}} - data := map[string]string{} - data[DevtronUniqueClientIdConfigMapKey] = util.Generate(16) // generate unique random number - data[InstallEventKey] = "1" // used in operator to detect event is install or upgrade - data[UIEventKey] = "1" - cm.Data = data - _, err = impl.K8sUtil.CreateConfigMap(impl.aCDAuthConfig.ACDConfigMapNamespace, cm, client) - if err != nil { - impl.logger.Errorw("exception while getting unique client id", "error", err) - return "", found, err - } - } - if cm == nil { - impl.logger.Errorw("configmap not found while getting unique client id") - return ucid.(string), found, fmt.Errorf("configmap %q not found while getting unique client id", DevtronUniqueClientIdConfigMap) - } - dataMap := cm.Data - ucid = dataMap[DevtronUniqueClientIdConfigMapKey] - impl.posthogClient.GetCache().Set(DevtronUniqueClientIdConfigMapKey, ucid, cache.DefaultExpiration) } - return ucid.(string), found, nil + if cm == nil { + impl.logger.Errorw("configmap not found while getting unique client id") + return "", false, fmt.Errorf("configmap %q not found while getting unique client id", DevtronUniqueClientIdConfigMap) + } + dataMap := cm.Data + ucid := dataMap[DevtronUniqueClientIdConfigMapKey] + if cache != nil { + cache.Set(DevtronUniqueClientIdConfigMapKey, ucid, goCache.DefaultExpiration) + } + return ucid, false, nil } From 8525719c16c98609c8f9dfbfbaa9e7e44e722ceb Mon Sep 17 00:00:00 2001 From: Ash-exp Date: Thu, 3 Apr 2025 12:10:42 +0530 Subject: [PATCH 03/19] updated wire gen files --- cmd/external-app/wire_gen.go | 2 +- wire_gen.go | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cmd/external-app/wire_gen.go b/cmd/external-app/wire_gen.go index 52ff9e5076..f1d6763cc8 100644 --- a/cmd/external-app/wire_gen.go +++ b/cmd/external-app/wire_gen.go @@ -390,7 +390,7 @@ func InitializeApp() (*App, error) { if err != nil { return nil, err } - serviceImpl := ucid.NewServiceImpl(sugaredLogger, posthogClient, k8sServiceImpl, acdAuthConfig) + serviceImpl := ucid.NewServiceImpl(sugaredLogger, k8sServiceImpl, acdAuthConfig) providerIdentifierServiceImpl := providerIdentifier.NewProviderIdentifierServiceImpl(sugaredLogger) telemetryEventClientImpl, err := telemetry.NewTelemetryEventClientImpl(sugaredLogger, httpClient, clusterServiceImpl, k8sServiceImpl, acdAuthConfig, userServiceImpl, attributesRepositoryImpl, ssoLoginServiceImpl, posthogClient, serviceImpl, moduleRepositoryImpl, serverDataStoreServerDataStore, userAuditServiceImpl, helmAppClientImpl, providerIdentifierServiceImpl, cronLoggerImpl, installedAppReadServiceEAImpl, environmentVariables) if err != nil { diff --git a/wire_gen.go b/wire_gen.go index de7e59d8ef..c4ff527793 100644 --- a/wire_gen.go +++ b/wire_gen.go @@ -625,11 +625,7 @@ func InitializeApp() (*App, error) { } ciInfraGetter := ci.NewCiInfraGetter(sugaredLogger, infraConfigServiceImpl, infraConfigAuditServiceImpl) infraProviderImpl := infraProviders.NewInfraProviderImpl(sugaredLogger, infraGetter, ciInfraGetter) - posthogClient, err := posthog.NewPosthogClient(sugaredLogger) - if err != nil { - return nil, err - } - serviceImpl := ucid.NewServiceImpl(sugaredLogger, posthogClient, k8sServiceImpl, acdAuthConfig) + serviceImpl := ucid.NewServiceImpl(sugaredLogger, k8sServiceImpl, acdAuthConfig) workflowServiceImpl, err := pipeline.NewWorkflowServiceImpl(sugaredLogger, environmentRepositoryImpl, ciCdConfig, configReadServiceImpl, globalCMCSServiceImpl, argoWorkflowExecutorImpl, k8sServiceImpl, systemWorkflowExecutorImpl, k8sCommonServiceImpl, infraProviderImpl, serviceImpl) if err != nil { return nil, err @@ -931,6 +927,10 @@ func InitializeApp() (*App, error) { ssoLoginServiceImpl := sso.NewSSOLoginServiceImpl(sugaredLogger, ssoLoginRepositoryImpl, k8sServiceImpl, environmentVariables, userAuthOidcHelperImpl) ssoLoginRestHandlerImpl := sso2.NewSsoLoginRestHandlerImpl(validate, sugaredLogger, enforcerImpl, userServiceImpl, ssoLoginServiceImpl) ssoLoginRouterImpl := sso2.NewSsoLoginRouterImpl(ssoLoginRestHandlerImpl) + posthogClient, err := posthog.NewPosthogClient(sugaredLogger) + if err != nil { + return nil, err + } providerIdentifierServiceImpl := providerIdentifier.NewProviderIdentifierServiceImpl(sugaredLogger) telemetryEventClientImplExtended, err := telemetry.NewTelemetryEventClientImplExtended(sugaredLogger, httpClient, clusterServiceImplExtended, k8sServiceImpl, acdAuthConfig, environmentServiceImpl, userServiceImpl, appListingRepositoryImpl, posthogClient, serviceImpl, ciPipelineConfigReadServiceImpl, pipelineRepositoryImpl, gitProviderRepositoryImpl, attributesRepositoryImpl, ssoLoginServiceImpl, appRepositoryImpl, ciWorkflowRepositoryImpl, cdWorkflowRepositoryImpl, dockerArtifactStoreRepositoryImpl, gitMaterialReadServiceImpl, ciTemplateRepositoryImpl, chartRepositoryImpl, userAuditServiceImpl, ciBuildConfigServiceImpl, moduleRepositoryImpl, serverDataStoreServerDataStore, helmAppClientImpl, installedAppReadServiceImpl, userAttributesRepositoryImpl, providerIdentifierServiceImpl, cronLoggerImpl, gitOpsConfigReadServiceImpl) if err != nil { From 44abd3fbff849a754e00dd61664f7687062a9fd9 Mon Sep 17 00:00:00 2001 From: Ash-exp Date: Thu, 3 Apr 2025 12:23:51 +0530 Subject: [PATCH 04/19] fix: CheckIfReTriggerRequired condition and CdHandlerImpl.UpdateWorkflow method --- .../pipelineConfig/CdWorfkflowRepository.go | 11 +++++++++++ pkg/pipeline/CdHandler.go | 4 ++-- pkg/pipeline/executors/WorkflowUtils.go | 7 +++++-- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/internal/sql/repository/pipelineConfig/CdWorfkflowRepository.go b/internal/sql/repository/pipelineConfig/CdWorfkflowRepository.go index a737a7076a..9aa3eeaa28 100644 --- a/internal/sql/repository/pipelineConfig/CdWorfkflowRepository.go +++ b/internal/sql/repository/pipelineConfig/CdWorfkflowRepository.go @@ -50,6 +50,7 @@ type CdWorkflowRepository interface { FindWorkflowRunnerByCdWorkflowId(wfIds []int) ([]*CdWorkflowRunner, error) FindPreviousCdWfRunnerByStatus(pipelineId int, currentWFRunnerId int, status []string) ([]*CdWorkflowRunner, error) FindWorkflowRunnerById(wfrId int) (*CdWorkflowRunner, error) + FindPreOrPostCdWorkflowRunnerById(wfrId int) (*CdWorkflowRunner, error) FindBasicWorkflowRunnerById(wfrId int) (*CdWorkflowRunner, error) FindRetriedWorkflowCountByReferenceId(wfrId int) (int, error) FindLatestWfrByAppIdAndEnvironmentId(appId int, environmentId int) (*CdWorkflowRunner, error) @@ -528,6 +529,16 @@ func (impl *CdWorkflowRepositoryImpl) FindWorkflowRunnerById(wfrId int) (*CdWork return wfr, err } +func (impl *CdWorkflowRepositoryImpl) FindPreOrPostCdWorkflowRunnerById(wfrId int) (*CdWorkflowRunner, error) { + wfr := &CdWorkflowRunner{} + err := impl.dbConnection.Model(wfr). + Column("cd_workflow_runner.*", "CdWorkflow", "CdWorkflow.Pipeline", "CdWorkflow.CiArtifact", "CdWorkflow.Pipeline.Environment"). + Where("cd_workflow_runner.id = ?", wfrId). + Where("cd_workflow_runner.workflow_type != ?", apiBean.CD_WORKFLOW_TYPE_DEPLOY). + Select() + return wfr, err +} + func (impl *CdWorkflowRepositoryImpl) FindBasicWorkflowRunnerById(wfrId int) (*CdWorkflowRunner, error) { wfr := &CdWorkflowRunner{} err := impl.dbConnection.Model(wfr). diff --git a/pkg/pipeline/CdHandler.go b/pkg/pipeline/CdHandler.go index e11c2ca76e..a45551df66 100644 --- a/pkg/pipeline/CdHandler.go +++ b/pkg/pipeline/CdHandler.go @@ -279,9 +279,9 @@ func (impl *CdHandlerImpl) UpdateWorkflow(workflowStatus bean6.CiCdStatus) (int, return 0, "", false, err } - savedWorkflow, err := impl.cdWorkflowRepository.FindWorkflowRunnerById(workflowId) + savedWorkflow, err := impl.cdWorkflowRepository.FindPreOrPostCdWorkflowRunnerById(workflowId) if err != nil { - impl.Logger.Error("cannot get saved wf", "err", err) + impl.Logger.Error("cannot get saved wf", "workflowId", workflowId, "err", err) return 0, "", false, err } diff --git a/pkg/pipeline/executors/WorkflowUtils.go b/pkg/pipeline/executors/WorkflowUtils.go index c812f761fe..f59022d797 100644 --- a/pkg/pipeline/executors/WorkflowUtils.go +++ b/pkg/pipeline/executors/WorkflowUtils.go @@ -288,8 +288,11 @@ func GetClientInstance(config *rest.Config, namespace string) (v1alpha12.Workflo } func CheckIfReTriggerRequired(status, message, workflowRunnerStatus string) bool { - return ((status == string(v1alpha1.NodeError) || status == string(v1alpha1.NodeFailed)) && - message == cdWorkflow.POD_DELETED_MESSAGE) && (workflowRunnerStatus != cdWorkflow.WorkflowCancel && workflowRunnerStatus != cdWorkflow.WorkflowAborted) + return (status == string(v1alpha1.NodeError) || status == string(v1alpha1.NodeFailed)) && + message == cdWorkflow.POD_DELETED_MESSAGE && + workflowRunnerStatus != cdWorkflow.WorkflowCancel && + workflowRunnerStatus != cdWorkflow.WorkflowAborted && + workflowRunnerStatus != cdWorkflow.WorkflowSucceeded } From 30fd819b7ac8fd3a10ffda53e439cca19fba834f Mon Sep 17 00:00:00 2001 From: Ash-exp Date: Thu, 3 Apr 2025 13:43:35 +0530 Subject: [PATCH 05/19] fix: workflow message update --- .../pipelineConfig/bean/cdWorkflow/bean.go | 54 ------------------- pkg/pipeline/CdHandler.go | 30 +++++++---- pkg/pipeline/CiHandler.go | 16 ++++-- 3 files changed, 31 insertions(+), 69 deletions(-) delete mode 100644 internal/sql/repository/pipelineConfig/bean/cdWorkflow/bean.go diff --git a/internal/sql/repository/pipelineConfig/bean/cdWorkflow/bean.go b/internal/sql/repository/pipelineConfig/bean/cdWorkflow/bean.go deleted file mode 100644 index 645ef52eb2..0000000000 --- a/internal/sql/repository/pipelineConfig/bean/cdWorkflow/bean.go +++ /dev/null @@ -1,54 +0,0 @@ -package cdWorkflow - -import ( - "errors" - "github.com/devtron-labs/common-lib/utils/k8s/health" - "github.com/devtron-labs/devtron/client/argocdServer/bean" -) - -var WfrTerminalStatusList = []string{WorkflowAborted, WorkflowFailed, WorkflowSucceeded, bean.HIBERNATING, string(health.HealthStatusHealthy), string(health.HealthStatusDegraded)} - -type WorkflowStatus int - -const ( - WF_UNKNOWN WorkflowStatus = iota - REQUEST_ACCEPTED - ENQUEUED - QUE_ERROR - WF_STARTED - DROPPED_STALE - DEQUE_ERROR - TRIGGER_ERROR -) - -const ( - WorkflowStarting = "Starting" - WorkflowInQueue = "Queued" - WorkflowInitiated = "Initiating" - WorkflowInProgress = "Progressing" - WorkflowAborted = "Aborted" - WorkflowFailed = "Failed" - WorkflowSucceeded = "Succeeded" - WorkflowTimedOut = "TimedOut" - WorkflowUnableToFetchState = "UnableToFetch" - WorkflowTypeDeploy = "DEPLOY" - WorkflowTypePre = "PRE" - WorkflowTypePost = "POST" -) - -func (a WorkflowStatus) String() string { - return [...]string{"WF_UNKNOWN", "REQUEST_ACCEPTED", "ENQUEUED", "QUE_ERROR", "WF_STARTED", "DROPPED_STALE", "DEQUE_ERROR", "TRIGGER_ERROR"}[a] -} - -var ErrorDeploymentSuperseded = errors.New(NEW_DEPLOYMENT_INITIATED) - -const ( - WORKFLOW_EXECUTOR_TYPE_AWF = "AWF" - WORKFLOW_EXECUTOR_TYPE_SYSTEM = "SYSTEM" - NEW_DEPLOYMENT_INITIATED = "A new deployment was initiated before this deployment completed!" - PIPELINE_DELETED = "The pipeline has been deleted!" - FOUND_VULNERABILITY = "Found vulnerability on image" - GITOPS_REPO_NOT_CONFIGURED = "GitOps repository is not configured for the app" -) - -type WorkflowExecutorType string diff --git a/pkg/pipeline/CdHandler.go b/pkg/pipeline/CdHandler.go index a45551df66..6a12c1ed01 100644 --- a/pkg/pipeline/CdHandler.go +++ b/pkg/pipeline/CdHandler.go @@ -22,8 +22,8 @@ import ( "fmt" "github.com/devtron-labs/common-lib/utils" bean4 "github.com/devtron-labs/common-lib/utils/bean" - "github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig/adapter/cdWorkflow" - cdWorkflow2 "github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig/bean/workflow/cdWorkflow" + cdWorkflowAdapter "github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig/adapter/cdWorkflow" + cdWorkflowBean "github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig/bean/workflow/cdWorkflow" bean2 "github.com/devtron-labs/devtron/pkg/bean" "github.com/devtron-labs/devtron/pkg/build/artifacts/imageTagging" "github.com/devtron-labs/devtron/pkg/cluster/adapter" @@ -39,6 +39,7 @@ import ( "net/http" "os" "path/filepath" + "slices" "strconv" "strings" "time" @@ -227,7 +228,7 @@ func (impl *CdHandlerImpl) CancelStage(workflowRunnerId int, forceAbort bool, us return 0, err } } - workflowRunner.Status = cdWorkflow2.WorkflowCancel + workflowRunner.Status = cdWorkflowBean.WorkflowCancel workflowRunner.UpdatedOn = time.Now() workflowRunner.UpdatedBy = userId err = impl.cdWorkflowRunnerService.UpdateCdWorkflowRunnerWithStage(workflowRunner) @@ -239,7 +240,7 @@ func (impl *CdHandlerImpl) CancelStage(workflowRunnerId int, forceAbort bool, us } func (impl *CdHandlerImpl) updateWorkflowRunnerForForceAbort(workflowRunner *pipelineConfig.CdWorkflowRunner) error { - workflowRunner.Status = cdWorkflow2.WorkflowCancel + workflowRunner.Status = cdWorkflowBean.WorkflowCancel workflowRunner.PodStatus = string(bean2.Failed) workflowRunner.Message = constants.FORCE_ABORT_MESSAGE_AFTER_STARTING_STAGE err := impl.cdWorkflowRunnerService.UpdateCdWorkflowRunnerWithStage(workflowRunner) @@ -288,13 +289,22 @@ func (impl *CdHandlerImpl) UpdateWorkflow(workflowStatus bean6.CiCdStatus) (int, cdArtifactLocationFormat := impl.config.GetArtifactLocationFormat() cdArtifactLocation := fmt.Sprintf(cdArtifactLocationFormat, savedWorkflow.CdWorkflowId, savedWorkflow.Id) if impl.stateChanged(status, podStatus, message, workflowStatus.FinishedAt.Time, savedWorkflow) { - if savedWorkflow.Status != cdWorkflow2.WorkflowCancel { + if savedWorkflow.Status != cdWorkflowBean.WorkflowCancel { savedWorkflow.Status = status } savedWorkflow.CdArtifactLocation = cdArtifactLocation savedWorkflow.PodStatus = podStatus - savedWorkflow.Message = message - savedWorkflow.FinishedOn = workflowStatus.FinishedAt.Time + if !slices.Contains(cdWorkflowBean.WfrTerminalStatusList, savedWorkflow.Status) { + savedWorkflow.Message = message + // NOTE: we are doing this to fix where a pre-cd / post-cd workflow message becomes larger than 1000, and in db we had set the charter limit to 1000 + if len(message) > 1000 { + savedWorkflow.Message = message[:1000] + } + savedWorkflow.FinishedOn = workflowStatus.FinishedAt.Time + } else { + impl.Logger.Warnw("cd stage already in terminal state. skipped message and finishedOn from being updated", + "wfId", savedWorkflow.Id, "status", savedWorkflow.Status, "message", message, "finishedOn", workflowStatus.FinishedAt.Time) + } savedWorkflow.Name = workflowName // removed log location from here since we are saving it at trigger savedWorkflow.PodName = podName @@ -312,7 +322,7 @@ func (impl *CdHandlerImpl) UpdateWorkflow(workflowStatus bean6.CiCdStatus) (int, impl.Logger.Errorw("error in fetching environment deployment config by appId and envId", "appId", appId, "envId", envId, "err", err) return 0, "", true, err } - util3.TriggerCDMetrics(cdWorkflow.GetTriggerMetricsFromRunnerObj(savedWorkflow, envDeploymentConfig), impl.config.ExposeCDMetrics) + util3.TriggerCDMetrics(cdWorkflowAdapter.GetTriggerMetricsFromRunnerObj(savedWorkflow, envDeploymentConfig), impl.config.ExposeCDMetrics) if string(v1alpha1.NodeError) == savedWorkflow.Status || string(v1alpha1.NodeFailed) == savedWorkflow.Status { impl.Logger.Warnw("cd stage failed for workflow: ", "wfId", savedWorkflow.Id) } @@ -558,7 +568,7 @@ func (impl *CdHandlerImpl) getWorkflowLogs(pipelineId int, cdWorkflow *pipelineC if logStream == nil || err != nil { if !cdWorkflow.BlobStorageEnabled { return nil, nil, errors.New("logs-not-stored-in-repository") - } else if string(v1alpha1.NodeSucceeded) == cdWorkflow.Status || string(v1alpha1.NodeError) == cdWorkflow.Status || string(v1alpha1.NodeFailed) == cdWorkflow.Status || cdWorkflow.Status == cdWorkflow2.WorkflowCancel { + } else if string(v1alpha1.NodeSucceeded) == cdWorkflow.Status || string(v1alpha1.NodeError) == cdWorkflow.Status || string(v1alpha1.NodeFailed) == cdWorkflow.Status || cdWorkflow.Status == cdWorkflowBean.WorkflowCancel { impl.Logger.Debugw("pod is not live", "podName", cdWorkflow.PodName, "err", err) return impl.getLogsFromRepository(pipelineId, cdWorkflow, clusterConfig, runStageInEnv) } @@ -583,7 +593,7 @@ func (impl *CdHandlerImpl) getLogsFromRepository(pipelineId int, cdWorkflow *pip PipelineId: cdWorkflow.CdWorkflow.PipelineId, WorkflowId: cdWorkflow.Id, PodName: cdWorkflow.PodName, - LogsFilePath: cdWorkflow.LogLocation, // impl.ciCdConfig.CiDefaultBuildLogsKeyPrefix + "/" + cdWorkflow.Name + "/main.log", //TODO - fixme + LogsFilePath: cdWorkflow.LogLocation, // impl.ciCdConfig.CiDefaultBuildLogsKeyPrefix + "/" + cdWorkflowAda.Name + "/main.log", //TODO - fixme CloudProvider: impl.config.CloudProvider, AzureBlobConfig: &blob_storage.AzureBlobBaseConfig{ Enabled: impl.config.CloudProvider == types.BLOB_STORAGE_AZURE, diff --git a/pkg/pipeline/CiHandler.go b/pkg/pipeline/CiHandler.go index fa7ee5d455..7549bbe34f 100644 --- a/pkg/pipeline/CiHandler.go +++ b/pkg/pipeline/CiHandler.go @@ -41,6 +41,7 @@ import ( "os" "path/filepath" "regexp" + "slices" "strconv" "strings" "time" @@ -1203,16 +1204,21 @@ func (impl *CiHandlerImpl) UpdateWorkflow(workflowStatus bean6.CiCdStatus) (int, savedWorkflow.Status = status } savedWorkflow.PodStatus = podStatus - savedWorkflow.Message = message - // NOTE: we are doing this for a quick fix where ci pending message become larger than 250 and in db we had set the charter limit to 250 - if len(message) > 250 { - savedWorkflow.Message = message[:250] + if !slices.Contains(cdWorkflow.WfrTerminalStatusList, savedWorkflow.Status) { + savedWorkflow.Message = message + // NOTE: we are doing this for a quick fix where ci pending message become larger than 250 and in db we had set the charter limit to 250 + if len(message) > 250 { + savedWorkflow.Message = message[:250] + } + savedWorkflow.FinishedOn = workflowStatus.FinishedAt.Time + } else { + impl.Logger.Warnw("cd stage already in terminal state. skipped message and finishedOn from being updated", + "wfId", savedWorkflow.Id, "status", savedWorkflow.Status, "message", message, "finishedOn", workflowStatus.FinishedAt.Time) } if savedWorkflow.ExecutorType == cdWorkflow.WORKFLOW_EXECUTOR_TYPE_SYSTEM && savedWorkflow.Status == cdWorkflow.WorkflowCancel { savedWorkflow.PodStatus = "Failed" savedWorkflow.Message = constants2.TERMINATE_MESSAGE } - savedWorkflow.FinishedOn = workflowStatus.FinishedAt.Time savedWorkflow.Name = workflowName //savedWorkflow.LogLocation = "/ci-pipeline/" + strconv.Itoa(savedWorkflow.CiPipelineId) + "/workflow/" + strconv.Itoa(savedWorkflow.Id) + "/logs" //TODO need to fetch from workflow object //savedWorkflow.LogLocation = logLocation // removed because we are saving log location at trigger From 8ca9d531dffa3aeb1d45cbd4e95195b6948d535c Mon Sep 17 00:00:00 2001 From: Ash-exp Date: Thu, 3 Apr 2025 13:50:55 +0530 Subject: [PATCH 06/19] updated import alias --- pkg/pipeline/CdHandler.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/pipeline/CdHandler.go b/pkg/pipeline/CdHandler.go index 6a12c1ed01..ef088b323f 100644 --- a/pkg/pipeline/CdHandler.go +++ b/pkg/pipeline/CdHandler.go @@ -22,7 +22,7 @@ import ( "fmt" "github.com/devtron-labs/common-lib/utils" bean4 "github.com/devtron-labs/common-lib/utils/bean" - cdWorkflowAdapter "github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig/adapter/cdWorkflow" + pipelineAdapter "github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig/adapter/cdWorkflow" cdWorkflowBean "github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig/bean/workflow/cdWorkflow" bean2 "github.com/devtron-labs/devtron/pkg/bean" "github.com/devtron-labs/devtron/pkg/build/artifacts/imageTagging" @@ -56,7 +56,7 @@ import ( pipelineBean "github.com/devtron-labs/devtron/pkg/pipeline/bean" "github.com/devtron-labs/devtron/pkg/pipeline/types" resourceGroup2 "github.com/devtron-labs/devtron/pkg/resourceGroup" - util3 "github.com/devtron-labs/devtron/util" + globalUtil "github.com/devtron-labs/devtron/util" "github.com/devtron-labs/devtron/util/rbac" "github.com/go-pg/pg" "go.opentelemetry.io/otel" @@ -322,7 +322,7 @@ func (impl *CdHandlerImpl) UpdateWorkflow(workflowStatus bean6.CiCdStatus) (int, impl.Logger.Errorw("error in fetching environment deployment config by appId and envId", "appId", appId, "envId", envId, "err", err) return 0, "", true, err } - util3.TriggerCDMetrics(cdWorkflowAdapter.GetTriggerMetricsFromRunnerObj(savedWorkflow, envDeploymentConfig), impl.config.ExposeCDMetrics) + globalUtil.TriggerCDMetrics(pipelineAdapter.GetTriggerMetricsFromRunnerObj(savedWorkflow, envDeploymentConfig), impl.config.ExposeCDMetrics) if string(v1alpha1.NodeError) == savedWorkflow.Status || string(v1alpha1.NodeFailed) == savedWorkflow.Status { impl.Logger.Warnw("cd stage failed for workflow: ", "wfId", savedWorkflow.Id) } @@ -593,7 +593,7 @@ func (impl *CdHandlerImpl) getLogsFromRepository(pipelineId int, cdWorkflow *pip PipelineId: cdWorkflow.CdWorkflow.PipelineId, WorkflowId: cdWorkflow.Id, PodName: cdWorkflow.PodName, - LogsFilePath: cdWorkflow.LogLocation, // impl.ciCdConfig.CiDefaultBuildLogsKeyPrefix + "/" + cdWorkflowAda.Name + "/main.log", //TODO - fixme + LogsFilePath: cdWorkflow.LogLocation, // impl.ciCdConfig.CiDefaultBuildLogsKeyPrefix + "/" + cdWorkflow.Name + "/main.log", //TODO - fixme CloudProvider: impl.config.CloudProvider, AzureBlobConfig: &blob_storage.AzureBlobBaseConfig{ Enabled: impl.config.CloudProvider == types.BLOB_STORAGE_AZURE, From 4e73878e46a5ee1b4f5e8e40c01fe15d547f21e0 Mon Sep 17 00:00:00 2001 From: Ash-exp Date: Thu, 3 Apr 2025 14:24:32 +0530 Subject: [PATCH 07/19] fix: ci/ cd status update inconsistencies --- .../configure/BuildPipelineRestHandler.go | 2 +- .../in/WorkflowEventProcessorService.go | 25 ++++++++++-------- pkg/pipeline/CdHandler.go | 18 ++++++------- pkg/pipeline/CiHandler.go | 26 +++++++++---------- 4 files changed, 37 insertions(+), 34 deletions(-) diff --git a/api/restHandler/app/pipeline/configure/BuildPipelineRestHandler.go b/api/restHandler/app/pipeline/configure/BuildPipelineRestHandler.go index cb730a93ab..54c549df45 100644 --- a/api/restHandler/app/pipeline/configure/BuildPipelineRestHandler.go +++ b/api/restHandler/app/pipeline/configure/BuildPipelineRestHandler.go @@ -1508,7 +1508,7 @@ func (handler *PipelineConfigRestHandlerImpl) HandleWorkflowWebhook(w http.Respo return } handler.Logger.Infow("request payload, HandleWorkflowWebhook", "payload", wfUpdateReq) - resp, err := handler.ciHandler.UpdateWorkflow(wfUpdateReq) + resp, _, err := handler.ciHandler.UpdateWorkflow(wfUpdateReq) if err != nil { handler.Logger.Errorw("service err, HandleWorkflowWebhook", "err", err, "payload", wfUpdateReq) common.WriteJsonResp(w, err, resp, http.StatusInternalServerError) diff --git a/pkg/eventProcessor/in/WorkflowEventProcessorService.go b/pkg/eventProcessor/in/WorkflowEventProcessorService.go index 49b127f95a..3496f92aaf 100644 --- a/pkg/eventProcessor/in/WorkflowEventProcessorService.go +++ b/pkg/eventProcessor/in/WorkflowEventProcessorService.go @@ -414,18 +414,20 @@ func (impl *WorkflowEventProcessorImpl) SubscribeCIWorkflowStatusUpdate() error return } } - err = impl.ciHandler.CheckAndReTriggerCI(wfStatus) + // update the ci workflow status + _, stateChanged, err := impl.ciHandler.UpdateWorkflow(wfStatus) if err != nil { - impl.logger.Errorw("error in checking and re triggering ci", "err", err) - //don't return as we have to update the workflow status - } - - _, err = impl.ciHandler.UpdateWorkflow(wfStatus) - if err != nil { - impl.logger.Errorw("error on update workflow status", "err", err, "msg", msg.Data) + impl.logger.Errorw("error on update workflow status", "msg", msg.Data, "err", err) return } - + if stateChanged { + // check if we need to re-trigger the ci + err = impl.ciHandler.CheckAndReTriggerCI(wfStatus) + if err != nil { + impl.logger.Errorw("error in checking and re triggering ci", "wfStatus", wfStatus, "err", err) + return + } + } } // add required logging here @@ -474,9 +476,9 @@ func (impl *WorkflowEventProcessorImpl) SubscribeCDWorkflowStatusUpdate() error } } wfrId, wfrStatus, stateChanged, err := impl.cdHandler.UpdateWorkflow(wfStatus) - impl.logger.Debugw("UpdateWorkflow", "wfrId", wfrId, "wfrStatus", wfrStatus) + impl.logger.Debugw("cd UpdateWorkflow for wfStatus", "wfrId", wfrId, "wfrStatus", wfrStatus, "wfStatus", wfStatus) if err != nil { - impl.logger.Error("err", err) + impl.logger.Errorw("error in cd workflow status update", "wfrId", wfrId, "wfrStatus", wfrStatus, "wfStatus", wfStatus, "err", err) return } @@ -492,6 +494,7 @@ func (impl *WorkflowEventProcessorImpl) SubscribeCDWorkflowStatusUpdate() error err := impl.cdHandler.DeactivateImageReservationPathsOnFailure(wfr.ImagePathReservationIds) if err != nil { impl.logger.Errorw("error in removing image path reservation ", "imagePathReservationIds", wfr.ImagePathReservationIds, "err", err) + // not returning here as we need to send the notification event and re-trigger the cd stage (if required) } } } diff --git a/pkg/pipeline/CdHandler.go b/pkg/pipeline/CdHandler.go index ef088b323f..533a39515b 100644 --- a/pkg/pipeline/CdHandler.go +++ b/pkg/pipeline/CdHandler.go @@ -268,15 +268,15 @@ func (impl *CdHandlerImpl) handleForceAbortCaseForCdStage(workflowRunner *pipeli } func (impl *CdHandlerImpl) UpdateWorkflow(workflowStatus bean6.CiCdStatus) (int, string, bool, error) { - wfStatusRs := impl.extractWorkfowStatus(workflowStatus) + wfStatusRs := impl.extractWorkflowStatus(workflowStatus) workflowName, status, podStatus, message, podName := wfStatusRs.WorkflowName, wfStatusRs.Status, wfStatusRs.PodStatus, wfStatusRs.Message, wfStatusRs.PodName - impl.Logger.Debugw("cd update for ", "wf ", workflowName, "status", status) + impl.Logger.Debugw("cd workflow status update event for", "wf ", workflowName, "status", status) if workflowName == "" { return 0, "", false, errors.New("invalid wf name") } workflowId, err := strconv.Atoi(workflowName[:strings.Index(workflowName, "-")]) if err != nil { - impl.Logger.Error("invalid wf status update req", "err", err) + impl.Logger.Errorw("invalid wf status update req", "workflowName", workflowName, "err", err) return 0, "", false, err } @@ -309,29 +309,29 @@ func (impl *CdHandlerImpl) UpdateWorkflow(workflowStatus bean6.CiCdStatus) (int, // removed log location from here since we are saving it at trigger savedWorkflow.PodName = podName savedWorkflow.UpdateAuditLog(1) - impl.Logger.Debugw("updating workflow ", "workflow", savedWorkflow) + impl.Logger.Debugw("updating cd workflow runner", "workflow", savedWorkflow) err = impl.cdWorkflowRunnerService.UpdateCdWorkflowRunnerWithStage(savedWorkflow) if err != nil { - impl.Logger.Error("update wf failed for id " + strconv.Itoa(savedWorkflow.Id)) - return 0, "", true, err + impl.Logger.Errorw("update wf failed for id", "wfId", savedWorkflow.Id, "err", err) + return savedWorkflow.Id, "", true, err } appId := savedWorkflow.CdWorkflow.Pipeline.AppId envId := savedWorkflow.CdWorkflow.Pipeline.EnvironmentId envDeploymentConfig, err := impl.deploymentConfigService.GetConfigForDevtronApps(appId, envId) if err != nil { impl.Logger.Errorw("error in fetching environment deployment config by appId and envId", "appId", appId, "envId", envId, "err", err) - return 0, "", true, err + return savedWorkflow.Id, savedWorkflow.Status, true, err } globalUtil.TriggerCDMetrics(pipelineAdapter.GetTriggerMetricsFromRunnerObj(savedWorkflow, envDeploymentConfig), impl.config.ExposeCDMetrics) if string(v1alpha1.NodeError) == savedWorkflow.Status || string(v1alpha1.NodeFailed) == savedWorkflow.Status { - impl.Logger.Warnw("cd stage failed for workflow: ", "wfId", savedWorkflow.Id) + impl.Logger.Warnw("cd stage failed for workflow", "wfId", savedWorkflow.Id) } return savedWorkflow.Id, savedWorkflow.Status, true, nil } return savedWorkflow.Id, savedWorkflow.Status, false, nil } -func (impl *CdHandlerImpl) extractWorkfowStatus(workflowStatus bean6.CiCdStatus) *types.WorkflowStatus { +func (impl *CdHandlerImpl) extractWorkflowStatus(workflowStatus bean6.CiCdStatus) *types.WorkflowStatus { workflowName := "" status := string(workflowStatus.Phase) podStatus := "Pending" diff --git a/pkg/pipeline/CiHandler.go b/pkg/pipeline/CiHandler.go index 7549bbe34f..81aaeb187d 100644 --- a/pkg/pipeline/CiHandler.go +++ b/pkg/pipeline/CiHandler.go @@ -90,7 +90,7 @@ type CiHandler interface { GetBuildHistory(pipelineId int, appId int, offset int, size int) ([]types.WorkflowResponse, error) DownloadCiWorkflowArtifacts(pipelineId int, buildId int) (*os.File, error) - UpdateWorkflow(workflowStatus bean6.CiCdStatus) (int, error) + UpdateWorkflow(workflowStatus bean6.CiCdStatus) (int, bool, error) FetchCiStatusForTriggerView(appId int) ([]*pipelineConfig.CiWorkflowStatus, error) FetchCiStatusForTriggerViewV1(appId int) ([]*pipelineConfig.CiWorkflowStatus, error) @@ -1165,35 +1165,34 @@ func (impl *CiHandlerImpl) extractPodStatusAndWorkflow(workflowStatus bean6.CiCd } func (impl *CiHandlerImpl) getRefWorkflowAndCiRetryCount(savedWorkflow *pipelineConfig.CiWorkflow) (int, *pipelineConfig.CiWorkflow, error) { - var err error - if savedWorkflow.ReferenceCiWorkflowId != 0 { + var err error savedWorkflow, err = impl.ciWorkflowRepository.FindById(savedWorkflow.ReferenceCiWorkflowId) - } - if err != nil { - impl.Logger.Errorw("cannot get saved wf", "err", err) - return 0, savedWorkflow, err + if err != nil { + impl.Logger.Errorw("cannot get saved wf", "err", err) + return 0, savedWorkflow, err + } } retryCount, err := impl.ciWorkflowRepository.FindRetriedWorkflowCountByReferenceId(savedWorkflow.Id) return retryCount, savedWorkflow, err } -func (impl *CiHandlerImpl) UpdateWorkflow(workflowStatus bean6.CiCdStatus) (int, error) { +func (impl *CiHandlerImpl) UpdateWorkflow(workflowStatus bean6.CiCdStatus) (int, bool, error) { workflowName, status, podStatus, message, _, podName := ExtractWorkflowStatus(workflowStatus) if workflowName == "" { impl.Logger.Errorw("extract workflow status, invalid wf name", "workflowName", workflowName, "status", status, "podStatus", podStatus, "message", message) - return 0, errors.New("invalid wf name") + return 0, false, errors.New("invalid wf name") } workflowId, err := strconv.Atoi(workflowName[:strings.Index(workflowName, "-")]) if err != nil { impl.Logger.Errorw("invalid wf status update req", "err", err) - return 0, err + return 0, false, err } savedWorkflow, err := impl.ciWorkflowRepository.FindById(workflowId) if err != nil { impl.Logger.Errorw("cannot get saved wf", "err", err) - return 0, err + return 0, false, err } ciArtifactLocationFormat := impl.config.GetArtifactLocationFormat() @@ -1228,11 +1227,12 @@ func (impl *CiHandlerImpl) UpdateWorkflow(workflowStatus bean6.CiCdStatus) (int, err = impl.ciService.UpdateCiWorkflowWithStage(savedWorkflow) if err != nil { impl.Logger.Error("update wf failed for id " + strconv.Itoa(savedWorkflow.Id)) - return 0, err + return savedWorkflow.Id, true, err } impl.sendCIFailEvent(savedWorkflow, status, message) + return savedWorkflow.Id, true, nil } - return savedWorkflow.Id, nil + return savedWorkflow.Id, false, nil } func (impl *CiHandlerImpl) sendCIFailEvent(savedWorkflow *pipelineConfig.CiWorkflow, status, message string) { From b49821ebc7cfaa8bb6443c90a6c9ffabb7a877bf Mon Sep 17 00:00:00 2001 From: Ash-exp Date: Thu, 3 Apr 2025 23:03:08 +0530 Subject: [PATCH 08/19] fix: checkForOptOut method error handling --- client/telemetry/TelemetryEventClient.go | 2 +- go.mod | 4 ++-- go.sum | 8 ++++---- .../devtron-labs/authenticator/client/oidcClient.go | 11 +++++++---- vendor/modules.txt | 8 ++++---- 5 files changed, 18 insertions(+), 15 deletions(-) diff --git a/client/telemetry/TelemetryEventClient.go b/client/telemetry/TelemetryEventClient.go index a64196242f..7a4a697094 100644 --- a/client/telemetry/TelemetryEventClient.go +++ b/client/telemetry/TelemetryEventClient.go @@ -686,8 +686,8 @@ func (impl *TelemetryEventClientImpl) checkForOptOut(ctx context.Context, UCID s response, err := util.HttpRequest(newCtx, url) if err != nil { + // this should be non-blocking call and should not fail the request for ucid getting impl.logger.Errorw("check opt-out list failed, rest api error", "ucid", UCID, "err", err) - return false, err } flag := response["result"].(bool) return flag, nil diff --git a/go.mod b/go.mod index c9ccd0dd10..aa0d1cdcd6 100644 --- a/go.mod +++ b/go.mod @@ -307,8 +307,8 @@ require ( replace ( github.com/argoproj/argo-workflows/v3 => github.com/devtron-labs/argo-workflows/v3 v3.5.13 - github.com/devtron-labs/authenticator => github.com/devtron-labs/devtron-services/authenticator v0.0.0-20250402155428-3fa1ffc068e2 - github.com/devtron-labs/common-lib => github.com/devtron-labs/devtron-services/common-lib v0.0.0-20250402155428-3fa1ffc068e2 + github.com/devtron-labs/authenticator => github.com/devtron-labs/devtron-services/authenticator v0.0.0-20250403171407-721f466f49ce + github.com/devtron-labs/common-lib => github.com/devtron-labs/devtron-services/common-lib v0.0.0-20250403171407-721f466f49ce github.com/go-check/check => github.com/go-check/check v0.0.0-20180628173108-788fd7840127 github.com/googleapis/gnostic => github.com/googleapis/gnostic v0.5.5 k8s.io/api => k8s.io/api v0.29.7 diff --git a/go.sum b/go.sum index 9b29696f0c..2a9b9bb3e6 100644 --- a/go.sum +++ b/go.sum @@ -829,10 +829,10 @@ github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc h1:VRRKCwnzq github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/devtron-labs/argo-workflows/v3 v3.5.13 h1:3pINq0gXOSeTw2z/vYe+j80lRpSN5Rp/8mfQORh8SmU= github.com/devtron-labs/argo-workflows/v3 v3.5.13/go.mod h1:/vqxcovDPT4zqr4DjR5v7CF8ggpY1l3TSa2CIG3jmjA= -github.com/devtron-labs/devtron-services/authenticator v0.0.0-20250402155428-3fa1ffc068e2 h1:Ik3LiAVccf6gqrbEwryD/uPYbSV/i7z4UTvYcLgM8jk= -github.com/devtron-labs/devtron-services/authenticator v0.0.0-20250402155428-3fa1ffc068e2/go.mod h1:FfaLDXN1ZXxyRpnskBqVIYkpkWDCzBmDgIO9xqLnxdQ= -github.com/devtron-labs/devtron-services/common-lib v0.0.0-20250402155428-3fa1ffc068e2 h1:k2bWvWk6if6I7k+URmrh1Dp2fleNDNu/pl+ZnImeUGE= -github.com/devtron-labs/devtron-services/common-lib v0.0.0-20250402155428-3fa1ffc068e2/go.mod h1:zkNShlkcHxsmnL0gKNbs0uyRL8lZonGKr5Km63uTLI0= +github.com/devtron-labs/devtron-services/authenticator v0.0.0-20250403171407-721f466f49ce h1:A4+SH98TFhHo/cUWi9CE3rbw0TjU6uH7cfOFOsmQrqk= +github.com/devtron-labs/devtron-services/authenticator v0.0.0-20250403171407-721f466f49ce/go.mod h1:FfaLDXN1ZXxyRpnskBqVIYkpkWDCzBmDgIO9xqLnxdQ= +github.com/devtron-labs/devtron-services/common-lib v0.0.0-20250403171407-721f466f49ce h1:hp5p/mPLsoCyqM51b88Uu8AgCTn0K2bwKEsB5Fy2C24= +github.com/devtron-labs/devtron-services/common-lib v0.0.0-20250403171407-721f466f49ce/go.mod h1:zkNShlkcHxsmnL0gKNbs0uyRL8lZonGKr5Km63uTLI0= github.com/devtron-labs/go-bitbucket v0.9.60-beta h1:VEx1jvDgdtDPS6A1uUFoaEi0l1/oLhbr+90xOwr6sDU= github.com/devtron-labs/go-bitbucket v0.9.60-beta/go.mod h1:GnuiCesvh8xyHeMCb+twm8lBR/kQzJYSKL28ZfObp1Y= github.com/devtron-labs/protos v0.0.3-0.20250323220609-ecf8a0f7305e h1:U6UdYbW8a7xn5IzFPd8cywjVVPfutGJCudjePAfL/Hs= diff --git a/vendor/github.com/devtron-labs/authenticator/client/oidcClient.go b/vendor/github.com/devtron-labs/authenticator/client/oidcClient.go index b7dcba2f99..551dec305e 100644 --- a/vendor/github.com/devtron-labs/authenticator/client/oidcClient.go +++ b/vendor/github.com/devtron-labs/authenticator/client/oidcClient.go @@ -44,9 +44,11 @@ func GetSettings(conf *DexConfig) (*oidc.Settings, error) { settings := &oidc.Settings{ URL: conf.Url, OIDCConfig: oidc.OIDCConfig{CLIClientID: conf.DexClientID, - ClientSecret: conf.DexClientSecret, - Issuer: proxyUrl, - ServerSecret: conf.ServerSecret}, + ClientSecret: conf.DexClientSecret, + Issuer: proxyUrl, + ServerSecret: conf.ServerSecret, + RequestedScopes: conf.DexScopes, + }, UserSessionDuration: time.Duration(conf.UserSessionDurationSeconds) * time.Second, AdminPasswordMtime: conf.AdminPasswordMtime, } @@ -88,7 +90,8 @@ type DexConfig struct { UserSessionDurationSeconds int `env:"USER_SESSION_DURATION_SECONDS" envDefault:"86400"` AdminPasswordMtime time.Time `json:"ADMIN_PASSWORD_MTIME"` DexConfigRaw string - DevtronSecretName string `env:"DEVTRON_SECRET_NAME" envDefault:"devtron-secret"` + DevtronSecretName string `env:"DEVTRON_SECRET_NAME" envDefault:"devtron-secret"` + DexScopes []string `env:"DEX_SCOPES" envDefault:"" envSeparator:","` } func (c *DexConfig) GetDexProxyUrl() (string, error) { diff --git a/vendor/modules.txt b/vendor/modules.txt index 7084a09385..ae3dc39f9b 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -472,7 +472,7 @@ github.com/davecgh/go-spew/spew # github.com/deckarep/golang-set v1.8.0 ## explicit; go 1.17 github.com/deckarep/golang-set -# github.com/devtron-labs/authenticator v0.4.35-0.20240809073103-6e11da8083f8 => github.com/devtron-labs/devtron-services/authenticator v0.0.0-20250402155428-3fa1ffc068e2 +# github.com/devtron-labs/authenticator v0.4.35-0.20240809073103-6e11da8083f8 => github.com/devtron-labs/devtron-services/authenticator v0.0.0-20250403171407-721f466f49ce ## explicit; go 1.21 github.com/devtron-labs/authenticator/apiToken github.com/devtron-labs/authenticator/client @@ -480,7 +480,7 @@ github.com/devtron-labs/authenticator/jwt github.com/devtron-labs/authenticator/middleware github.com/devtron-labs/authenticator/oidc github.com/devtron-labs/authenticator/password -# github.com/devtron-labs/common-lib v0.18.1-0.20241001061923-eda545dc839e => github.com/devtron-labs/devtron-services/common-lib v0.0.0-20250402155428-3fa1ffc068e2 +# github.com/devtron-labs/common-lib v0.18.1-0.20241001061923-eda545dc839e => github.com/devtron-labs/devtron-services/common-lib v0.0.0-20250403171407-721f466f49ce ## explicit; go 1.21 github.com/devtron-labs/common-lib/async github.com/devtron-labs/common-lib/blob-storage @@ -2352,8 +2352,8 @@ xorm.io/xorm/names xorm.io/xorm/schemas xorm.io/xorm/tags # github.com/argoproj/argo-workflows/v3 => github.com/devtron-labs/argo-workflows/v3 v3.5.13 -# github.com/devtron-labs/authenticator => github.com/devtron-labs/devtron-services/authenticator v0.0.0-20250402155428-3fa1ffc068e2 -# github.com/devtron-labs/common-lib => github.com/devtron-labs/devtron-services/common-lib v0.0.0-20250402155428-3fa1ffc068e2 +# github.com/devtron-labs/authenticator => github.com/devtron-labs/devtron-services/authenticator v0.0.0-20250403171407-721f466f49ce +# github.com/devtron-labs/common-lib => github.com/devtron-labs/devtron-services/common-lib v0.0.0-20250403171407-721f466f49ce # github.com/go-check/check => github.com/go-check/check v0.0.0-20180628173108-788fd7840127 # github.com/googleapis/gnostic => github.com/googleapis/gnostic v0.5.5 # k8s.io/api => k8s.io/api v0.29.7 From 186394a4536d7acea18322b322d747fecea52eef Mon Sep 17 00:00:00 2001 From: Ash-exp Date: Thu, 3 Apr 2025 23:27:24 +0530 Subject: [PATCH 09/19] fix: panic handling --- .../configure/BuildPipelineRestHandler.go | 4 ++-- env_gen.json | 2 +- env_gen.md | 1 + pkg/eventProcessor/bean/workflowEventBean.go | 6 ++++++ .../in/WorkflowEventProcessorService.go | 8 ++++---- pkg/pipeline/CdHandler.go | 8 ++++---- pkg/pipeline/CiHandler.go | 18 +++++++++--------- 7 files changed, 27 insertions(+), 20 deletions(-) diff --git a/api/restHandler/app/pipeline/configure/BuildPipelineRestHandler.go b/api/restHandler/app/pipeline/configure/BuildPipelineRestHandler.go index 54c549df45..997da569b8 100644 --- a/api/restHandler/app/pipeline/configure/BuildPipelineRestHandler.go +++ b/api/restHandler/app/pipeline/configure/BuildPipelineRestHandler.go @@ -25,7 +25,7 @@ import ( "github.com/devtron-labs/devtron/internal/sql/constants" "github.com/devtron-labs/devtron/pkg/build/artifacts/imageTagging" bean2 "github.com/devtron-labs/devtron/pkg/build/pipeline/bean" - bean3 "github.com/devtron-labs/devtron/pkg/eventProcessor/bean" + eventProcessorBean "github.com/devtron-labs/devtron/pkg/eventProcessor/bean" constants2 "github.com/devtron-labs/devtron/pkg/pipeline/constants" "github.com/devtron-labs/devtron/util/stringsUtil" "golang.org/x/exp/maps" @@ -1500,7 +1500,7 @@ func (handler *PipelineConfigRestHandlerImpl) DeleteMaterial(w http.ResponseWrit func (handler *PipelineConfigRestHandlerImpl) HandleWorkflowWebhook(w http.ResponseWriter, r *http.Request) { decoder := json.NewDecoder(r.Body) - var wfUpdateReq bean3.CiCdStatus + var wfUpdateReq eventProcessorBean.CiCdStatus err := decoder.Decode(&wfUpdateReq) if err != nil { handler.Logger.Errorw("request err, HandleWorkflowWebhook", "err", err, "payload", wfUpdateReq) diff --git a/env_gen.json b/env_gen.json index b4b889fc79..ad32c0da18 100644 --- a/env_gen.json +++ b/env_gen.json @@ -1 +1 @@ -[{"Category":"CD","Fields":[{"Env":"ARGO_APP_MANUAL_SYNC_TIME","EnvType":"int","EnvValue":"3","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CD_HELM_PIPELINE_STATUS_CRON_TIME","EnvType":"string","EnvValue":"*/2 * * * *","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CD_PIPELINE_STATUS_CRON_TIME","EnvType":"string","EnvValue":"*/2 * * * *","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CD_PIPELINE_STATUS_TIMEOUT_DURATION","EnvType":"string","EnvValue":"20","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEPLOY_STATUS_CRON_GET_PIPELINE_DEPLOYED_WITHIN_HOURS","EnvType":"int","EnvValue":"12","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEVTRON_CHART_ARGO_CD_INSTALL_REQUEST_TIMEOUT","EnvType":"int","EnvValue":"1","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEVTRON_CHART_INSTALL_REQUEST_TIMEOUT","EnvType":"int","EnvValue":"6","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"EXPOSE_CD_METRICS","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"FEATURE_MIGRATE_ARGOCD_APPLICATION_ENABLE","EnvType":"bool","EnvValue":"false","EnvDescription":"enable migration of external argocd application to devtron pipeline","Example":"","Deprecated":"false"},{"Env":"HELM_PIPELINE_STATUS_CHECK_ELIGIBLE_TIME","EnvType":"string","EnvValue":"120","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"IS_INTERNAL_USE","EnvType":"bool","EnvValue":"true","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"MIGRATE_DEPLOYMENT_CONFIG_DATA","EnvType":"bool","EnvValue":"false","EnvDescription":"migrate deployment config data from charts table to deployment_config table","Example":"","Deprecated":"false"},{"Env":"PIPELINE_DEGRADED_TIME","EnvType":"string","EnvValue":"10","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"REVISION_HISTORY_LIMIT_DEVTRON_APP","EnvType":"int","EnvValue":"1","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"REVISION_HISTORY_LIMIT_EXTERNAL_HELM_APP","EnvType":"int","EnvValue":"0","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"REVISION_HISTORY_LIMIT_HELM_APP","EnvType":"int","EnvValue":"1","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"REVISION_HISTORY_LIMIT_LINKED_HELM_APP","EnvType":"int","EnvValue":"15","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"RUN_HELM_INSTALL_IN_ASYNC_MODE_HELM_APPS","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"SHOULD_CHECK_NAMESPACE_ON_CLONE","EnvType":"bool","EnvValue":"false","EnvDescription":"should we check if namespace exists or not while cloning app","Example":"","Deprecated":"false"},{"Env":"USE_DEPLOYMENT_CONFIG_DATA","EnvType":"bool","EnvValue":"false","EnvDescription":"use deployment config data from deployment_config table","Example":"","Deprecated":"true"}]},{"Category":"CI_RUNNER","Fields":[{"Env":"AZURE_ACCOUNT_KEY","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"AZURE_ACCOUNT_NAME","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"AZURE_BLOB_CONTAINER_CI_CACHE","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"AZURE_BLOB_CONTAINER_CI_LOG","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"AZURE_GATEWAY_CONNECTION_INSECURE","EnvType":"bool","EnvValue":"true","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"AZURE_GATEWAY_URL","EnvType":"string","EnvValue":"http://devtron-minio.devtroncd:9000","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"BASE_LOG_LOCATION_PATH","EnvType":"string","EnvValue":"/home/devtron/","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"BLOB_STORAGE_GCP_CREDENTIALS_JSON","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"BLOB_STORAGE_PROVIDER","EnvType":"","EnvValue":"S3","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"BLOB_STORAGE_S3_ACCESS_KEY","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"BLOB_STORAGE_S3_BUCKET_VERSIONED","EnvType":"bool","EnvValue":"true","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"BLOB_STORAGE_S3_ENDPOINT","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"BLOB_STORAGE_S3_ENDPOINT_INSECURE","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"BLOB_STORAGE_S3_SECRET_KEY","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"BUILDX_CACHE_PATH","EnvType":"string","EnvValue":"/var/lib/devtron/buildx","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"BUILDX_K8S_DRIVER_OPTIONS","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"BUILDX_PROVENANCE_MODE","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"BUILD_LOG_TTL_VALUE_IN_SECS","EnvType":"int","EnvValue":"3600","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CACHE_LIMIT","EnvType":"int64","EnvValue":"5000000000","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CD_DEFAULT_ADDRESS_POOL_BASE_CIDR","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CD_DEFAULT_ADDRESS_POOL_SIZE","EnvType":"int","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CD_LIMIT_CI_CPU","EnvType":"string","EnvValue":"0.5","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CD_LIMIT_CI_MEM","EnvType":"string","EnvValue":"3G","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CD_NODE_LABEL_SELECTOR","EnvType":"","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CD_NODE_TAINTS_KEY","EnvType":"string","EnvValue":"dedicated","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CD_NODE_TAINTS_VALUE","EnvType":"string","EnvValue":"ci","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CD_REQ_CI_CPU","EnvType":"string","EnvValue":"0.5","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CD_REQ_CI_MEM","EnvType":"string","EnvValue":"3G","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CD_WORKFLOW_EXECUTOR_TYPE","EnvType":"","EnvValue":"AWF","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CD_WORKFLOW_SERVICE_ACCOUNT","EnvType":"string","EnvValue":"cd-runner","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CI_DEFAULT_ADDRESS_POOL_BASE_CIDR","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CI_DEFAULT_ADDRESS_POOL_SIZE","EnvType":"int","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CI_IGNORE_DOCKER_CACHE","EnvType":"bool","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CI_LOGS_KEY_PREFIX","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CI_NODE_LABEL_SELECTOR","EnvType":"","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CI_NODE_TAINTS_KEY","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CI_NODE_TAINTS_VALUE","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CI_RUNNER_DOCKER_MTU_VALUE","EnvType":"int","EnvValue":"-1","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CI_SUCCESS_AUTO_TRIGGER_BATCH_SIZE","EnvType":"int","EnvValue":"1","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CI_VOLUME_MOUNTS_JSON","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CI_WORKFLOW_EXECUTOR_TYPE","EnvType":"","EnvValue":"AWF","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEFAULT_ARTIFACT_KEY_LOCATION","EnvType":"string","EnvValue":"arsenal-v1/ci-artifacts","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEFAULT_BUILD_LOGS_BUCKET","EnvType":"string","EnvValue":"devtron-pro-ci-logs","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEFAULT_BUILD_LOGS_KEY_PREFIX","EnvType":"string","EnvValue":"arsenal-v1","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEFAULT_CACHE_BUCKET","EnvType":"string","EnvValue":"ci-caching","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEFAULT_CACHE_BUCKET_REGION","EnvType":"string","EnvValue":"us-east-2","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEFAULT_CD_ARTIFACT_KEY_LOCATION","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEFAULT_CD_LOGS_BUCKET_REGION","EnvType":"string","EnvValue":"us-east-2","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEFAULT_CD_NAMESPACE","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEFAULT_CD_TIMEOUT","EnvType":"int64","EnvValue":"3600","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEFAULT_CI_IMAGE","EnvType":"string","EnvValue":"686244538589.dkr.ecr.us-east-2.amazonaws.com/cirunner:47","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEFAULT_NAMESPACE","EnvType":"string","EnvValue":"devtron-ci","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEFAULT_TARGET_PLATFORM","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DOCKER_BUILD_CACHE_PATH","EnvType":"string","EnvValue":"/var/lib/docker","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"ENABLE_BUILD_CONTEXT","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"ENABLE_WORKFLOW_EXECUTION_STAGE","EnvType":"bool","EnvValue":"true","EnvDescription":"if enabled then we will display build stages separately for CI/Job/Pre-Post CD","Example":"true","Deprecated":"false"},{"Env":"EXTERNAL_BLOB_STORAGE_CM_NAME","EnvType":"string","EnvValue":"blob-storage-cm","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"EXTERNAL_BLOB_STORAGE_SECRET_NAME","EnvType":"string","EnvValue":"blob-storage-secret","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"EXTERNAL_CD_NODE_LABEL_SELECTOR","EnvType":"","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"EXTERNAL_CD_NODE_TAINTS_KEY","EnvType":"string","EnvValue":"dedicated","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"EXTERNAL_CD_NODE_TAINTS_VALUE","EnvType":"string","EnvValue":"ci","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"EXTERNAL_CI_API_SECRET","EnvType":"string","EnvValue":"devtroncd-secret","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"EXTERNAL_CI_PAYLOAD","EnvType":"string","EnvValue":"{\"ciProjectDetails\":[{\"gitRepository\":\"https://github.com/vikram1601/getting-started-nodejs.git\",\"checkoutPath\":\"./abc\",\"commitHash\":\"239077135f8cdeeccb7857e2851348f558cb53d3\",\"commitTime\":\"2022-10-30T20:00:00\",\"branch\":\"master\",\"message\":\"Update README.md\",\"author\":\"User Name \"}],\"dockerImage\":\"445808685819.dkr.ecr.us-east-2.amazonaws.com/orch:23907713-2\"}","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"EXTERNAL_CI_WEB_HOOK_URL","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"IGNORE_CM_CS_IN_CI_JOB","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"IMAGE_RETRY_COUNT","EnvType":"int","EnvValue":"0","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"IMAGE_RETRY_INTERVAL","EnvType":"int","EnvValue":"5","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"IMAGE_SCANNER_ENDPOINT","EnvType":"string","EnvValue":"http://image-scanner-new-demo-devtroncd-service.devtroncd:80","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"IMAGE_SCAN_MAX_RETRIES","EnvType":"int","EnvValue":"3","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"IMAGE_SCAN_RETRY_DELAY","EnvType":"int","EnvValue":"5","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"IN_APP_LOGGING_ENABLED","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"MAX_CD_WORKFLOW_RUNNER_RETRIES","EnvType":"int","EnvValue":"0","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"MAX_CI_WORKFLOW_RETRIES","EnvType":"int","EnvValue":"0","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"MODE","EnvType":"string","EnvValue":"DEV","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"NATS_SERVER_HOST","EnvType":"string","EnvValue":"localhost:4222","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"ORCH_HOST","EnvType":"string","EnvValue":"http://devtroncd-orchestrator-service-prod.devtroncd/webhook/msg/nats","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"ORCH_TOKEN","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"PRE_CI_CACHE_PATH","EnvType":"string","EnvValue":"/devtroncd-cache","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"SHOW_DOCKER_BUILD_ARGS","EnvType":"bool","EnvValue":"true","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"SKIP_CI_JOB_BUILD_CACHE_PUSH_PULL","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"SKIP_CREATING_ECR_REPO","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"TERMINATION_GRACE_PERIOD_SECS","EnvType":"int","EnvValue":"180","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"USE_ARTIFACT_LISTING_QUERY_V2","EnvType":"bool","EnvValue":"true","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"USE_BLOB_STORAGE_CONFIG_IN_CD_WORKFLOW","EnvType":"bool","EnvValue":"true","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"USE_BLOB_STORAGE_CONFIG_IN_CI_WORKFLOW","EnvType":"bool","EnvValue":"true","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"USE_BUILDX","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"USE_DOCKER_API_TO_GET_DIGEST","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"USE_EXTERNAL_NODE","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"USE_IMAGE_TAG_FROM_GIT_PROVIDER_FOR_TAG_BASED_BUILD","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"WF_CONTROLLER_INSTANCE_ID","EnvType":"string","EnvValue":"devtron-runner","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"WORKFLOW_CACHE_CONFIG","EnvType":"string","EnvValue":"{}","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"WORKFLOW_SERVICE_ACCOUNT","EnvType":"string","EnvValue":"ci-runner","EnvDescription":"","Example":"","Deprecated":"false"}]},{"Category":"DEVTRON","Fields":[{"Env":"-","EnvType":"","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"ADDITIONAL_NODE_GROUP_LABELS","EnvType":"","EnvValue":"","EnvDescription":"Add comma separated list of additional node group labels to default labels","Example":"karpenter.sh/nodepool,cloud.google.com/gke-nodepool","Deprecated":"false"},{"Env":"APP_SYNC_IMAGE","EnvType":"string","EnvValue":"quay.io/devtron/chart-sync:1227622d-132-3775","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"APP_SYNC_JOB_RESOURCES_OBJ","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"APP_SYNC_SERVICE_ACCOUNT","EnvType":"string","EnvValue":"chart-sync","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"APP_SYNC_SHUTDOWN_WAIT_DURATION","EnvType":"int","EnvValue":"120","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"ARGO_AUTO_SYNC_ENABLED","EnvType":"bool","EnvValue":"true","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"ARGO_GIT_COMMIT_RETRY_COUNT_ON_CONFLICT","EnvType":"int","EnvValue":"3","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"ARGO_GIT_COMMIT_RETRY_DELAY_ON_CONFLICT","EnvType":"int","EnvValue":"1","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"ARGO_REPO_REGISTER_RETRY_COUNT","EnvType":"int","EnvValue":"3","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"ARGO_REPO_REGISTER_RETRY_DELAY","EnvType":"int","EnvValue":"10","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"ASYNC_BUILDX_CACHE_EXPORT","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"BATCH_SIZE","EnvType":"int","EnvValue":"5","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"BLOB_STORAGE_ENABLED","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"BUILDX_CACHE_MODE_MIN","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CD_HOST","EnvType":"string","EnvValue":"localhost","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CD_NAMESPACE","EnvType":"string","EnvValue":"devtroncd","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CD_PORT","EnvType":"string","EnvValue":"8000","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CExpirationTime","EnvType":"int","EnvValue":"600","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CI_TRIGGER_CRON_TIME","EnvType":"int","EnvValue":"2","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CI_WORKFLOW_STATUS_UPDATE_CRON","EnvType":"string","EnvValue":"*/5 * * * *","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CLI_CMD_TIMEOUT_GLOBAL_SECONDS","EnvType":"int","EnvValue":"0","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CLUSTER_STATUS_CRON_TIME","EnvType":"int","EnvValue":"15","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CONSUMER_CONFIG_JSON","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEFAULT_LOG_TIME_LIMIT","EnvType":"int64","EnvValue":"1","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEFAULT_TIMEOUT","EnvType":"float64","EnvValue":"3600","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEVTRON_BOM_URL","EnvType":"string","EnvValue":"https://raw.githubusercontent.com/devtron-labs/devtron/%s/charts/devtron/devtron-bom.yaml","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEVTRON_DEFAULT_NAMESPACE","EnvType":"string","EnvValue":"devtroncd","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEVTRON_DEX_SECRET_NAMESPACE","EnvType":"string","EnvValue":"devtroncd","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEVTRON_HELM_RELEASE_CHART_NAME","EnvType":"string","EnvValue":"devtron-operator","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEVTRON_HELM_RELEASE_NAME","EnvType":"string","EnvValue":"devtron","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEVTRON_HELM_RELEASE_NAMESPACE","EnvType":"string","EnvValue":"devtroncd","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEVTRON_HELM_REPO_NAME","EnvType":"string","EnvValue":"devtron","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEVTRON_HELM_REPO_URL","EnvType":"string","EnvValue":"https://helm.devtron.ai","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEVTRON_INSTALLATION_TYPE","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEVTRON_MODULES_IDENTIFIER_IN_HELM_VALUES","EnvType":"string","EnvValue":"installer.modules","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEVTRON_SECRET_NAME","EnvType":"string","EnvValue":"devtron-secret","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEVTRON_VERSION_IDENTIFIER_IN_HELM_VALUES","EnvType":"string","EnvValue":"installer.release","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEX_CID","EnvType":"string","EnvValue":"example-app","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEX_CLIENT_ID","EnvType":"string","EnvValue":"argo-cd","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEX_CSTOREKEY","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEX_JWTKEY","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEX_RURL","EnvType":"string","EnvValue":"http://127.0.0.1:8080/callback","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEX_SECRET","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEX_URL","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"ECR_REPO_NAME_PREFIX","EnvType":"string","EnvValue":"test/","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"ENABLE_ASYNC_ARGO_CD_INSTALL_DEVTRON_CHART","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"ENABLE_ASYNC_INSTALL_DEVTRON_CHART","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"EPHEMERAL_SERVER_VERSION_REGEX","EnvType":"string","EnvValue":"v[1-9]\\.\\b(2[3-9]\\|[3-9][0-9])\\b.*","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"EVENT_URL","EnvType":"string","EnvValue":"http://localhost:3000/notify","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"EXECUTE_WIRE_NIL_CHECKER","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"EXPOSE_CI_METRICS","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"FEATURE_RESTART_WORKLOAD_BATCH_SIZE","EnvType":"int","EnvValue":"1","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"FEATURE_RESTART_WORKLOAD_WORKER_POOL_SIZE","EnvType":"int","EnvValue":"5","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"FORCE_SECURITY_SCANNING","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"GITOPS_REPO_PREFIX","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"GO_RUNTIME_ENV","EnvType":"string","EnvValue":"production","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"GRAFANA_HOST","EnvType":"string","EnvValue":"localhost","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"GRAFANA_NAMESPACE","EnvType":"string","EnvValue":"devtroncd","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"GRAFANA_ORG_ID","EnvType":"int","EnvValue":"2","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"GRAFANA_PASSWORD","EnvType":"string","EnvValue":"prom-operator","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"GRAFANA_PORT","EnvType":"string","EnvValue":"8090","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"GRAFANA_URL","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"GRAFANA_USERNAME","EnvType":"string","EnvValue":"admin","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"HIDE_IMAGE_TAGGING_HARD_DELETE","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"IGNORE_AUTOCOMPLETE_AUTH_CHECK","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"INSTALLED_MODULES","EnvType":"","EnvValue":"","EnvDescription":"List of installed modules given in helm values/yaml are written in cm and used by devtron to know which modules are given","Example":"security.trivy,security.clair","Deprecated":"false"},{"Env":"INSTALLER_CRD_NAMESPACE","EnvType":"string","EnvValue":"devtroncd","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"INSTALLER_CRD_OBJECT_GROUP_NAME","EnvType":"string","EnvValue":"installer.devtron.ai","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"INSTALLER_CRD_OBJECT_RESOURCE","EnvType":"string","EnvValue":"installers","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"INSTALLER_CRD_OBJECT_VERSION","EnvType":"string","EnvValue":"v1alpha1","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"IS_AIR_GAP_ENVIRONMENT","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"JwtExpirationTime","EnvType":"int","EnvValue":"120","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"K8s_CLIENT_MAX_IDLE_CONNS_PER_HOST","EnvType":"int","EnvValue":"25","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"K8s_TCP_IDLE_CONN_TIMEOUT","EnvType":"int","EnvValue":"300","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"K8s_TCP_KEEPALIVE","EnvType":"int","EnvValue":"30","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"K8s_TCP_TIMEOUT","EnvType":"int","EnvValue":"30","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"K8s_TLS_HANDSHAKE_TIMEOUT","EnvType":"int","EnvValue":"10","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"KUBELINK_GRPC_MAX_RECEIVE_MSG_SIZE","EnvType":"int","EnvValue":"20","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"KUBELINK_GRPC_MAX_SEND_MSG_SIZE","EnvType":"int","EnvValue":"4","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"LENS_TIMEOUT","EnvType":"int","EnvValue":"0","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"LENS_URL","EnvType":"string","EnvValue":"http://lens-milandevtron-service:80","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"LIMIT_CI_CPU","EnvType":"string","EnvValue":"0.5","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"LIMIT_CI_MEM","EnvType":"string","EnvValue":"3G","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"LOGGER_DEV_MODE","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"LOG_LEVEL","EnvType":"int","EnvValue":"-1","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"MAX_SESSION_PER_USER","EnvType":"int","EnvValue":"5","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"MODULE_METADATA_API_URL","EnvType":"string","EnvValue":"https://api.devtron.ai/module?name=%s","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"MODULE_STATUS_HANDLING_CRON_DURATION_MIN","EnvType":"int","EnvValue":"3","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"NATS_MSG_ACK_WAIT_IN_SECS","EnvType":"int","EnvValue":"120","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"NATS_MSG_BUFFER_SIZE","EnvType":"int","EnvValue":"-1","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"NATS_MSG_MAX_AGE","EnvType":"int","EnvValue":"86400","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"NATS_MSG_PROCESSING_BATCH_SIZE","EnvType":"int","EnvValue":"1","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"NATS_MSG_REPLICAS","EnvType":"int","EnvValue":"0","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"NOTIFICATION_MEDIUM","EnvType":"NotificationMedium","EnvValue":"rest","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"OTEL_COLLECTOR_URL","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"PARALLELISM_LIMIT_FOR_TAG_PROCESSING","EnvType":"int","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"PG_EXPORT_PROM_METRICS","EnvType":"bool","EnvValue":"true","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"PG_LOG_ALL_FAILURE_QUERIES","EnvType":"bool","EnvValue":"true","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"PG_LOG_ALL_QUERY","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"PG_LOG_SLOW_QUERY","EnvType":"bool","EnvValue":"true","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"PG_QUERY_DUR_THRESHOLD","EnvType":"int64","EnvValue":"5000","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"PLUGIN_NAME","EnvType":"string","EnvValue":"Pull images from container repository","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"PROPAGATE_EXTRA_LABELS","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"PROXY_SERVICE_CONFIG","EnvType":"string","EnvValue":"{}","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"REQ_CI_CPU","EnvType":"string","EnvValue":"0.5","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"REQ_CI_MEM","EnvType":"string","EnvValue":"3G","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"RESTRICT_TERMINAL_ACCESS_FOR_NON_SUPER_USER","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"RUNTIME_CONFIG_LOCAL_DEV","EnvType":"LocalDevMode","EnvValue":"true","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"SCOPED_VARIABLE_ENABLED","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"SCOPED_VARIABLE_FORMAT","EnvType":"string","EnvValue":"@{{%s}}","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"SCOPED_VARIABLE_HANDLE_PRIMITIVES","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"SCOPED_VARIABLE_NAME_REGEX","EnvType":"string","EnvValue":"^[a-zA-Z][a-zA-Z0-9_-]{0,62}[a-zA-Z0-9]$","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"SOCKET_DISCONNECT_DELAY_SECONDS","EnvType":"int","EnvValue":"5","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"SOCKET_HEARTBEAT_SECONDS","EnvType":"int","EnvValue":"25","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"STREAM_CONFIG_JSON","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"SYSTEM_VAR_PREFIX","EnvType":"string","EnvValue":"DEVTRON_","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"TERMINAL_POD_DEFAULT_NAMESPACE","EnvType":"string","EnvValue":"default","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"TERMINAL_POD_INACTIVE_DURATION_IN_MINS","EnvType":"int","EnvValue":"10","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"TERMINAL_POD_STATUS_SYNC_In_SECS","EnvType":"int","EnvValue":"600","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"TEST_APP","EnvType":"string","EnvValue":"orchestrator","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"TEST_PG_ADDR","EnvType":"string","EnvValue":"127.0.0.1","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"TEST_PG_DATABASE","EnvType":"string","EnvValue":"orchestrator","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"TEST_PG_LOG_QUERY","EnvType":"bool","EnvValue":"true","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"TEST_PG_PASSWORD","EnvType":"string","EnvValue":"postgrespw","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"TEST_PG_PORT","EnvType":"string","EnvValue":"55000","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"TEST_PG_USER","EnvType":"string","EnvValue":"postgres","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"TIMEOUT_FOR_FAILED_CI_BUILD","EnvType":"string","EnvValue":"15","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"TIMEOUT_IN_SECONDS","EnvType":"int","EnvValue":"5","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"USER_SESSION_DURATION_SECONDS","EnvType":"int","EnvValue":"86400","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"USE_ARTIFACT_LISTING_API_V2","EnvType":"bool","EnvValue":"true","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"USE_CUSTOM_HTTP_TRANSPORT","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"USE_GIT_CLI","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"USE_RBAC_CREATION_V2","EnvType":"bool","EnvValue":"true","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"VARIABLE_CACHE_ENABLED","EnvType":"bool","EnvValue":"true","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"VARIABLE_EXPRESSION_REGEX","EnvType":"string","EnvValue":"@{{([^}]+)}}","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"WEBHOOK_TOKEN","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"}]},{"Category":"GITOPS","Fields":[{"Env":"ACD_CM","EnvType":"string","EnvValue":"argocd-cm","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"ACD_NAMESPACE","EnvType":"string","EnvValue":"devtroncd","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"ACD_PASSWORD","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"ACD_USERNAME","EnvType":"string","EnvValue":"admin","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"GITOPS_SECRET_NAME","EnvType":"string","EnvValue":"devtron-gitops-secret","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"RESOURCE_LIST_FOR_REPLICAS","EnvType":"string","EnvValue":"Deployment,Rollout,StatefulSet,ReplicaSet","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"RESOURCE_LIST_FOR_REPLICAS_BATCH_SIZE","EnvType":"int","EnvValue":"5","EnvDescription":"","Example":"","Deprecated":"false"}]},{"Category":"INFRA_SETUP","Fields":[{"Env":"DASHBOARD_HOST","EnvType":"string","EnvValue":"localhost","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DASHBOARD_NAMESPACE","EnvType":"string","EnvValue":"devtroncd","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DASHBOARD_PORT","EnvType":"string","EnvValue":"3000","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEX_HOST","EnvType":"string","EnvValue":"http://localhost","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEX_PORT","EnvType":"string","EnvValue":"5556","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"GIT_SENSOR_PROTOCOL","EnvType":"string","EnvValue":"REST","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"GIT_SENSOR_TIMEOUT","EnvType":"int","EnvValue":"0","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"GIT_SENSOR_URL","EnvType":"string","EnvValue":"127.0.0.1:7070","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"HELM_CLIENT_URL","EnvType":"string","EnvValue":"127.0.0.1:50051","EnvDescription":"","Example":"","Deprecated":"false"}]},{"Category":"POSTGRES","Fields":[{"Env":"APP","EnvType":"string","EnvValue":"orchestrator","EnvDescription":"Application name","Example":"","Deprecated":"false"},{"Env":"CASBIN_DATABASE","EnvType":"string","EnvValue":"casbin","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"PG_ADDR","EnvType":"string","EnvValue":"127.0.0.1","EnvDescription":"address of postgres service","Example":"postgresql-postgresql.devtroncd","Deprecated":"false"},{"Env":"PG_DATABASE","EnvType":"string","EnvValue":"orchestrator","EnvDescription":"postgres database to be made connection with","Example":"orchestrator, casbin, git_sensor, lens","Deprecated":"false"},{"Env":"PG_PASSWORD","EnvType":"string","EnvValue":"{password}","EnvDescription":"password for postgres, associated with PG_USER","Example":"confidential ;)","Deprecated":"false"},{"Env":"PG_PORT","EnvType":"string","EnvValue":"5432","EnvDescription":"port of postgresql service","Example":"5432","Deprecated":"false"},{"Env":"PG_READ_TIMEOUT","EnvType":"int64","EnvValue":"30","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"PG_USER","EnvType":"string","EnvValue":"postgres","EnvDescription":"user for postgres","Example":"postgres","Deprecated":"false"},{"Env":"PG_WRITE_TIMEOUT","EnvType":"int64","EnvValue":"30","EnvDescription":"","Example":"","Deprecated":"false"}]},{"Category":"RBAC","Fields":[{"Env":"ENFORCER_CACHE","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"ENFORCER_CACHE_EXPIRATION_IN_SEC","EnvType":"int","EnvValue":"86400","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"ENFORCER_MAX_BATCH_SIZE","EnvType":"int","EnvValue":"1","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"USE_CASBIN_V2","EnvType":"bool","EnvValue":"true","EnvDescription":"","Example":"","Deprecated":"false"}]}] \ No newline at end of file +[{"Category":"CD","Fields":[{"Env":"ARGO_APP_MANUAL_SYNC_TIME","EnvType":"int","EnvValue":"3","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CD_HELM_PIPELINE_STATUS_CRON_TIME","EnvType":"string","EnvValue":"*/2 * * * *","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CD_PIPELINE_STATUS_CRON_TIME","EnvType":"string","EnvValue":"*/2 * * * *","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CD_PIPELINE_STATUS_TIMEOUT_DURATION","EnvType":"string","EnvValue":"20","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEPLOY_STATUS_CRON_GET_PIPELINE_DEPLOYED_WITHIN_HOURS","EnvType":"int","EnvValue":"12","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEVTRON_CHART_ARGO_CD_INSTALL_REQUEST_TIMEOUT","EnvType":"int","EnvValue":"1","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEVTRON_CHART_INSTALL_REQUEST_TIMEOUT","EnvType":"int","EnvValue":"6","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"EXPOSE_CD_METRICS","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"FEATURE_MIGRATE_ARGOCD_APPLICATION_ENABLE","EnvType":"bool","EnvValue":"false","EnvDescription":"enable migration of external argocd application to devtron pipeline","Example":"","Deprecated":"false"},{"Env":"HELM_PIPELINE_STATUS_CHECK_ELIGIBLE_TIME","EnvType":"string","EnvValue":"120","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"IS_INTERNAL_USE","EnvType":"bool","EnvValue":"true","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"MIGRATE_DEPLOYMENT_CONFIG_DATA","EnvType":"bool","EnvValue":"false","EnvDescription":"migrate deployment config data from charts table to deployment_config table","Example":"","Deprecated":"false"},{"Env":"PIPELINE_DEGRADED_TIME","EnvType":"string","EnvValue":"10","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"REVISION_HISTORY_LIMIT_DEVTRON_APP","EnvType":"int","EnvValue":"1","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"REVISION_HISTORY_LIMIT_EXTERNAL_HELM_APP","EnvType":"int","EnvValue":"0","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"REVISION_HISTORY_LIMIT_HELM_APP","EnvType":"int","EnvValue":"1","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"REVISION_HISTORY_LIMIT_LINKED_HELM_APP","EnvType":"int","EnvValue":"15","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"RUN_HELM_INSTALL_IN_ASYNC_MODE_HELM_APPS","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"SHOULD_CHECK_NAMESPACE_ON_CLONE","EnvType":"bool","EnvValue":"false","EnvDescription":"should we check if namespace exists or not while cloning app","Example":"","Deprecated":"false"},{"Env":"USE_DEPLOYMENT_CONFIG_DATA","EnvType":"bool","EnvValue":"false","EnvDescription":"use deployment config data from deployment_config table","Example":"","Deprecated":"true"}]},{"Category":"CI_RUNNER","Fields":[{"Env":"AZURE_ACCOUNT_KEY","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"AZURE_ACCOUNT_NAME","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"AZURE_BLOB_CONTAINER_CI_CACHE","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"AZURE_BLOB_CONTAINER_CI_LOG","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"AZURE_GATEWAY_CONNECTION_INSECURE","EnvType":"bool","EnvValue":"true","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"AZURE_GATEWAY_URL","EnvType":"string","EnvValue":"http://devtron-minio.devtroncd:9000","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"BASE_LOG_LOCATION_PATH","EnvType":"string","EnvValue":"/home/devtron/","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"BLOB_STORAGE_GCP_CREDENTIALS_JSON","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"BLOB_STORAGE_PROVIDER","EnvType":"","EnvValue":"S3","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"BLOB_STORAGE_S3_ACCESS_KEY","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"BLOB_STORAGE_S3_BUCKET_VERSIONED","EnvType":"bool","EnvValue":"true","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"BLOB_STORAGE_S3_ENDPOINT","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"BLOB_STORAGE_S3_ENDPOINT_INSECURE","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"BLOB_STORAGE_S3_SECRET_KEY","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"BUILDX_CACHE_PATH","EnvType":"string","EnvValue":"/var/lib/devtron/buildx","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"BUILDX_K8S_DRIVER_OPTIONS","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"BUILDX_PROVENANCE_MODE","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"BUILD_LOG_TTL_VALUE_IN_SECS","EnvType":"int","EnvValue":"3600","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CACHE_LIMIT","EnvType":"int64","EnvValue":"5000000000","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CD_DEFAULT_ADDRESS_POOL_BASE_CIDR","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CD_DEFAULT_ADDRESS_POOL_SIZE","EnvType":"int","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CD_LIMIT_CI_CPU","EnvType":"string","EnvValue":"0.5","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CD_LIMIT_CI_MEM","EnvType":"string","EnvValue":"3G","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CD_NODE_LABEL_SELECTOR","EnvType":"","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CD_NODE_TAINTS_KEY","EnvType":"string","EnvValue":"dedicated","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CD_NODE_TAINTS_VALUE","EnvType":"string","EnvValue":"ci","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CD_REQ_CI_CPU","EnvType":"string","EnvValue":"0.5","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CD_REQ_CI_MEM","EnvType":"string","EnvValue":"3G","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CD_WORKFLOW_EXECUTOR_TYPE","EnvType":"","EnvValue":"AWF","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CD_WORKFLOW_SERVICE_ACCOUNT","EnvType":"string","EnvValue":"cd-runner","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CI_DEFAULT_ADDRESS_POOL_BASE_CIDR","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CI_DEFAULT_ADDRESS_POOL_SIZE","EnvType":"int","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CI_IGNORE_DOCKER_CACHE","EnvType":"bool","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CI_LOGS_KEY_PREFIX","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CI_NODE_LABEL_SELECTOR","EnvType":"","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CI_NODE_TAINTS_KEY","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CI_NODE_TAINTS_VALUE","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CI_RUNNER_DOCKER_MTU_VALUE","EnvType":"int","EnvValue":"-1","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CI_SUCCESS_AUTO_TRIGGER_BATCH_SIZE","EnvType":"int","EnvValue":"1","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CI_VOLUME_MOUNTS_JSON","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CI_WORKFLOW_EXECUTOR_TYPE","EnvType":"","EnvValue":"AWF","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEFAULT_ARTIFACT_KEY_LOCATION","EnvType":"string","EnvValue":"arsenal-v1/ci-artifacts","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEFAULT_BUILD_LOGS_BUCKET","EnvType":"string","EnvValue":"devtron-pro-ci-logs","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEFAULT_BUILD_LOGS_KEY_PREFIX","EnvType":"string","EnvValue":"arsenal-v1","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEFAULT_CACHE_BUCKET","EnvType":"string","EnvValue":"ci-caching","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEFAULT_CACHE_BUCKET_REGION","EnvType":"string","EnvValue":"us-east-2","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEFAULT_CD_ARTIFACT_KEY_LOCATION","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEFAULT_CD_LOGS_BUCKET_REGION","EnvType":"string","EnvValue":"us-east-2","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEFAULT_CD_NAMESPACE","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEFAULT_CD_TIMEOUT","EnvType":"int64","EnvValue":"3600","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEFAULT_CI_IMAGE","EnvType":"string","EnvValue":"686244538589.dkr.ecr.us-east-2.amazonaws.com/cirunner:47","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEFAULT_NAMESPACE","EnvType":"string","EnvValue":"devtron-ci","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEFAULT_TARGET_PLATFORM","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DOCKER_BUILD_CACHE_PATH","EnvType":"string","EnvValue":"/var/lib/docker","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"ENABLE_BUILD_CONTEXT","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"ENABLE_WORKFLOW_EXECUTION_STAGE","EnvType":"bool","EnvValue":"true","EnvDescription":"if enabled then we will display build stages separately for CI/Job/Pre-Post CD","Example":"true","Deprecated":"false"},{"Env":"EXTERNAL_BLOB_STORAGE_CM_NAME","EnvType":"string","EnvValue":"blob-storage-cm","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"EXTERNAL_BLOB_STORAGE_SECRET_NAME","EnvType":"string","EnvValue":"blob-storage-secret","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"EXTERNAL_CD_NODE_LABEL_SELECTOR","EnvType":"","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"EXTERNAL_CD_NODE_TAINTS_KEY","EnvType":"string","EnvValue":"dedicated","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"EXTERNAL_CD_NODE_TAINTS_VALUE","EnvType":"string","EnvValue":"ci","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"EXTERNAL_CI_API_SECRET","EnvType":"string","EnvValue":"devtroncd-secret","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"EXTERNAL_CI_PAYLOAD","EnvType":"string","EnvValue":"{\"ciProjectDetails\":[{\"gitRepository\":\"https://github.com/vikram1601/getting-started-nodejs.git\",\"checkoutPath\":\"./abc\",\"commitHash\":\"239077135f8cdeeccb7857e2851348f558cb53d3\",\"commitTime\":\"2022-10-30T20:00:00\",\"branch\":\"master\",\"message\":\"Update README.md\",\"author\":\"User Name \"}],\"dockerImage\":\"445808685819.dkr.ecr.us-east-2.amazonaws.com/orch:23907713-2\"}","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"EXTERNAL_CI_WEB_HOOK_URL","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"IGNORE_CM_CS_IN_CI_JOB","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"IMAGE_RETRY_COUNT","EnvType":"int","EnvValue":"0","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"IMAGE_RETRY_INTERVAL","EnvType":"int","EnvValue":"5","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"IMAGE_SCANNER_ENDPOINT","EnvType":"string","EnvValue":"http://image-scanner-new-demo-devtroncd-service.devtroncd:80","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"IMAGE_SCAN_MAX_RETRIES","EnvType":"int","EnvValue":"3","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"IMAGE_SCAN_RETRY_DELAY","EnvType":"int","EnvValue":"5","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"IN_APP_LOGGING_ENABLED","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"MAX_CD_WORKFLOW_RUNNER_RETRIES","EnvType":"int","EnvValue":"0","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"MAX_CI_WORKFLOW_RETRIES","EnvType":"int","EnvValue":"0","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"MODE","EnvType":"string","EnvValue":"DEV","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"NATS_SERVER_HOST","EnvType":"string","EnvValue":"localhost:4222","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"ORCH_HOST","EnvType":"string","EnvValue":"http://devtroncd-orchestrator-service-prod.devtroncd/webhook/msg/nats","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"ORCH_TOKEN","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"PRE_CI_CACHE_PATH","EnvType":"string","EnvValue":"/devtroncd-cache","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"SHOW_DOCKER_BUILD_ARGS","EnvType":"bool","EnvValue":"true","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"SKIP_CI_JOB_BUILD_CACHE_PUSH_PULL","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"SKIP_CREATING_ECR_REPO","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"TERMINATION_GRACE_PERIOD_SECS","EnvType":"int","EnvValue":"180","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"USE_ARTIFACT_LISTING_QUERY_V2","EnvType":"bool","EnvValue":"true","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"USE_BLOB_STORAGE_CONFIG_IN_CD_WORKFLOW","EnvType":"bool","EnvValue":"true","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"USE_BLOB_STORAGE_CONFIG_IN_CI_WORKFLOW","EnvType":"bool","EnvValue":"true","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"USE_BUILDX","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"USE_DOCKER_API_TO_GET_DIGEST","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"USE_EXTERNAL_NODE","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"USE_IMAGE_TAG_FROM_GIT_PROVIDER_FOR_TAG_BASED_BUILD","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"WF_CONTROLLER_INSTANCE_ID","EnvType":"string","EnvValue":"devtron-runner","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"WORKFLOW_CACHE_CONFIG","EnvType":"string","EnvValue":"{}","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"WORKFLOW_SERVICE_ACCOUNT","EnvType":"string","EnvValue":"ci-runner","EnvDescription":"","Example":"","Deprecated":"false"}]},{"Category":"DEVTRON","Fields":[{"Env":"-","EnvType":"","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"ADDITIONAL_NODE_GROUP_LABELS","EnvType":"","EnvValue":"","EnvDescription":"Add comma separated list of additional node group labels to default labels","Example":"karpenter.sh/nodepool,cloud.google.com/gke-nodepool","Deprecated":"false"},{"Env":"APP_SYNC_IMAGE","EnvType":"string","EnvValue":"quay.io/devtron/chart-sync:1227622d-132-3775","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"APP_SYNC_JOB_RESOURCES_OBJ","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"APP_SYNC_SERVICE_ACCOUNT","EnvType":"string","EnvValue":"chart-sync","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"APP_SYNC_SHUTDOWN_WAIT_DURATION","EnvType":"int","EnvValue":"120","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"ARGO_AUTO_SYNC_ENABLED","EnvType":"bool","EnvValue":"true","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"ARGO_GIT_COMMIT_RETRY_COUNT_ON_CONFLICT","EnvType":"int","EnvValue":"3","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"ARGO_GIT_COMMIT_RETRY_DELAY_ON_CONFLICT","EnvType":"int","EnvValue":"1","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"ARGO_REPO_REGISTER_RETRY_COUNT","EnvType":"int","EnvValue":"3","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"ARGO_REPO_REGISTER_RETRY_DELAY","EnvType":"int","EnvValue":"10","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"ASYNC_BUILDX_CACHE_EXPORT","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"BATCH_SIZE","EnvType":"int","EnvValue":"5","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"BLOB_STORAGE_ENABLED","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"BUILDX_CACHE_MODE_MIN","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CD_HOST","EnvType":"string","EnvValue":"localhost","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CD_NAMESPACE","EnvType":"string","EnvValue":"devtroncd","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CD_PORT","EnvType":"string","EnvValue":"8000","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CExpirationTime","EnvType":"int","EnvValue":"600","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CI_TRIGGER_CRON_TIME","EnvType":"int","EnvValue":"2","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CI_WORKFLOW_STATUS_UPDATE_CRON","EnvType":"string","EnvValue":"*/5 * * * *","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CLI_CMD_TIMEOUT_GLOBAL_SECONDS","EnvType":"int","EnvValue":"0","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CLUSTER_STATUS_CRON_TIME","EnvType":"int","EnvValue":"15","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"CONSUMER_CONFIG_JSON","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEFAULT_LOG_TIME_LIMIT","EnvType":"int64","EnvValue":"1","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEFAULT_TIMEOUT","EnvType":"float64","EnvValue":"3600","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEVTRON_BOM_URL","EnvType":"string","EnvValue":"https://raw.githubusercontent.com/devtron-labs/devtron/%s/charts/devtron/devtron-bom.yaml","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEVTRON_DEFAULT_NAMESPACE","EnvType":"string","EnvValue":"devtroncd","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEVTRON_DEX_SECRET_NAMESPACE","EnvType":"string","EnvValue":"devtroncd","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEVTRON_HELM_RELEASE_CHART_NAME","EnvType":"string","EnvValue":"devtron-operator","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEVTRON_HELM_RELEASE_NAME","EnvType":"string","EnvValue":"devtron","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEVTRON_HELM_RELEASE_NAMESPACE","EnvType":"string","EnvValue":"devtroncd","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEVTRON_HELM_REPO_NAME","EnvType":"string","EnvValue":"devtron","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEVTRON_HELM_REPO_URL","EnvType":"string","EnvValue":"https://helm.devtron.ai","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEVTRON_INSTALLATION_TYPE","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEVTRON_MODULES_IDENTIFIER_IN_HELM_VALUES","EnvType":"string","EnvValue":"installer.modules","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEVTRON_SECRET_NAME","EnvType":"string","EnvValue":"devtron-secret","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEVTRON_VERSION_IDENTIFIER_IN_HELM_VALUES","EnvType":"string","EnvValue":"installer.release","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEX_CID","EnvType":"string","EnvValue":"example-app","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEX_CLIENT_ID","EnvType":"string","EnvValue":"argo-cd","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEX_CSTOREKEY","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEX_JWTKEY","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEX_RURL","EnvType":"string","EnvValue":"http://127.0.0.1:8080/callback","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEX_SCOPES","EnvType":"","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEX_SECRET","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEX_URL","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"ECR_REPO_NAME_PREFIX","EnvType":"string","EnvValue":"test/","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"ENABLE_ASYNC_ARGO_CD_INSTALL_DEVTRON_CHART","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"ENABLE_ASYNC_INSTALL_DEVTRON_CHART","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"EPHEMERAL_SERVER_VERSION_REGEX","EnvType":"string","EnvValue":"v[1-9]\\.\\b(2[3-9]\\|[3-9][0-9])\\b.*","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"EVENT_URL","EnvType":"string","EnvValue":"http://localhost:3000/notify","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"EXECUTE_WIRE_NIL_CHECKER","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"EXPOSE_CI_METRICS","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"FEATURE_RESTART_WORKLOAD_BATCH_SIZE","EnvType":"int","EnvValue":"1","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"FEATURE_RESTART_WORKLOAD_WORKER_POOL_SIZE","EnvType":"int","EnvValue":"5","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"FORCE_SECURITY_SCANNING","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"GITOPS_REPO_PREFIX","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"GO_RUNTIME_ENV","EnvType":"string","EnvValue":"production","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"GRAFANA_HOST","EnvType":"string","EnvValue":"localhost","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"GRAFANA_NAMESPACE","EnvType":"string","EnvValue":"devtroncd","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"GRAFANA_ORG_ID","EnvType":"int","EnvValue":"2","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"GRAFANA_PASSWORD","EnvType":"string","EnvValue":"prom-operator","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"GRAFANA_PORT","EnvType":"string","EnvValue":"8090","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"GRAFANA_URL","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"GRAFANA_USERNAME","EnvType":"string","EnvValue":"admin","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"HIDE_IMAGE_TAGGING_HARD_DELETE","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"IGNORE_AUTOCOMPLETE_AUTH_CHECK","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"INSTALLED_MODULES","EnvType":"","EnvValue":"","EnvDescription":"List of installed modules given in helm values/yaml are written in cm and used by devtron to know which modules are given","Example":"security.trivy,security.clair","Deprecated":"false"},{"Env":"INSTALLER_CRD_NAMESPACE","EnvType":"string","EnvValue":"devtroncd","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"INSTALLER_CRD_OBJECT_GROUP_NAME","EnvType":"string","EnvValue":"installer.devtron.ai","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"INSTALLER_CRD_OBJECT_RESOURCE","EnvType":"string","EnvValue":"installers","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"INSTALLER_CRD_OBJECT_VERSION","EnvType":"string","EnvValue":"v1alpha1","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"IS_AIR_GAP_ENVIRONMENT","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"JwtExpirationTime","EnvType":"int","EnvValue":"120","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"K8s_CLIENT_MAX_IDLE_CONNS_PER_HOST","EnvType":"int","EnvValue":"25","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"K8s_TCP_IDLE_CONN_TIMEOUT","EnvType":"int","EnvValue":"300","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"K8s_TCP_KEEPALIVE","EnvType":"int","EnvValue":"30","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"K8s_TCP_TIMEOUT","EnvType":"int","EnvValue":"30","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"K8s_TLS_HANDSHAKE_TIMEOUT","EnvType":"int","EnvValue":"10","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"KUBELINK_GRPC_MAX_RECEIVE_MSG_SIZE","EnvType":"int","EnvValue":"20","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"KUBELINK_GRPC_MAX_SEND_MSG_SIZE","EnvType":"int","EnvValue":"4","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"LENS_TIMEOUT","EnvType":"int","EnvValue":"0","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"LENS_URL","EnvType":"string","EnvValue":"http://lens-milandevtron-service:80","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"LIMIT_CI_CPU","EnvType":"string","EnvValue":"0.5","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"LIMIT_CI_MEM","EnvType":"string","EnvValue":"3G","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"LOGGER_DEV_MODE","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"LOG_LEVEL","EnvType":"int","EnvValue":"-1","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"MAX_SESSION_PER_USER","EnvType":"int","EnvValue":"5","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"MODULE_METADATA_API_URL","EnvType":"string","EnvValue":"https://api.devtron.ai/module?name=%s","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"MODULE_STATUS_HANDLING_CRON_DURATION_MIN","EnvType":"int","EnvValue":"3","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"NATS_MSG_ACK_WAIT_IN_SECS","EnvType":"int","EnvValue":"120","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"NATS_MSG_BUFFER_SIZE","EnvType":"int","EnvValue":"-1","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"NATS_MSG_MAX_AGE","EnvType":"int","EnvValue":"86400","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"NATS_MSG_PROCESSING_BATCH_SIZE","EnvType":"int","EnvValue":"1","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"NATS_MSG_REPLICAS","EnvType":"int","EnvValue":"0","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"NOTIFICATION_MEDIUM","EnvType":"NotificationMedium","EnvValue":"rest","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"OTEL_COLLECTOR_URL","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"PARALLELISM_LIMIT_FOR_TAG_PROCESSING","EnvType":"int","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"PG_EXPORT_PROM_METRICS","EnvType":"bool","EnvValue":"true","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"PG_LOG_ALL_FAILURE_QUERIES","EnvType":"bool","EnvValue":"true","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"PG_LOG_ALL_QUERY","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"PG_LOG_SLOW_QUERY","EnvType":"bool","EnvValue":"true","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"PG_QUERY_DUR_THRESHOLD","EnvType":"int64","EnvValue":"5000","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"PLUGIN_NAME","EnvType":"string","EnvValue":"Pull images from container repository","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"PROPAGATE_EXTRA_LABELS","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"PROXY_SERVICE_CONFIG","EnvType":"string","EnvValue":"{}","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"REQ_CI_CPU","EnvType":"string","EnvValue":"0.5","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"REQ_CI_MEM","EnvType":"string","EnvValue":"3G","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"RESTRICT_TERMINAL_ACCESS_FOR_NON_SUPER_USER","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"RUNTIME_CONFIG_LOCAL_DEV","EnvType":"LocalDevMode","EnvValue":"true","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"SCOPED_VARIABLE_ENABLED","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"SCOPED_VARIABLE_FORMAT","EnvType":"string","EnvValue":"@{{%s}}","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"SCOPED_VARIABLE_HANDLE_PRIMITIVES","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"SCOPED_VARIABLE_NAME_REGEX","EnvType":"string","EnvValue":"^[a-zA-Z][a-zA-Z0-9_-]{0,62}[a-zA-Z0-9]$","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"SOCKET_DISCONNECT_DELAY_SECONDS","EnvType":"int","EnvValue":"5","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"SOCKET_HEARTBEAT_SECONDS","EnvType":"int","EnvValue":"25","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"STREAM_CONFIG_JSON","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"SYSTEM_VAR_PREFIX","EnvType":"string","EnvValue":"DEVTRON_","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"TERMINAL_POD_DEFAULT_NAMESPACE","EnvType":"string","EnvValue":"default","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"TERMINAL_POD_INACTIVE_DURATION_IN_MINS","EnvType":"int","EnvValue":"10","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"TERMINAL_POD_STATUS_SYNC_In_SECS","EnvType":"int","EnvValue":"600","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"TEST_APP","EnvType":"string","EnvValue":"orchestrator","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"TEST_PG_ADDR","EnvType":"string","EnvValue":"127.0.0.1","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"TEST_PG_DATABASE","EnvType":"string","EnvValue":"orchestrator","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"TEST_PG_LOG_QUERY","EnvType":"bool","EnvValue":"true","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"TEST_PG_PASSWORD","EnvType":"string","EnvValue":"postgrespw","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"TEST_PG_PORT","EnvType":"string","EnvValue":"55000","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"TEST_PG_USER","EnvType":"string","EnvValue":"postgres","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"TIMEOUT_FOR_FAILED_CI_BUILD","EnvType":"string","EnvValue":"15","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"TIMEOUT_IN_SECONDS","EnvType":"int","EnvValue":"5","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"USER_SESSION_DURATION_SECONDS","EnvType":"int","EnvValue":"86400","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"USE_ARTIFACT_LISTING_API_V2","EnvType":"bool","EnvValue":"true","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"USE_CUSTOM_HTTP_TRANSPORT","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"USE_GIT_CLI","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"USE_RBAC_CREATION_V2","EnvType":"bool","EnvValue":"true","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"VARIABLE_CACHE_ENABLED","EnvType":"bool","EnvValue":"true","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"VARIABLE_EXPRESSION_REGEX","EnvType":"string","EnvValue":"@{{([^}]+)}}","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"WEBHOOK_TOKEN","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"}]},{"Category":"GITOPS","Fields":[{"Env":"ACD_CM","EnvType":"string","EnvValue":"argocd-cm","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"ACD_NAMESPACE","EnvType":"string","EnvValue":"devtroncd","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"ACD_PASSWORD","EnvType":"string","EnvValue":"","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"ACD_USERNAME","EnvType":"string","EnvValue":"admin","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"GITOPS_SECRET_NAME","EnvType":"string","EnvValue":"devtron-gitops-secret","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"RESOURCE_LIST_FOR_REPLICAS","EnvType":"string","EnvValue":"Deployment,Rollout,StatefulSet,ReplicaSet","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"RESOURCE_LIST_FOR_REPLICAS_BATCH_SIZE","EnvType":"int","EnvValue":"5","EnvDescription":"","Example":"","Deprecated":"false"}]},{"Category":"INFRA_SETUP","Fields":[{"Env":"DASHBOARD_HOST","EnvType":"string","EnvValue":"localhost","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DASHBOARD_NAMESPACE","EnvType":"string","EnvValue":"devtroncd","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DASHBOARD_PORT","EnvType":"string","EnvValue":"3000","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEX_HOST","EnvType":"string","EnvValue":"http://localhost","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"DEX_PORT","EnvType":"string","EnvValue":"5556","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"GIT_SENSOR_PROTOCOL","EnvType":"string","EnvValue":"REST","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"GIT_SENSOR_TIMEOUT","EnvType":"int","EnvValue":"0","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"GIT_SENSOR_URL","EnvType":"string","EnvValue":"127.0.0.1:7070","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"HELM_CLIENT_URL","EnvType":"string","EnvValue":"127.0.0.1:50051","EnvDescription":"","Example":"","Deprecated":"false"}]},{"Category":"POSTGRES","Fields":[{"Env":"APP","EnvType":"string","EnvValue":"orchestrator","EnvDescription":"Application name","Example":"","Deprecated":"false"},{"Env":"CASBIN_DATABASE","EnvType":"string","EnvValue":"casbin","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"PG_ADDR","EnvType":"string","EnvValue":"127.0.0.1","EnvDescription":"address of postgres service","Example":"postgresql-postgresql.devtroncd","Deprecated":"false"},{"Env":"PG_DATABASE","EnvType":"string","EnvValue":"orchestrator","EnvDescription":"postgres database to be made connection with","Example":"orchestrator, casbin, git_sensor, lens","Deprecated":"false"},{"Env":"PG_PASSWORD","EnvType":"string","EnvValue":"{password}","EnvDescription":"password for postgres, associated with PG_USER","Example":"confidential ;)","Deprecated":"false"},{"Env":"PG_PORT","EnvType":"string","EnvValue":"5432","EnvDescription":"port of postgresql service","Example":"5432","Deprecated":"false"},{"Env":"PG_READ_TIMEOUT","EnvType":"int64","EnvValue":"30","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"PG_USER","EnvType":"string","EnvValue":"postgres","EnvDescription":"user for postgres","Example":"postgres","Deprecated":"false"},{"Env":"PG_WRITE_TIMEOUT","EnvType":"int64","EnvValue":"30","EnvDescription":"","Example":"","Deprecated":"false"}]},{"Category":"RBAC","Fields":[{"Env":"ENFORCER_CACHE","EnvType":"bool","EnvValue":"false","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"ENFORCER_CACHE_EXPIRATION_IN_SEC","EnvType":"int","EnvValue":"86400","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"ENFORCER_MAX_BATCH_SIZE","EnvType":"int","EnvValue":"1","EnvDescription":"","Example":"","Deprecated":"false"},{"Env":"USE_CASBIN_V2","EnvType":"bool","EnvValue":"true","EnvDescription":"","Example":"","Deprecated":"false"}]}] \ No newline at end of file diff --git a/env_gen.md b/env_gen.md index f247bf8a1f..63d998590a 100644 --- a/env_gen.md +++ b/env_gen.md @@ -168,6 +168,7 @@ | DEX_CSTOREKEY | string | | | | false | | DEX_JWTKEY | string | | | | false | | DEX_RURL | string |http://127.0.0.1:8080/callback | | | false | + | DEX_SCOPES | | | | | false | | DEX_SECRET | string | | | | false | | DEX_URL | string | | | | false | | ECR_REPO_NAME_PREFIX | string |test/ | | | false | diff --git a/pkg/eventProcessor/bean/workflowEventBean.go b/pkg/eventProcessor/bean/workflowEventBean.go index ddf532fd72..3f401845c4 100644 --- a/pkg/eventProcessor/bean/workflowEventBean.go +++ b/pkg/eventProcessor/bean/workflowEventBean.go @@ -120,3 +120,9 @@ type CiCdStatus struct { DevtronAdministratorInstance string `json:"devtronAdministratorInstance"` *v1alpha1.WorkflowStatus } + +func NewCiCdStatus() CiCdStatus { + return CiCdStatus{ + WorkflowStatus: &v1alpha1.WorkflowStatus{}, + } +} diff --git a/pkg/eventProcessor/in/WorkflowEventProcessorService.go b/pkg/eventProcessor/in/WorkflowEventProcessorService.go index f921103d84..12dd7155eb 100644 --- a/pkg/eventProcessor/in/WorkflowEventProcessorService.go +++ b/pkg/eventProcessor/in/WorkflowEventProcessorService.go @@ -392,7 +392,7 @@ func (impl *WorkflowEventProcessorImpl) SubscribeHibernateBulkAction() error { func (impl *WorkflowEventProcessorImpl) SubscribeCIWorkflowStatusUpdate() error { callback := func(msg *model.PubSubMsg) { - wfStatus := bean.CiCdStatus{} + wfStatus := bean.NewCiCdStatus() err := json.Unmarshal([]byte(msg.Data), &wfStatus) if err != nil { impl.logger.Errorw("error while unmarshalling wf status update", "err", err, "msg", msg.Data) @@ -432,7 +432,7 @@ func (impl *WorkflowEventProcessorImpl) SubscribeCIWorkflowStatusUpdate() error // add required logging here var loggerFunc pubsub.LoggerFunc = func(msg model.PubSubMsg) (string, []interface{}) { - wfStatus := bean.CiCdStatus{} + wfStatus := bean.NewCiCdStatus() err := json.Unmarshal([]byte(msg.Data), &wfStatus) if err != nil { return "error while unmarshalling wf status update", []interface{}{"err", err, "msg", msg.Data} @@ -453,7 +453,7 @@ func (impl *WorkflowEventProcessorImpl) SubscribeCIWorkflowStatusUpdate() error func (impl *WorkflowEventProcessorImpl) SubscribeCDWorkflowStatusUpdate() error { callback := func(msg *model.PubSubMsg) { - wfStatus := bean.CiCdStatus{} + wfStatus := bean.NewCiCdStatus() err := json.Unmarshal([]byte(msg.Data), &wfStatus) if err != nil { impl.logger.Error("Error while unmarshalling wfStatus json object", "error", err) @@ -530,7 +530,7 @@ func (impl *WorkflowEventProcessorImpl) SubscribeCDWorkflowStatusUpdate() error // add required logging here var loggerFunc pubsub.LoggerFunc = func(msg model.PubSubMsg) (string, []interface{}) { - wfStatus := bean.CiCdStatus{} + wfStatus := bean.NewCiCdStatus() err := json.Unmarshal([]byte(msg.Data), &wfStatus) if err != nil { return "error while unmarshalling wfStatus json object", []interface{}{"error", err} diff --git a/pkg/pipeline/CdHandler.go b/pkg/pipeline/CdHandler.go index 533a39515b..210616b1b7 100644 --- a/pkg/pipeline/CdHandler.go +++ b/pkg/pipeline/CdHandler.go @@ -30,7 +30,7 @@ import ( bean3 "github.com/devtron-labs/devtron/pkg/cluster/bean" repository3 "github.com/devtron-labs/devtron/pkg/cluster/environment/repository" common2 "github.com/devtron-labs/devtron/pkg/deployment/common" - bean6 "github.com/devtron-labs/devtron/pkg/eventProcessor/bean" + eventProcessorBean "github.com/devtron-labs/devtron/pkg/eventProcessor/bean" "github.com/devtron-labs/devtron/pkg/pipeline/constants" util2 "github.com/devtron-labs/devtron/pkg/pipeline/util" "github.com/devtron-labs/devtron/pkg/pipeline/workflowStatus" @@ -71,7 +71,7 @@ const ( ) type CdHandler interface { - UpdateWorkflow(workflowStatus bean6.CiCdStatus) (int, string, bool, error) + UpdateWorkflow(workflowStatus eventProcessorBean.CiCdStatus) (int, string, bool, error) GetCdBuildHistory(appId int, environmentId int, pipelineId int, offset int, size int) ([]pipelineBean.CdWorkflowWithArtifact, error) GetRunningWorkflowLogs(environmentId int, pipelineId int, workflowId int) (*bufio.Reader, func() error, error) FetchCdWorkflowDetails(appId int, environmentId int, pipelineId int, buildId int) (types.WorkflowResponse, error) @@ -267,7 +267,7 @@ func (impl *CdHandlerImpl) handleForceAbortCaseForCdStage(workflowRunner *pipeli return nil } -func (impl *CdHandlerImpl) UpdateWorkflow(workflowStatus bean6.CiCdStatus) (int, string, bool, error) { +func (impl *CdHandlerImpl) UpdateWorkflow(workflowStatus eventProcessorBean.CiCdStatus) (int, string, bool, error) { wfStatusRs := impl.extractWorkflowStatus(workflowStatus) workflowName, status, podStatus, message, podName := wfStatusRs.WorkflowName, wfStatusRs.Status, wfStatusRs.PodStatus, wfStatusRs.Message, wfStatusRs.PodName impl.Logger.Debugw("cd workflow status update event for", "wf ", workflowName, "status", status) @@ -331,7 +331,7 @@ func (impl *CdHandlerImpl) UpdateWorkflow(workflowStatus bean6.CiCdStatus) (int, return savedWorkflow.Id, savedWorkflow.Status, false, nil } -func (impl *CdHandlerImpl) extractWorkflowStatus(workflowStatus bean6.CiCdStatus) *types.WorkflowStatus { +func (impl *CdHandlerImpl) extractWorkflowStatus(workflowStatus eventProcessorBean.CiCdStatus) *types.WorkflowStatus { workflowName := "" status := string(workflowStatus.Phase) podStatus := "Pending" diff --git a/pkg/pipeline/CiHandler.go b/pkg/pipeline/CiHandler.go index 1c60af4c2c..42eea8b72d 100644 --- a/pkg/pipeline/CiHandler.go +++ b/pkg/pipeline/CiHandler.go @@ -25,7 +25,7 @@ import ( "github.com/devtron-labs/common-lib/utils/workFlow" "github.com/devtron-labs/devtron/internal/sql/constants" "github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig/bean/workflow/cdWorkflow" - bean6 "github.com/devtron-labs/devtron/pkg/auth/user/bean" + userBean "github.com/devtron-labs/devtron/pkg/auth/user/bean" "github.com/devtron-labs/devtron/pkg/bean/common" "github.com/devtron-labs/devtron/pkg/build/artifacts/imageTagging" bean4 "github.com/devtron-labs/devtron/pkg/build/pipeline/bean" @@ -33,7 +33,7 @@ import ( bean5 "github.com/devtron-labs/devtron/pkg/cluster/bean" "github.com/devtron-labs/devtron/pkg/cluster/environment" repository2 "github.com/devtron-labs/devtron/pkg/cluster/environment/repository" - bean6 "github.com/devtron-labs/devtron/pkg/eventProcessor/bean" + eventProcessorBean "github.com/devtron-labs/devtron/pkg/eventProcessor/bean" constants2 "github.com/devtron-labs/devtron/pkg/pipeline/constants" util3 "github.com/devtron-labs/devtron/pkg/pipeline/util" "github.com/devtron-labs/devtron/pkg/pipeline/workflowStatus" @@ -77,7 +77,7 @@ import ( type CiHandler interface { HandleCIWebhook(gitCiTriggerRequest bean.GitCiTriggerRequest) (int, error) HandleCIManual(ciTriggerRequest bean.CiTriggerRequest) (int, error) - CheckAndReTriggerCI(workflowStatus bean6.CiCdStatus) error + CheckAndReTriggerCI(workflowStatus eventProcessorBean.CiCdStatus) error FetchMaterialsByPipelineId(pipelineId int, showAll bool) ([]pipelineConfig.CiPipelineMaterialResponse, error) FetchMaterialsByPipelineIdAndGitMaterialId(pipelineId int, gitMaterialId int, showAll bool) ([]pipelineConfig.CiPipelineMaterialResponse, error) FetchWorkflowDetails(appId int, pipelineId int, buildId int) (types.WorkflowResponse, error) @@ -91,7 +91,7 @@ type CiHandler interface { GetBuildHistory(pipelineId int, appId int, offset int, size int) ([]types.WorkflowResponse, error) DownloadCiWorkflowArtifacts(pipelineId int, buildId int) (*os.File, error) - UpdateWorkflow(workflowStatus bean6.CiCdStatus) (int, bool, error) + UpdateWorkflow(workflowStatus eventProcessorBean.CiCdStatus) (int, bool, error) FetchCiStatusForTriggerView(appId int) ([]*pipelineConfig.CiWorkflowStatus, error) FetchCiStatusForTriggerViewV1(appId int) ([]*pipelineConfig.CiWorkflowStatus, error) @@ -174,7 +174,7 @@ func NewCiHandlerImpl(Logger *zap.SugaredLogger, ciService CiService, ciPipeline return cih } -func (impl *CiHandlerImpl) CheckAndReTriggerCI(workflowStatus bean6.CiCdStatus) error { +func (impl *CiHandlerImpl) CheckAndReTriggerCI(workflowStatus eventProcessorBean.CiCdStatus) error { //return if re-trigger feature is disabled if !impl.config.WorkflowRetriesEnabled() { @@ -225,7 +225,7 @@ func (impl *CiHandlerImpl) reTriggerCi(retryCount int, refCiWorkflow *pipelineCo } trigger := types.Trigger{} - trigger.BuildTriggerObject(refCiWorkflow, ciMaterials, bean6.SYSTEM_USER_ID, true, nil, "") + trigger.BuildTriggerObject(refCiWorkflow, ciMaterials, userBean.SYSTEM_USER_ID, true, nil, "") _, err = impl.ciService.TriggerCiPipeline(trigger) if err != nil { @@ -1113,7 +1113,7 @@ func (impl *CiHandlerImpl) GetHistoricBuildLogs(workflowId int, ciWorkflow *pipe return resp, err } -func ExtractWorkflowStatus(workflowStatus bean6.CiCdStatus) (string, string, string, string, string, string) { +func ExtractWorkflowStatus(workflowStatus eventProcessorBean.CiCdStatus) (string, string, string, string, string, string) { workflowName := "" status := string(workflowStatus.Phase) podStatus := "" @@ -1143,7 +1143,7 @@ func ExtractWorkflowStatus(workflowStatus bean6.CiCdStatus) (string, string, str return workflowName, status, podStatus, message, logLocation, podName } -func (impl *CiHandlerImpl) extractPodStatusAndWorkflow(workflowStatus bean6.CiCdStatus) (string, string, *pipelineConfig.CiWorkflow, error) { +func (impl *CiHandlerImpl) extractPodStatusAndWorkflow(workflowStatus eventProcessorBean.CiCdStatus) (string, string, *pipelineConfig.CiWorkflow, error) { workflowName, status, _, message, _, _ := ExtractWorkflowStatus(workflowStatus) if workflowName == "" { impl.Logger.Errorw("extract workflow status, invalid wf name", "workflowName", workflowName, "status", status, "message", message) @@ -1178,7 +1178,7 @@ func (impl *CiHandlerImpl) getRefWorkflowAndCiRetryCount(savedWorkflow *pipeline return retryCount, savedWorkflow, err } -func (impl *CiHandlerImpl) UpdateWorkflow(workflowStatus bean6.CiCdStatus) (int, bool, error) { +func (impl *CiHandlerImpl) UpdateWorkflow(workflowStatus eventProcessorBean.CiCdStatus) (int, bool, error) { workflowName, status, podStatus, message, _, podName := ExtractWorkflowStatus(workflowStatus) if workflowName == "" { impl.Logger.Errorw("extract workflow status, invalid wf name", "workflowName", workflowName, "status", status, "podStatus", podStatus, "message", message) From 48773ff35912b061c23c853ca469d9afb0e9c801 Mon Sep 17 00:00:00 2001 From: Ash-exp Date: Fri, 4 Apr 2025 00:04:38 +0530 Subject: [PATCH 10/19] fix: updated DevtronAdministratorInstanceLabelKey for system executor --- pkg/pipeline/bean/WorkflowTemplate.go | 18 ++++++++++-------- pkg/pipeline/executors/WorkflowUtils.go | 9 +++++---- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/pkg/pipeline/bean/WorkflowTemplate.go b/pkg/pipeline/bean/WorkflowTemplate.go index d39968fa2e..abc8be4588 100644 --- a/pkg/pipeline/bean/WorkflowTemplate.go +++ b/pkg/pipeline/bean/WorkflowTemplate.go @@ -52,14 +52,16 @@ type WorkflowTemplate struct { } const ( - CI_WORKFLOW_NAME = "ci" - CI_WORKFLOW_WITH_STAGES = "ci-stages-with-env" - CiStage = "CI" - JobStage = "JOB" - CdStage = "CD" - CD_WORKFLOW_NAME = "cd" - CD_WORKFLOW_WITH_STAGES = "cd-stages-with-env" - WorkflowGenerateNamePrefix = "devtron.ai/generate-name-prefix" + CI_WORKFLOW_NAME = "ci" + CI_WORKFLOW_WITH_STAGES = "ci-stages-with-env" + CiStage = "CI" + JobStage = "JOB" + CdStage = "CD" + CD_WORKFLOW_NAME = "cd" + CD_WORKFLOW_WITH_STAGES = "cd-stages-with-env" + WorkflowGenerateNamePrefix = "devtron.ai/generate-name-prefix" + DevtronLabelPurposeKey = "devtron.ai/purpose" + DevtronLabelPurposeWorkflow = "workflow" ) func (workflowTemplate *WorkflowTemplate) GetEntrypoint() string { diff --git a/pkg/pipeline/executors/WorkflowUtils.go b/pkg/pipeline/executors/WorkflowUtils.go index f59022d797..c08bfd8efd 100644 --- a/pkg/pipeline/executors/WorkflowUtils.go +++ b/pkg/pipeline/executors/WorkflowUtils.go @@ -298,9 +298,10 @@ func CheckIfReTriggerRequired(status, message, workflowRunnerStatus string) bool func GetWorkflowLabelsForSystemExecutor(workflowTemplate bean.WorkflowTemplate) map[string]string { return map[string]string{ - DEVTRON_WORKFLOW_LABEL_KEY: DEVTRON_WORKFLOW_LABEL_VALUE, - "devtron.ai/purpose": "workflow", - informerBean.WorkflowTypeLabelKey: workflowTemplate.WorkflowType, - bean.WorkflowGenerateNamePrefix: workflowTemplate.WorkflowNamePrefix, + DEVTRON_WORKFLOW_LABEL_KEY: DEVTRON_WORKFLOW_LABEL_VALUE, + bean.DevtronLabelPurposeKey: bean.DevtronLabelPurposeWorkflow, + informerBean.WorkflowTypeLabelKey: workflowTemplate.WorkflowType, + bean.WorkflowGenerateNamePrefix: workflowTemplate.WorkflowNamePrefix, + informerBean.DevtronAdministratorInstanceLabelKey: workflowTemplate.DevtronInstanceUID, } } From 756be6791bca09155b81df7c10272ca0427a1da3 Mon Sep 17 00:00:00 2001 From: Ash-exp Date: Fri, 4 Apr 2025 02:17:03 +0530 Subject: [PATCH 11/19] fix: reverted base64 encoding --- .../in/WorkflowEventProcessorService.go | 19 ++++--------------- pkg/pipeline/WorkflowService.go | 3 +-- 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/pkg/eventProcessor/in/WorkflowEventProcessorService.go b/pkg/eventProcessor/in/WorkflowEventProcessorService.go index 12dd7155eb..ed466604d5 100644 --- a/pkg/eventProcessor/in/WorkflowEventProcessorService.go +++ b/pkg/eventProcessor/in/WorkflowEventProcessorService.go @@ -18,7 +18,6 @@ package in import ( "context" - "encoding/base64" "encoding/json" "errors" "fmt" @@ -404,13 +403,8 @@ func (impl *WorkflowEventProcessorImpl) SubscribeCIWorkflowStatusUpdate() error impl.logger.Errorw("error in getting UCID", "err", err) return } - decodedUCID, err := base64.StdEncoding.DecodeString(wfStatus.DevtronAdministratorInstance) - if err != nil { - impl.logger.Errorw("error in decoding UCID", "err", err) - return - } - if string(decodedUCID) != devtronUCID { - impl.logger.Warnw("mis match in UCID. skipping...", "decodedUCID", string(decodedUCID), "devtronUCID", devtronUCID) + if wfStatus.DevtronAdministratorInstance != devtronUCID { + impl.logger.Warnw("mis match in UCID. skipping...", "devtronAdministratorInstance", wfStatus.DevtronAdministratorInstance, "devtronUCID", devtronUCID) return } } @@ -465,13 +459,8 @@ func (impl *WorkflowEventProcessorImpl) SubscribeCDWorkflowStatusUpdate() error impl.logger.Errorw("error in getting UCID", "err", err) return } - decodedUCID, err := base64.StdEncoding.DecodeString(wfStatus.DevtronAdministratorInstance) - if err != nil { - impl.logger.Errorw("error in decoding UCID", "err", err) - return - } - if string(decodedUCID) != devtronUCID { - impl.logger.Warnw("mis match in UCID. skipping...", "decodedUCID", string(decodedUCID), "devtronUCID", devtronUCID) + if wfStatus.DevtronAdministratorInstance != devtronUCID { + impl.logger.Warnw("mis match in UCID. skipping...", "devtronAdministratorInstance", wfStatus.DevtronAdministratorInstance, "devtronUCID", devtronUCID) return } } diff --git a/pkg/pipeline/WorkflowService.go b/pkg/pipeline/WorkflowService.go index 660350a271..5aadc259bb 100644 --- a/pkg/pipeline/WorkflowService.go +++ b/pkg/pipeline/WorkflowService.go @@ -18,7 +18,6 @@ package pipeline import ( "context" - "encoding/base64" "encoding/json" "errors" "fmt" @@ -223,7 +222,7 @@ func (impl *WorkflowServiceImpl) createWorkflowTemplate(workflowRequest *types.W impl.Logger.Errorw("error in getting UCID", "err", err) return bean3.WorkflowTemplate{}, err } - workflowTemplate.DevtronInstanceUID = base64.StdEncoding.EncodeToString([]byte(devtronUCID)) + workflowTemplate.DevtronInstanceUID = devtronUCID return workflowTemplate, nil } From 3c42cd7b1189efc1f223fa1cfb05cafd08c763ef Mon Sep 17 00:00:00 2001 From: Ash-exp Date: Fri, 4 Apr 2025 03:12:43 +0530 Subject: [PATCH 12/19] fix: ci/ cd workflow msg update --- pkg/pipeline/CdHandler.go | 10 ++++++---- pkg/pipeline/CiHandler.go | 30 ++++++++++++++++-------------- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/pkg/pipeline/CdHandler.go b/pkg/pipeline/CdHandler.go index 210616b1b7..1bb887f9ba 100644 --- a/pkg/pipeline/CdHandler.go +++ b/pkg/pipeline/CdHandler.go @@ -295,10 +295,12 @@ func (impl *CdHandlerImpl) UpdateWorkflow(workflowStatus eventProcessorBean.CiCd savedWorkflow.CdArtifactLocation = cdArtifactLocation savedWorkflow.PodStatus = podStatus if !slices.Contains(cdWorkflowBean.WfrTerminalStatusList, savedWorkflow.Status) { - savedWorkflow.Message = message - // NOTE: we are doing this to fix where a pre-cd / post-cd workflow message becomes larger than 1000, and in db we had set the charter limit to 1000 - if len(message) > 1000 { - savedWorkflow.Message = message[:1000] + if !slices.Contains(cdWorkflowBean.WfrTerminalStatusList, savedWorkflow.PodStatus) { + savedWorkflow.Message = message + // NOTE: we are doing this to fix where a pre-cd / post-cd workflow message becomes larger than 1000, and in db we had set the charter limit to 1000 + if len(message) > 1000 { + savedWorkflow.Message = message[:1000] + } } savedWorkflow.FinishedOn = workflowStatus.FinishedAt.Time } else { diff --git a/pkg/pipeline/CiHandler.go b/pkg/pipeline/CiHandler.go index 42eea8b72d..9b8596cd91 100644 --- a/pkg/pipeline/CiHandler.go +++ b/pkg/pipeline/CiHandler.go @@ -24,7 +24,7 @@ import ( "github.com/devtron-labs/common-lib/utils" "github.com/devtron-labs/common-lib/utils/workFlow" "github.com/devtron-labs/devtron/internal/sql/constants" - "github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig/bean/workflow/cdWorkflow" + cdWorkflowBean "github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig/bean/workflow/cdWorkflow" userBean "github.com/devtron-labs/devtron/pkg/auth/user/bean" "github.com/devtron-labs/devtron/pkg/bean/common" "github.com/devtron-labs/devtron/pkg/build/artifacts/imageTagging" @@ -666,8 +666,8 @@ func (impl *CiHandlerImpl) CancelBuild(workflowId int, forceAbort bool) (int, er return workflow.Id, nil } - workflow.Status = cdWorkflow.WorkflowCancel - if workflow.ExecutorType == cdWorkflow.WORKFLOW_EXECUTOR_TYPE_SYSTEM { + workflow.Status = cdWorkflowBean.WorkflowCancel + if workflow.ExecutorType == cdWorkflowBean.WORKFLOW_EXECUTOR_TYPE_SYSTEM { workflow.PodStatus = "Failed" workflow.Message = constants2.TERMINATE_MESSAGE } @@ -710,7 +710,7 @@ func (impl *CiHandlerImpl) handleForceAbortCaseForCi(workflow *pipelineConfig.Ci } func (impl *CiHandlerImpl) updateWorkflowForForceAbort(workflow *pipelineConfig.CiWorkflow) error { - workflow.Status = cdWorkflow.WorkflowCancel + workflow.Status = cdWorkflowBean.WorkflowCancel workflow.PodStatus = string(bean.Failed) workflow.Message = constants2.FORCE_ABORT_MESSAGE_AFTER_STARTING_STAGE err := impl.ciService.UpdateCiWorkflowWithStage(workflow) @@ -878,7 +878,7 @@ func (impl *CiHandlerImpl) getWorkflowLogs(ciWorkflow *pipelineConfig.CiWorkflow if logStream == nil || err != nil { if !ciWorkflow.BlobStorageEnabled { return nil, nil, &util.ApiError{Code: "200", HttpStatusCode: 400, UserMessage: "logs-not-stored-in-repository"} - } else if string(v1alpha1.NodeSucceeded) == ciWorkflow.Status || string(v1alpha1.NodeError) == ciWorkflow.Status || string(v1alpha1.NodeFailed) == ciWorkflow.Status || ciWorkflow.Status == cdWorkflow.WorkflowCancel { + } else if string(v1alpha1.NodeSucceeded) == ciWorkflow.Status || string(v1alpha1.NodeError) == ciWorkflow.Status || string(v1alpha1.NodeFailed) == ciWorkflow.Status || ciWorkflow.Status == cdWorkflowBean.WorkflowCancel { impl.Logger.Debugw("pod is not live", "podName", ciWorkflow.PodName, "err", err) return impl.getLogsFromRepository(ciWorkflow, clusterConfig, isExt) } @@ -1200,22 +1200,24 @@ func (impl *CiHandlerImpl) UpdateWorkflow(workflowStatus eventProcessorBean.CiCd ciArtifactLocation := fmt.Sprintf(ciArtifactLocationFormat, savedWorkflow.Id, savedWorkflow.Id) if impl.stateChanged(status, podStatus, message, workflowStatus.FinishedAt.Time, savedWorkflow) { - if savedWorkflow.Status != cdWorkflow.WorkflowCancel { + if savedWorkflow.Status != cdWorkflowBean.WorkflowCancel { savedWorkflow.Status = status } savedWorkflow.PodStatus = podStatus - if !slices.Contains(cdWorkflow.WfrTerminalStatusList, savedWorkflow.Status) { - savedWorkflow.Message = message - // NOTE: we are doing this for a quick fix where ci pending message become larger than 250 and in db we had set the charter limit to 250 - if len(message) > 250 { - savedWorkflow.Message = message[:250] + if !slices.Contains(cdWorkflowBean.WfrTerminalStatusList, savedWorkflow.Status) { + if !slices.Contains(cdWorkflowBean.WfrTerminalStatusList, savedWorkflow.PodStatus) { + savedWorkflow.Message = message + // NOTE: we are doing this for a quick fix where ci pending message become larger than 250 and in db we had set the charter limit to 250 + if len(message) > 250 { + savedWorkflow.Message = message[:250] + } } savedWorkflow.FinishedOn = workflowStatus.FinishedAt.Time } else { impl.Logger.Warnw("cd stage already in terminal state. skipped message and finishedOn from being updated", "wfId", savedWorkflow.Id, "status", savedWorkflow.Status, "message", message, "finishedOn", workflowStatus.FinishedAt.Time) } - if savedWorkflow.ExecutorType == cdWorkflow.WORKFLOW_EXECUTOR_TYPE_SYSTEM && savedWorkflow.Status == cdWorkflow.WorkflowCancel { + if savedWorkflow.ExecutorType == cdWorkflowBean.WORKFLOW_EXECUTOR_TYPE_SYSTEM && savedWorkflow.Status == cdWorkflowBean.WorkflowCancel { savedWorkflow.PodStatus = "Failed" savedWorkflow.Message = constants2.TERMINATE_MESSAGE } @@ -1708,7 +1710,7 @@ func (impl *CiHandlerImpl) UpdateCiWorkflowStatusFailure(timeoutForFailureCiBuil // skip this and process for next ci workflow } } - if ciWorkflow.ExecutorType == cdWorkflow.WORKFLOW_EXECUTOR_TYPE_SYSTEM { + if ciWorkflow.ExecutorType == cdWorkflowBean.WORKFLOW_EXECUTOR_TYPE_SYSTEM { if wf.Status == string(v1alpha1.WorkflowFailed) { isPodDeleted = true } @@ -1724,7 +1726,7 @@ func (impl *CiHandlerImpl) UpdateCiWorkflowStatusFailure(timeoutForFailureCiBuil ciWorkflow.Status = "Failed" ciWorkflow.PodStatus = "Failed" if isPodDeleted { - ciWorkflow.Message = cdWorkflow.POD_DELETED_MESSAGE + ciWorkflow.Message = cdWorkflowBean.POD_DELETED_MESSAGE //error logging handled inside handlePodDeleted impl.handlePodDeleted(ciWorkflow) } else { From 23befaaadf2b982907da3053c45ebb030823a606 Mon Sep 17 00:00:00 2001 From: Ash-exp Date: Fri, 4 Apr 2025 10:27:28 +0530 Subject: [PATCH 13/19] fix: ci/ cd workflow msg update --- pkg/pipeline/CdHandler.go | 18 +++++++++--------- pkg/pipeline/CiHandler.go | 18 +++++++++--------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/pkg/pipeline/CdHandler.go b/pkg/pipeline/CdHandler.go index 1bb887f9ba..87d338263e 100644 --- a/pkg/pipeline/CdHandler.go +++ b/pkg/pipeline/CdHandler.go @@ -294,18 +294,18 @@ func (impl *CdHandlerImpl) UpdateWorkflow(workflowStatus eventProcessorBean.CiCd } savedWorkflow.CdArtifactLocation = cdArtifactLocation savedWorkflow.PodStatus = podStatus - if !slices.Contains(cdWorkflowBean.WfrTerminalStatusList, savedWorkflow.Status) { - if !slices.Contains(cdWorkflowBean.WfrTerminalStatusList, savedWorkflow.PodStatus) { - savedWorkflow.Message = message - // NOTE: we are doing this to fix where a pre-cd / post-cd workflow message becomes larger than 1000, and in db we had set the charter limit to 1000 - if len(message) > 1000 { - savedWorkflow.Message = message[:1000] - } + if !slices.Contains(cdWorkflowBean.WfrTerminalStatusList, savedWorkflow.PodStatus) { + savedWorkflow.Message = message + // NOTE: we are doing this to fix where a pre-cd / post-cd workflow message becomes larger than 1000, and in db we had set the charter limit to 1000 + if len(message) > 1000 { + savedWorkflow.Message = message[:1000] + } + if !slices.Contains(cdWorkflowBean.WfrTerminalStatusList, savedWorkflow.Status) { + savedWorkflow.FinishedOn = workflowStatus.FinishedAt.Time } - savedWorkflow.FinishedOn = workflowStatus.FinishedAt.Time } else { impl.Logger.Warnw("cd stage already in terminal state. skipped message and finishedOn from being updated", - "wfId", savedWorkflow.Id, "status", savedWorkflow.Status, "message", message, "finishedOn", workflowStatus.FinishedAt.Time) + "wfId", savedWorkflow.Id, "podStatus", savedWorkflow.PodStatus, "status", savedWorkflow.Status, "message", message, "finishedOn", workflowStatus.FinishedAt.Time) } savedWorkflow.Name = workflowName // removed log location from here since we are saving it at trigger diff --git a/pkg/pipeline/CiHandler.go b/pkg/pipeline/CiHandler.go index 9b8596cd91..8bffdea516 100644 --- a/pkg/pipeline/CiHandler.go +++ b/pkg/pipeline/CiHandler.go @@ -1204,18 +1204,18 @@ func (impl *CiHandlerImpl) UpdateWorkflow(workflowStatus eventProcessorBean.CiCd savedWorkflow.Status = status } savedWorkflow.PodStatus = podStatus - if !slices.Contains(cdWorkflowBean.WfrTerminalStatusList, savedWorkflow.Status) { - if !slices.Contains(cdWorkflowBean.WfrTerminalStatusList, savedWorkflow.PodStatus) { - savedWorkflow.Message = message - // NOTE: we are doing this for a quick fix where ci pending message become larger than 250 and in db we had set the charter limit to 250 - if len(message) > 250 { - savedWorkflow.Message = message[:250] - } + if !slices.Contains(cdWorkflowBean.WfrTerminalStatusList, savedWorkflow.PodStatus) { + savedWorkflow.Message = message + // NOTE: we are doing this for a quick fix where ci pending message become larger than 250 and in db we had set the charter limit to 250 + if len(message) > 250 { + savedWorkflow.Message = message[:250] + } + if !slices.Contains(cdWorkflowBean.WfrTerminalStatusList, savedWorkflow.Status) { + savedWorkflow.FinishedOn = workflowStatus.FinishedAt.Time } - savedWorkflow.FinishedOn = workflowStatus.FinishedAt.Time } else { impl.Logger.Warnw("cd stage already in terminal state. skipped message and finishedOn from being updated", - "wfId", savedWorkflow.Id, "status", savedWorkflow.Status, "message", message, "finishedOn", workflowStatus.FinishedAt.Time) + "wfId", savedWorkflow.Id, "podStatus", savedWorkflow.PodStatus, "status", savedWorkflow.Status, "message", message, "finishedOn", workflowStatus.FinishedAt.Time) } if savedWorkflow.ExecutorType == cdWorkflowBean.WORKFLOW_EXECUTOR_TYPE_SYSTEM && savedWorkflow.Status == cdWorkflowBean.WorkflowCancel { savedWorkflow.PodStatus = "Failed" From 87a2f2593b66a1dcd05fc3718866eafb56e85b55 Mon Sep 17 00:00:00 2001 From: Ash-exp Date: Fri, 4 Apr 2025 11:26:19 +0530 Subject: [PATCH 14/19] matrics for retrigger failed event --- internal/middleware/instrument.go | 5 ++++ .../in/WorkflowEventProcessorService.go | 29 ++++++++++++------- pkg/pipeline/CdHandler.go | 12 ++++---- pkg/pipeline/CiHandler.go | 8 ++--- 4 files changed, 33 insertions(+), 21 deletions(-) diff --git a/internal/middleware/instrument.go b/internal/middleware/instrument.go index 0bbb8693e3..7fcc0d9ebf 100644 --- a/internal/middleware/instrument.go +++ b/internal/middleware/instrument.go @@ -117,6 +117,11 @@ var TerminalSessionDuration = promauto.NewHistogramVec(prometheus.HistogramOpts{ Help: "duration of each terminal session", }, []string{"podName", "namespace", "clusterId"}) +var ReTriggerFailedCounter = promauto.NewCounterVec(prometheus.CounterOpts{ + Name: "re_trigger_failed_counter", + Help: "ci/ pre cd/ post cd workflow re-trigger failed counter", +}, []string{"workflowType", "workflowId"}) + // prometheusMiddleware implements mux.MiddlewareFunc. func PrometheusMiddleware(next http.Handler) http.Handler { // prometheus.MustRegister(requestCounter) diff --git a/pkg/eventProcessor/in/WorkflowEventProcessorService.go b/pkg/eventProcessor/in/WorkflowEventProcessorService.go index ed466604d5..8388295dd5 100644 --- a/pkg/eventProcessor/in/WorkflowEventProcessorService.go +++ b/pkg/eventProcessor/in/WorkflowEventProcessorService.go @@ -27,6 +27,7 @@ import ( "github.com/devtron-labs/common-lib/utils/registry" apiBean "github.com/devtron-labs/devtron/api/bean" client "github.com/devtron-labs/devtron/client/events" + "github.com/devtron-labs/devtron/internal/middleware" "github.com/devtron-labs/devtron/internal/sql/constants" "github.com/devtron-labs/devtron/internal/sql/models" "github.com/devtron-labs/devtron/internal/sql/repository" @@ -409,7 +410,7 @@ func (impl *WorkflowEventProcessorImpl) SubscribeCIWorkflowStatusUpdate() error } } // update the ci workflow status - _, stateChanged, err := impl.ciHandler.UpdateWorkflow(wfStatus) + ciWfId, stateChanged, err := impl.ciHandler.UpdateWorkflow(wfStatus) if err != nil { impl.logger.Errorw("error on update workflow status", "msg", msg.Data, "err", err) return @@ -418,9 +419,12 @@ func (impl *WorkflowEventProcessorImpl) SubscribeCIWorkflowStatusUpdate() error // check if we need to re-trigger the ci err = impl.ciHandler.CheckAndReTriggerCI(wfStatus) if err != nil { + middleware.ReTriggerFailedCounter.WithLabelValues("CI", strconv.Itoa(ciWfId)).Inc() impl.logger.Errorw("error in checking and re triggering ci", "wfStatus", wfStatus, "err", err) return } + } else { + impl.logger.Debugw("no state change detected for the ci workflow status update, ignoring this event", "workflowRunnerId", ciWfId, "wfStatus", wfStatus) } } @@ -439,7 +443,7 @@ func (impl *WorkflowEventProcessorImpl) SubscribeCIWorkflowStatusUpdate() error err := impl.pubSubClient.Subscribe(pubsub.WORKFLOW_STATUS_UPDATE_TOPIC, callback, loggerFunc) if err != nil { - impl.logger.Error("err", err) + impl.logger.Error("error in subscribing to ci workflow status update topic", "err", err) return err } return nil @@ -464,10 +468,10 @@ func (impl *WorkflowEventProcessorImpl) SubscribeCDWorkflowStatusUpdate() error return } } - wfrId, wfrStatus, stateChanged, err := impl.cdHandler.UpdateWorkflow(wfStatus) - impl.logger.Debugw("cd UpdateWorkflow for wfStatus", "wfrId", wfrId, "wfrStatus", wfrStatus, "wfStatus", wfStatus) + wfrId, status, stateChanged, err := impl.cdHandler.UpdateWorkflow(wfStatus) + impl.logger.Debugw("cd UpdateWorkflow for wfStatus", "wfrId", wfrId, "status", status, "wfStatus", wfStatus) if err != nil { - impl.logger.Errorw("error in cd workflow status update", "wfrId", wfrId, "wfrStatus", wfrStatus, "wfStatus", wfStatus, "err", err) + impl.logger.Errorw("error in cd workflow status update", "wfrId", wfrId, "status", status, "wfStatus", wfStatus, "err", err) return } @@ -478,7 +482,7 @@ func (impl *WorkflowEventProcessorImpl) SubscribeCDWorkflowStatusUpdate() error return } - if wfrStatus == string(v1alpha1.NodeFailed) || wfrStatus == string(v1alpha1.NodeError) { + if wfr.Status == string(v1alpha1.NodeFailed) || wfr.Status == string(v1alpha1.NodeError) { if len(wfr.ImagePathReservationIds) > 0 { err := impl.cdHandler.DeactivateImageReservationPathsOnFailure(wfr.ImagePathReservationIds) if err != nil { @@ -491,13 +495,16 @@ func (impl *WorkflowEventProcessorImpl) SubscribeCDWorkflowStatusUpdate() error wfStatusInEvent := string(wfStatus.Phase) if wfStatusInEvent == string(v1alpha1.NodeSucceeded) || wfStatusInEvent == string(v1alpha1.NodeFailed) || wfStatusInEvent == string(v1alpha1.NodeError) { // the re-trigger should only happen when we get a pod deleted event. - if wfr != nil && executors.CheckIfReTriggerRequired(wfrStatus, wfStatus.Message, wfr.Status) { + if executors.CheckIfReTriggerRequired(status, wfStatus.Message, wfr.Status) { err = impl.workflowDagExecutor.HandleCdStageReTrigger(wfr) if err != nil { // check if this log required or not - impl.logger.Errorw("error in HandleCdStageReTrigger", "workflowRunnerId", wfr.Id, "workflowStatus", wfrStatus, "workflowStatusMessage", wfStatus.Message, "error", err) + workflowType := fmt.Sprintf("%s-CD", wfr.WorkflowType) + middleware.ReTriggerFailedCounter.WithLabelValues(workflowType, strconv.Itoa(wfrId)).Inc() + impl.logger.Errorw("error in HandleCdStageReTrigger", "workflowRunnerId", wfr.Id, "status", status, "message", wfStatus.Message, "error", err) + return } - impl.logger.Debugw("re-triggered cd stage", "workflowRunnerId", wfr.Id, "workflowStatus", wfrStatus, "workflowStatusMessage", wfStatus.Message) + impl.logger.Debugw("re-triggered cd stage", "workflowRunnerId", wfr.Id, "status", status, "message", wfStatus.Message) } else { // we send this notification on *workflow_runner* status, both success and failure // during workflow runner failure, particularly when failure occurred due to pod deletion , we get two events from kubewatch. @@ -513,7 +520,7 @@ func (impl *WorkflowEventProcessorImpl) SubscribeCDWorkflowStatusUpdate() error } } } else { - impl.logger.Debugw("no state change detected for the cd workflow status update, ignoring this event", "workflowRunnerId", wfrId, "wfrStatus", wfrStatus) + impl.logger.Debugw("no state change detected for the cd workflow status update, ignoring this event", "workflowRunnerId", wfrId, "status", status) } } @@ -530,7 +537,7 @@ func (impl *WorkflowEventProcessorImpl) SubscribeCDWorkflowStatusUpdate() error err := impl.pubSubClient.Subscribe(pubsub.CD_WORKFLOW_STATUS_UPDATE, callback, loggerFunc) if err != nil { - impl.logger.Error("err", err) + impl.logger.Error("error in subscribing to cd workflow status update topic", "err", err) return err } return nil diff --git a/pkg/pipeline/CdHandler.go b/pkg/pipeline/CdHandler.go index 87d338263e..4889e361b6 100644 --- a/pkg/pipeline/CdHandler.go +++ b/pkg/pipeline/CdHandler.go @@ -289,11 +289,6 @@ func (impl *CdHandlerImpl) UpdateWorkflow(workflowStatus eventProcessorBean.CiCd cdArtifactLocationFormat := impl.config.GetArtifactLocationFormat() cdArtifactLocation := fmt.Sprintf(cdArtifactLocationFormat, savedWorkflow.CdWorkflowId, savedWorkflow.Id) if impl.stateChanged(status, podStatus, message, workflowStatus.FinishedAt.Time, savedWorkflow) { - if savedWorkflow.Status != cdWorkflowBean.WorkflowCancel { - savedWorkflow.Status = status - } - savedWorkflow.CdArtifactLocation = cdArtifactLocation - savedWorkflow.PodStatus = podStatus if !slices.Contains(cdWorkflowBean.WfrTerminalStatusList, savedWorkflow.PodStatus) { savedWorkflow.Message = message // NOTE: we are doing this to fix where a pre-cd / post-cd workflow message becomes larger than 1000, and in db we had set the charter limit to 1000 @@ -307,6 +302,11 @@ func (impl *CdHandlerImpl) UpdateWorkflow(workflowStatus eventProcessorBean.CiCd impl.Logger.Warnw("cd stage already in terminal state. skipped message and finishedOn from being updated", "wfId", savedWorkflow.Id, "podStatus", savedWorkflow.PodStatus, "status", savedWorkflow.Status, "message", message, "finishedOn", workflowStatus.FinishedAt.Time) } + if savedWorkflow.Status != cdWorkflowBean.WorkflowCancel { + savedWorkflow.Status = status + } + savedWorkflow.CdArtifactLocation = cdArtifactLocation + savedWorkflow.PodStatus = podStatus savedWorkflow.Name = workflowName // removed log location from here since we are saving it at trigger savedWorkflow.PodName = podName @@ -330,7 +330,7 @@ func (impl *CdHandlerImpl) UpdateWorkflow(workflowStatus eventProcessorBean.CiCd } return savedWorkflow.Id, savedWorkflow.Status, true, nil } - return savedWorkflow.Id, savedWorkflow.Status, false, nil + return savedWorkflow.Id, status, false, nil } func (impl *CdHandlerImpl) extractWorkflowStatus(workflowStatus eventProcessorBean.CiCdStatus) *types.WorkflowStatus { diff --git a/pkg/pipeline/CiHandler.go b/pkg/pipeline/CiHandler.go index 8bffdea516..8fb4a4b8da 100644 --- a/pkg/pipeline/CiHandler.go +++ b/pkg/pipeline/CiHandler.go @@ -1200,10 +1200,6 @@ func (impl *CiHandlerImpl) UpdateWorkflow(workflowStatus eventProcessorBean.CiCd ciArtifactLocation := fmt.Sprintf(ciArtifactLocationFormat, savedWorkflow.Id, savedWorkflow.Id) if impl.stateChanged(status, podStatus, message, workflowStatus.FinishedAt.Time, savedWorkflow) { - if savedWorkflow.Status != cdWorkflowBean.WorkflowCancel { - savedWorkflow.Status = status - } - savedWorkflow.PodStatus = podStatus if !slices.Contains(cdWorkflowBean.WfrTerminalStatusList, savedWorkflow.PodStatus) { savedWorkflow.Message = message // NOTE: we are doing this for a quick fix where ci pending message become larger than 250 and in db we had set the charter limit to 250 @@ -1217,6 +1213,10 @@ func (impl *CiHandlerImpl) UpdateWorkflow(workflowStatus eventProcessorBean.CiCd impl.Logger.Warnw("cd stage already in terminal state. skipped message and finishedOn from being updated", "wfId", savedWorkflow.Id, "podStatus", savedWorkflow.PodStatus, "status", savedWorkflow.Status, "message", message, "finishedOn", workflowStatus.FinishedAt.Time) } + if savedWorkflow.Status != cdWorkflowBean.WorkflowCancel { + savedWorkflow.Status = status + } + savedWorkflow.PodStatus = podStatus if savedWorkflow.ExecutorType == cdWorkflowBean.WORKFLOW_EXECUTOR_TYPE_SYSTEM && savedWorkflow.Status == cdWorkflowBean.WorkflowCancel { savedWorkflow.PodStatus = "Failed" savedWorkflow.Message = constants2.TERMINATE_MESSAGE From 2a76464e1bb64ce0a232f7498cdc9a9e4153ab71 Mon Sep 17 00:00:00 2001 From: Ash-exp Date: Fri, 4 Apr 2025 11:28:08 +0530 Subject: [PATCH 15/19] updated logger --- pkg/eventProcessor/in/WorkflowEventProcessorService.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/eventProcessor/in/WorkflowEventProcessorService.go b/pkg/eventProcessor/in/WorkflowEventProcessorService.go index 8388295dd5..9816c31920 100644 --- a/pkg/eventProcessor/in/WorkflowEventProcessorService.go +++ b/pkg/eventProcessor/in/WorkflowEventProcessorService.go @@ -504,7 +504,7 @@ func (impl *WorkflowEventProcessorImpl) SubscribeCDWorkflowStatusUpdate() error impl.logger.Errorw("error in HandleCdStageReTrigger", "workflowRunnerId", wfr.Id, "status", status, "message", wfStatus.Message, "error", err) return } - impl.logger.Debugw("re-triggered cd stage", "workflowRunnerId", wfr.Id, "status", status, "message", wfStatus.Message) + impl.logger.Infow("re-triggered cd stage", "workflowRunnerId", wfr.Id, "status", status, "message", wfStatus.Message) } else { // we send this notification on *workflow_runner* status, both success and failure // during workflow runner failure, particularly when failure occurred due to pod deletion , we get two events from kubewatch. From b54bb9efc677cf5be493a9adab904071a1497871 Mon Sep 17 00:00:00 2001 From: Ash-exp Date: Tue, 8 Apr 2025 00:40:25 +0530 Subject: [PATCH 16/19] chore: posthug refactoring and const renamed --- App.go | 6 +- Wire.go | 8 +- client/telemetry/TelemetryEventClient.go | 26 ++--- .../telemetry/TelemetryEventClientExtended.go | 10 +- cmd/external-app/externalApp.go | 6 +- cmd/external-app/wire.go | 4 +- cmd/external-app/wire_gen.go | 2 +- go.mod | 4 +- go.sum | 8 +- .../pipelineConfig/CdWorfkflowRepository.go | 1 - pkg/pipeline/CdHandler.go | 4 - pkg/pipeline/bean/WorkflowTemplate.go | 6 +- pkg/pipeline/executors/WorkflowUtils.go | 10 +- .../sql/32703300_workflow_message.down.sql | 1 + scripts/sql/32703300_workflow_message.up.sql | 11 +++ .../devtron-labs/common-lib/informer/bean.go | 2 +- .../common-lib/telemetry/PosthogClient.go | 99 +++++++++++++++++++ .../devtron-labs/common-lib/telemetry/bean.go | 34 +++++++ .../common-lib/utils/http/HttpUtil.go | 12 ++- vendor/modules.txt | 9 +- wire_gen.go | 8 +- 21 files changed, 208 insertions(+), 63 deletions(-) create mode 100644 scripts/sql/32703300_workflow_message.down.sql create mode 100644 scripts/sql/32703300_workflow_message.up.sql create mode 100644 vendor/github.com/devtron-labs/common-lib/telemetry/PosthogClient.go create mode 100644 vendor/github.com/devtron-labs/common-lib/telemetry/bean.go diff --git a/App.go b/App.go index 37c38ed9d2..649c319298 100644 --- a/App.go +++ b/App.go @@ -23,7 +23,7 @@ import ( "fmt" "github.com/devtron-labs/common-lib/middlewares" pubsub "github.com/devtron-labs/common-lib/pubsub-lib" - "github.com/devtron-labs/devtron/client/telemetry/posthog" + posthogTelemetry "github.com/devtron-labs/common-lib/telemetry" "github.com/devtron-labs/devtron/pkg/eventProcessor" "github.com/devtron-labs/devtron/pkg/eventProcessor/in" "log" @@ -55,7 +55,7 @@ type App struct { EnforcerV2 *casbinv2.SyncedEnforcer server *http.Server db *pg.DB - posthogClient *posthog.PosthogClient + posthogClient *posthogTelemetry.PosthogClient // eventProcessor.CentralEventProcessor is used to register event processors centralEventProcessor *eventProcessor.CentralEventProcessor // do not remove this. // used for local dev only @@ -73,7 +73,7 @@ func NewApp(router *router.MuxRouter, enforcer *casbin.SyncedEnforcer, db *pg.DB, sessionManager2 *authMiddleware.SessionManager, - posthogClient *posthog.PosthogClient, + posthogClient *posthogTelemetry.PosthogClient, loggingMiddleware util.LoggingMiddleware, centralEventProcessor *eventProcessor.CentralEventProcessor, pubSubClient *pubsub.PubSubClientServiceImpl, diff --git a/Wire.go b/Wire.go index f7446f1573..d58d997949 100644 --- a/Wire.go +++ b/Wire.go @@ -22,7 +22,8 @@ package main import ( "github.com/devtron-labs/authenticator/middleware" cloudProviderIdentifier "github.com/devtron-labs/common-lib/cloud-provider-identifier" - pubsub1 "github.com/devtron-labs/common-lib/pubsub-lib" + pubSub "github.com/devtron-labs/common-lib/pubsub-lib" + posthogTelemetry "github.com/devtron-labs/common-lib/telemetry" util4 "github.com/devtron-labs/common-lib/utils/k8s" "github.com/devtron-labs/devtron/api/apiToken" appStoreRestHandler "github.com/devtron-labs/devtron/api/appStore" @@ -97,7 +98,6 @@ import ( "github.com/devtron-labs/devtron/client/lens" "github.com/devtron-labs/devtron/client/proxy" "github.com/devtron-labs/devtron/client/telemetry" - "github.com/devtron-labs/devtron/client/telemetry/posthog" "github.com/devtron-labs/devtron/internal/sql/repository" app2 "github.com/devtron-labs/devtron/internal/sql/repository/app" appStatusRepo "github.com/devtron-labs/devtron/internal/sql/repository/appStatus" @@ -502,7 +502,7 @@ func InitializeApp() (*App, error) { pipeline.NewCiLogServiceImpl, wire.Bind(new(pipeline.CiLogService), new(*pipeline.CiLogServiceImpl)), - pubsub1.NewPubSubClientServiceImpl, + pubSub.NewPubSubClientServiceImpl, rbac.NewEnforcerUtilImpl, wire.Bind(new(rbac.EnforcerUtil), new(*rbac.EnforcerUtilImpl)), @@ -694,7 +694,7 @@ func InitializeApp() (*App, error) { wire.Bind(new(router.TelemetryRouter), new(*router.TelemetryRouterImpl)), restHandler.NewTelemetryRestHandlerImpl, wire.Bind(new(restHandler.TelemetryRestHandler), new(*restHandler.TelemetryRestHandlerImpl)), - posthog.NewPosthogClient, + posthogTelemetry.NewPosthogClient, ucid.WireSet, cloudProviderIdentifier.NewProviderIdentifierServiceImpl, diff --git a/client/telemetry/TelemetryEventClient.go b/client/telemetry/TelemetryEventClient.go index 7a4a697094..4a8f673ab7 100644 --- a/client/telemetry/TelemetryEventClient.go +++ b/client/telemetry/TelemetryEventClient.go @@ -22,9 +22,9 @@ import ( "encoding/json" "fmt" cloudProviderIdentifier "github.com/devtron-labs/common-lib/cloud-provider-identifier" + posthogTelemetry "github.com/devtron-labs/common-lib/telemetry" "github.com/devtron-labs/common-lib/utils/k8s/commonBean" "github.com/devtron-labs/devtron/api/helm-app/gRPC" - posthogClient "github.com/devtron-labs/devtron/client/telemetry/posthog" installedAppReader "github.com/devtron-labs/devtron/pkg/appStore/installedApp/read" bean2 "github.com/devtron-labs/devtron/pkg/attributes/bean" "github.com/devtron-labs/devtron/pkg/auth/user/bean" @@ -63,7 +63,7 @@ type TelemetryEventClientImpl struct { userService user2.UserService attributeRepo repository.AttributesRepository ssoLoginService sso.SSOLoginService - posthogClient *posthogClient.PosthogClient + posthogClient *posthogTelemetry.PosthogClient ucid ucidService.Service moduleRepository moduleRepo.ModuleRepository serverDataStore *serverDataStore.ServerDataStore @@ -88,7 +88,7 @@ type TelemetryEventClient interface { func NewTelemetryEventClientImpl(logger *zap.SugaredLogger, client *http.Client, clusterService cluster.ClusterService, K8sUtil *k8s.K8sServiceImpl, aCDAuthConfig *util3.ACDAuthConfig, userService user2.UserService, attributeRepo repository.AttributesRepository, ssoLoginService sso.SSOLoginService, - posthog *posthogClient.PosthogClient, ucid ucidService.Service, + posthog *posthogTelemetry.PosthogClient, ucid ucidService.Service, moduleRepository moduleRepo.ModuleRepository, serverDataStore *serverDataStore.ServerDataStore, userAuditService user2.UserAuditService, helmAppClient gRPC.HelmAppClient, cloudProviderIdentifierService cloudProviderIdentifier.ProviderIdentifierService, cronLogger *cron3.CronLoggerImpl, @@ -120,13 +120,13 @@ func NewTelemetryEventClientImpl(logger *zap.SugaredLogger, client *http.Client, } watcher.HeartbeatEventForTelemetry() - _, err := cron.AddFunc(posthogClient.SummaryCronExpr, watcher.SummaryEventForTelemetryEA) + _, err := cron.AddFunc(posthogTelemetry.SummaryCronExpr, watcher.SummaryEventForTelemetryEA) if err != nil { logger.Errorw("error in starting summery event", "err", err) return nil, err } - _, err = cron.AddFunc(posthogClient.HeartbeatCronExpr, watcher.HeartbeatEventForTelemetry) + _, err = cron.AddFunc(posthogTelemetry.HeartbeatCronExpr, watcher.HeartbeatEventForTelemetry) if err != nil { logger.Errorw("error in starting heartbeat event", "err", err) return nil, err @@ -275,7 +275,7 @@ func (impl *TelemetryEventClientImpl) SendSummaryEvent(eventType string) error { return err } - if posthogClient.IsOptOut { + if posthogTelemetry.IsOptOut { impl.logger.Warnw("client is opt-out for telemetry, there will be no events capture", "ucid", ucid) return err } @@ -353,7 +353,7 @@ func (impl *TelemetryEventClientImpl) SendGenericTelemetryEvent(eventType string return nil } - if posthogClient.IsOptOut { + if posthogTelemetry.IsOptOut { impl.logger.Warnw("client is opt-out for telemetry, there will be no events capture", "ucid", ucid) return nil } @@ -364,7 +364,7 @@ func (impl *TelemetryEventClientImpl) SendGenericTelemetryEvent(eventType string func (impl *TelemetryEventClientImpl) EnqueueGenericPostHogEvent(ucid string, eventType string, prop map[string]interface{}) error { if impl.posthogClient.Client == nil { impl.logger.Warn("no posthog client found, creating new") - client, err := impl.retryPosthogClient(posthogClient.PosthogApiKey, posthogClient.PosthogEndpoint) + client, err := impl.retryPosthogClient(posthogTelemetry.PosthogApiKey, posthogTelemetry.PosthogEndpoint) if err == nil { impl.posthogClient.Client = client } @@ -389,7 +389,7 @@ func (impl *TelemetryEventClientImpl) HeartbeatEventForTelemetry() { impl.logger.Errorw("exception caught inside telemetry heartbeat event", "err", err) return } - if posthogClient.IsOptOut { + if posthogTelemetry.IsOptOut { impl.logger.Warnw("client is opt-out for telemetry, there will be no events capture", "ucid", ucid) return } @@ -437,9 +437,9 @@ func (impl *TelemetryEventClientImpl) GetTelemetryMetaInfo() (*TelemetryMetaInfo return nil, err } data := &TelemetryMetaInfo{ - Url: posthogClient.PosthogEndpoint, + Url: posthogTelemetry.PosthogEndpoint, UCID: ucid, - ApiKey: posthogClient.PosthogEncodedApiKey, + ApiKey: posthogTelemetry.PosthogEncodedApiKey, } return data, err } @@ -668,7 +668,7 @@ func (impl *TelemetryEventClientImpl) getUCIDAndCheckIsOptedOut(ctx context.Cont impl.logger.Errorw("error sending event to posthog, failed check for opt-out", "err", err) return "", err } - posthogClient.IsOptOut = flag + posthogTelemetry.IsOptOut = flag } return ucid, nil } @@ -676,7 +676,7 @@ func (impl *TelemetryEventClientImpl) getUCIDAndCheckIsOptedOut(ctx context.Cont func (impl *TelemetryEventClientImpl) checkForOptOut(ctx context.Context, UCID string) (bool, error) { newCtx, span := otel.Tracer("orchestrator").Start(ctx, "TelemetryEventClientImpl.checkForOptOut") defer span.End() - decodedUrl, err := base64.StdEncoding.DecodeString(posthogClient.TelemetryOptOutApiBaseUrl) + decodedUrl, err := base64.StdEncoding.DecodeString(posthogTelemetry.TelemetryOptOutApiBaseUrl) if err != nil { impl.logger.Errorw("check opt-out list failed, decode error", "err", err) return false, err diff --git a/client/telemetry/TelemetryEventClientExtended.go b/client/telemetry/TelemetryEventClientExtended.go index 1670a6b4db..d5b309b6f6 100644 --- a/client/telemetry/TelemetryEventClientExtended.go +++ b/client/telemetry/TelemetryEventClientExtended.go @@ -20,9 +20,9 @@ import ( "context" "encoding/json" cloudProviderIdentifier "github.com/devtron-labs/common-lib/cloud-provider-identifier" + posthogTelemetry "github.com/devtron-labs/common-lib/telemetry" util2 "github.com/devtron-labs/common-lib/utils/k8s" client "github.com/devtron-labs/devtron/api/helm-app/gRPC" - posthogClient "github.com/devtron-labs/devtron/client/telemetry/posthog" installedAppReader "github.com/devtron-labs/devtron/pkg/appStore/installedApp/read" "github.com/devtron-labs/devtron/pkg/auth/sso" user2 "github.com/devtron-labs/devtron/pkg/auth/user" @@ -74,7 +74,7 @@ type TelemetryEventClientImplExtended struct { func NewTelemetryEventClientImplExtended(logger *zap.SugaredLogger, client *http.Client, clusterService cluster.ClusterService, K8sUtil *util2.K8sServiceImpl, aCDAuthConfig *util3.ACDAuthConfig, environmentService environment.EnvironmentService, userService user2.UserService, - appListingRepository repository.AppListingRepository, posthog *posthogClient.PosthogClient, ucid ucidService.Service, + appListingRepository repository.AppListingRepository, posthog *posthogTelemetry.PosthogClient, ucid ucidService.Service, ciPipelineConfigReadService ciConfig.CiPipelineConfigReadService, pipelineRepository pipelineConfig.PipelineRepository, gitProviderRepository repository3.GitProviderRepository, attributeRepo repository.AttributesRepository, ssoLoginService sso.SSOLoginService, appRepository app.AppRepository, @@ -129,13 +129,13 @@ func NewTelemetryEventClientImplExtended(logger *zap.SugaredLogger, client *http } watcher.HeartbeatEventForTelemetry() - _, err := cron.AddFunc(posthogClient.SummaryCronExpr, watcher.SummaryEventForTelemetry) + _, err := cron.AddFunc(posthogTelemetry.SummaryCronExpr, watcher.SummaryEventForTelemetry) if err != nil { logger.Errorw("error in starting summery event", "err", err) return nil, err } - _, err = cron.AddFunc(posthogClient.HeartbeatCronExpr, watcher.HeartbeatEventForTelemetry) + _, err = cron.AddFunc(posthogTelemetry.HeartbeatCronExpr, watcher.HeartbeatEventForTelemetry) if err != nil { logger.Errorw("error in starting heartbeat event", "err", err) return nil, err @@ -158,7 +158,7 @@ func (impl *TelemetryEventClientImplExtended) SendSummaryEvent(eventType string) return err } - if posthogClient.IsOptOut { + if posthogTelemetry.IsOptOut { impl.logger.Warnw("client is opt-out for telemetry, there will be no events capture", "ucid", ucid) return err } diff --git a/cmd/external-app/externalApp.go b/cmd/external-app/externalApp.go index 8d5ee62cb7..dba06f4eea 100644 --- a/cmd/external-app/externalApp.go +++ b/cmd/external-app/externalApp.go @@ -20,7 +20,7 @@ import ( "context" "errors" "fmt" - "github.com/devtron-labs/devtron/client/telemetry/posthog" + posthogTelemetry "github.com/devtron-labs/common-lib/telemetry" "net/http" "os" "time" @@ -41,14 +41,14 @@ type App struct { Logger *zap.SugaredLogger server *http.Server telemetry telemetry.TelemetryEventClient - posthogClient *posthog.PosthogClient + posthogClient *posthogTelemetry.PosthogClient } func NewApp(db *pg.DB, sessionManager *authMiddleware.SessionManager, MuxRouter *MuxRouter, telemetry telemetry.TelemetryEventClient, - posthogClient *posthog.PosthogClient, + posthogClient *posthogTelemetry.PosthogClient, Logger *zap.SugaredLogger) *App { return &App{ db: db, diff --git a/cmd/external-app/wire.go b/cmd/external-app/wire.go index 4dc491cd7f..31a15cbf8a 100644 --- a/cmd/external-app/wire.go +++ b/cmd/external-app/wire.go @@ -22,6 +22,7 @@ package main import ( "github.com/devtron-labs/authenticator/middleware" cloudProviderIdentifier "github.com/devtron-labs/common-lib/cloud-provider-identifier" + posthogTelemetry "github.com/devtron-labs/common-lib/telemetry" util4 "github.com/devtron-labs/common-lib/utils/k8s" "github.com/devtron-labs/devtron/api/apiToken" "github.com/devtron-labs/devtron/api/appStore" @@ -60,7 +61,6 @@ import ( "github.com/devtron-labs/devtron/client/argocdServer/session" "github.com/devtron-labs/devtron/client/dashboard" "github.com/devtron-labs/devtron/client/telemetry" - "github.com/devtron-labs/devtron/client/telemetry/posthog" "github.com/devtron-labs/devtron/internal/sql/repository" app2 "github.com/devtron-labs/devtron/internal/sql/repository/app" "github.com/devtron-labs/devtron/internal/sql/repository/appStatus" @@ -133,7 +133,7 @@ func InitializeApp() (*App, error) { util.NewSugardLogger, util.IntValidator, util2.GetACDAuthConfig, - posthog.NewPosthogClient, + posthogTelemetry.NewPosthogClient, ucid.WireSet, delete2.NewDeleteServiceImpl, gitMaterial.GitMaterialWireSet, diff --git a/cmd/external-app/wire_gen.go b/cmd/external-app/wire_gen.go index f1d6763cc8..0190d93983 100644 --- a/cmd/external-app/wire_gen.go +++ b/cmd/external-app/wire_gen.go @@ -52,7 +52,7 @@ import ( "github.com/devtron-labs/devtron/client/argocdServer/repoCredsK8sClient" "github.com/devtron-labs/devtron/client/dashboard" "github.com/devtron-labs/devtron/client/telemetry" - "github.com/devtron-labs/devtron/client/telemetry/posthog" + posthog "github.com/devtron-labs/common-lib/telemetry" repository5 "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/appStatus" diff --git a/go.mod b/go.mod index aa0d1cdcd6..7631bd384e 100644 --- a/go.mod +++ b/go.mod @@ -307,8 +307,8 @@ require ( replace ( github.com/argoproj/argo-workflows/v3 => github.com/devtron-labs/argo-workflows/v3 v3.5.13 - github.com/devtron-labs/authenticator => github.com/devtron-labs/devtron-services/authenticator v0.0.0-20250403171407-721f466f49ce - github.com/devtron-labs/common-lib => github.com/devtron-labs/devtron-services/common-lib v0.0.0-20250403171407-721f466f49ce + github.com/devtron-labs/authenticator => github.com/devtron-labs/devtron-services/authenticator v0.0.0-20250407184841-36bb51a7d2fa + github.com/devtron-labs/common-lib => github.com/devtron-labs/devtron-services/common-lib v0.0.0-20250407184841-36bb51a7d2fa github.com/go-check/check => github.com/go-check/check v0.0.0-20180628173108-788fd7840127 github.com/googleapis/gnostic => github.com/googleapis/gnostic v0.5.5 k8s.io/api => k8s.io/api v0.29.7 diff --git a/go.sum b/go.sum index 2a9b9bb3e6..22e91ce7b6 100644 --- a/go.sum +++ b/go.sum @@ -829,10 +829,10 @@ github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc h1:VRRKCwnzq github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/devtron-labs/argo-workflows/v3 v3.5.13 h1:3pINq0gXOSeTw2z/vYe+j80lRpSN5Rp/8mfQORh8SmU= github.com/devtron-labs/argo-workflows/v3 v3.5.13/go.mod h1:/vqxcovDPT4zqr4DjR5v7CF8ggpY1l3TSa2CIG3jmjA= -github.com/devtron-labs/devtron-services/authenticator v0.0.0-20250403171407-721f466f49ce h1:A4+SH98TFhHo/cUWi9CE3rbw0TjU6uH7cfOFOsmQrqk= -github.com/devtron-labs/devtron-services/authenticator v0.0.0-20250403171407-721f466f49ce/go.mod h1:FfaLDXN1ZXxyRpnskBqVIYkpkWDCzBmDgIO9xqLnxdQ= -github.com/devtron-labs/devtron-services/common-lib v0.0.0-20250403171407-721f466f49ce h1:hp5p/mPLsoCyqM51b88Uu8AgCTn0K2bwKEsB5Fy2C24= -github.com/devtron-labs/devtron-services/common-lib v0.0.0-20250403171407-721f466f49ce/go.mod h1:zkNShlkcHxsmnL0gKNbs0uyRL8lZonGKr5Km63uTLI0= +github.com/devtron-labs/devtron-services/authenticator v0.0.0-20250407184841-36bb51a7d2fa h1:NsMmPjQXq+Adr4mS22rTikyS3RhP8ARNgNVR9zFWD74= +github.com/devtron-labs/devtron-services/authenticator v0.0.0-20250407184841-36bb51a7d2fa/go.mod h1:FfaLDXN1ZXxyRpnskBqVIYkpkWDCzBmDgIO9xqLnxdQ= +github.com/devtron-labs/devtron-services/common-lib v0.0.0-20250407184841-36bb51a7d2fa h1:vrNxj/SMaypXKcIQqoN1tOXZdIeYi1mz6Htp5MPnASw= +github.com/devtron-labs/devtron-services/common-lib v0.0.0-20250407184841-36bb51a7d2fa/go.mod h1:zkNShlkcHxsmnL0gKNbs0uyRL8lZonGKr5Km63uTLI0= github.com/devtron-labs/go-bitbucket v0.9.60-beta h1:VEx1jvDgdtDPS6A1uUFoaEi0l1/oLhbr+90xOwr6sDU= github.com/devtron-labs/go-bitbucket v0.9.60-beta/go.mod h1:GnuiCesvh8xyHeMCb+twm8lBR/kQzJYSKL28ZfObp1Y= github.com/devtron-labs/protos v0.0.3-0.20250323220609-ecf8a0f7305e h1:U6UdYbW8a7xn5IzFPd8cywjVVPfutGJCudjePAfL/Hs= diff --git a/internal/sql/repository/pipelineConfig/CdWorfkflowRepository.go b/internal/sql/repository/pipelineConfig/CdWorfkflowRepository.go index 9aa3eeaa28..6d7a9455ba 100644 --- a/internal/sql/repository/pipelineConfig/CdWorfkflowRepository.go +++ b/internal/sql/repository/pipelineConfig/CdWorfkflowRepository.go @@ -458,7 +458,6 @@ func (impl *CdWorkflowRepositoryImpl) SaveWorkFlowRunnerWithTx(wfr *CdWorkflowRu } func (impl *CdWorkflowRepositoryImpl) UpdateWorkFlowRunnerWithTx(wfr *CdWorkflowRunner, tx *pg.Tx) error { - wfr.Message = util.GetTruncatedMessage(wfr.Message, 1000) err := tx.Update(wfr) return err } diff --git a/pkg/pipeline/CdHandler.go b/pkg/pipeline/CdHandler.go index 4889e361b6..f277f3de72 100644 --- a/pkg/pipeline/CdHandler.go +++ b/pkg/pipeline/CdHandler.go @@ -291,10 +291,6 @@ func (impl *CdHandlerImpl) UpdateWorkflow(workflowStatus eventProcessorBean.CiCd if impl.stateChanged(status, podStatus, message, workflowStatus.FinishedAt.Time, savedWorkflow) { if !slices.Contains(cdWorkflowBean.WfrTerminalStatusList, savedWorkflow.PodStatus) { savedWorkflow.Message = message - // NOTE: we are doing this to fix where a pre-cd / post-cd workflow message becomes larger than 1000, and in db we had set the charter limit to 1000 - if len(message) > 1000 { - savedWorkflow.Message = message[:1000] - } if !slices.Contains(cdWorkflowBean.WfrTerminalStatusList, savedWorkflow.Status) { savedWorkflow.FinishedOn = workflowStatus.FinishedAt.Time } diff --git a/pkg/pipeline/bean/WorkflowTemplate.go b/pkg/pipeline/bean/WorkflowTemplate.go index abc8be4588..dcab419b5e 100644 --- a/pkg/pipeline/bean/WorkflowTemplate.go +++ b/pkg/pipeline/bean/WorkflowTemplate.go @@ -81,9 +81,9 @@ func (workflowTemplate *WorkflowTemplate) SetActiveDeadlineSeconds(timeout int64 func (workflowTemplate *WorkflowTemplate) CreateObjectMetadata() *v12.ObjectMeta { workflowLabels := map[string]string{ - WorkflowGenerateNamePrefix: workflowTemplate.WorkflowNamePrefix, - informerBean.WorkflowTypeLabelKey: workflowTemplate.WorkflowType, - informerBean.DevtronAdministratorInstanceLabelKey: workflowTemplate.DevtronInstanceUID, + WorkflowGenerateNamePrefix: workflowTemplate.WorkflowNamePrefix, + informerBean.WorkflowTypeLabelKey: workflowTemplate.WorkflowType, + informerBean.DevtronOwnerInstanceLabelKey: workflowTemplate.DevtronInstanceUID, } switch workflowTemplate.WorkflowType { case CI_WORKFLOW_NAME: diff --git a/pkg/pipeline/executors/WorkflowUtils.go b/pkg/pipeline/executors/WorkflowUtils.go index c08bfd8efd..bbf7439660 100644 --- a/pkg/pipeline/executors/WorkflowUtils.go +++ b/pkg/pipeline/executors/WorkflowUtils.go @@ -298,10 +298,10 @@ func CheckIfReTriggerRequired(status, message, workflowRunnerStatus string) bool func GetWorkflowLabelsForSystemExecutor(workflowTemplate bean.WorkflowTemplate) map[string]string { return map[string]string{ - DEVTRON_WORKFLOW_LABEL_KEY: DEVTRON_WORKFLOW_LABEL_VALUE, - bean.DevtronLabelPurposeKey: bean.DevtronLabelPurposeWorkflow, - informerBean.WorkflowTypeLabelKey: workflowTemplate.WorkflowType, - bean.WorkflowGenerateNamePrefix: workflowTemplate.WorkflowNamePrefix, - informerBean.DevtronAdministratorInstanceLabelKey: workflowTemplate.DevtronInstanceUID, + DEVTRON_WORKFLOW_LABEL_KEY: DEVTRON_WORKFLOW_LABEL_VALUE, + bean.DevtronLabelPurposeKey: bean.DevtronLabelPurposeWorkflow, + informerBean.WorkflowTypeLabelKey: workflowTemplate.WorkflowType, + bean.WorkflowGenerateNamePrefix: workflowTemplate.WorkflowNamePrefix, + informerBean.DevtronOwnerInstanceLabelKey: workflowTemplate.DevtronInstanceUID, } } diff --git a/scripts/sql/32703300_workflow_message.down.sql b/scripts/sql/32703300_workflow_message.down.sql new file mode 100644 index 0000000000..7b794d76d6 --- /dev/null +++ b/scripts/sql/32703300_workflow_message.down.sql @@ -0,0 +1 @@ +-- Migration down is not applicable here as cd_workflow_runner.message has moved to higher DataType \ No newline at end of file diff --git a/scripts/sql/32703300_workflow_message.up.sql b/scripts/sql/32703300_workflow_message.up.sql new file mode 100644 index 0000000000..bc3083ee77 --- /dev/null +++ b/scripts/sql/32703300_workflow_message.up.sql @@ -0,0 +1,11 @@ +BEGIN; + +-- cd_workflow_runner.message has a limit of 1000 characters. migrating to +ALTER TABLE "public"."cd_workflow_runner" + ALTER COLUMN "message" TYPE TEXT; + +-- ci_workflow.message has a limit of 250 characters. migrating to +ALTER TABLE "public"."ci_workflow" + ALTER COLUMN "message" TYPE TEXT; + +COMMIT; \ No newline at end of file diff --git a/vendor/github.com/devtron-labs/common-lib/informer/bean.go b/vendor/github.com/devtron-labs/common-lib/informer/bean.go index e3b0304328..38aed85afc 100644 --- a/vendor/github.com/devtron-labs/common-lib/informer/bean.go +++ b/vendor/github.com/devtron-labs/common-lib/informer/bean.go @@ -32,7 +32,7 @@ const ( ) const ( - DevtronAdministratorInstanceLabelKey = "devtron.ai/administrator-instance" + DevtronOwnerInstanceLabelKey = "devtron.ai/owner-instance" ) const ( diff --git a/vendor/github.com/devtron-labs/common-lib/telemetry/PosthogClient.go b/vendor/github.com/devtron-labs/common-lib/telemetry/PosthogClient.go new file mode 100644 index 0000000000..79a8c72f88 --- /dev/null +++ b/vendor/github.com/devtron-labs/common-lib/telemetry/PosthogClient.go @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2020-2024. Devtron Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package telemetry + +import ( + "context" + "encoding/base64" + "encoding/json" + "go.opentelemetry.io/otel" + "time" + + "github.com/devtron-labs/common-lib/utils/http" + "github.com/patrickmn/go-cache" + "github.com/posthog/posthog-go" + "go.uber.org/zap" +) + +type PosthogClient struct { + Client posthog.Client + cache *cache.Cache +} + +func (p *PosthogClient) GetCache() *cache.Cache { + return p.cache +} + +func NewPosthogClient(logger *zap.SugaredLogger) (*PosthogClient, error) { + if PosthogApiKey == "" { + encodedApiKey, apiKey, posthogUrl, err := getPosthogApiKey(context.Background(), TelemetryApiKeyEndpoint, logger) + if err != nil { + logger.Errorw("exception caught while getting api key", "err", err) + } else { + PosthogApiKey = apiKey + PosthogEncodedApiKey = encodedApiKey + PosthogEndpoint = posthogUrl + } + } + + client, err := posthog.NewWithConfig(PosthogApiKey, posthog.Config{Endpoint: PosthogEndpoint}) + //defer client.Close() + if err != nil { + logger.Errorw("exception caught while creating posthog client", "err", err) + } + d := time.Duration(CacheExpiry) + c := cache.New(d*time.Minute, d*time.Minute) + pgClient := &PosthogClient{ + Client: client, + cache: c, + } + return pgClient, nil +} + +func getPosthogApiKey(ctx context.Context, encodedPosthogApiKeyUrl string, logger *zap.SugaredLogger) (string, string, string, error) { + newCtx, span := otel.Tracer("common").Start(ctx, "telemetry.getPosthogApiKey") + defer span.End() + decodedPosthogApiKeyUrl, err := base64.StdEncoding.DecodeString(encodedPosthogApiKeyUrl) + if err != nil { + logger.Errorw("error fetching posthog api key, decode error", "err", err) + return "", "", "", err + } + apiKeyUrl := string(decodedPosthogApiKeyUrl) + response, err := http.HttpRequest(newCtx, apiKeyUrl) + if err != nil { + logger.Errorw("error fetching posthog api key, http call", "err", err) + return "", "", "", err + } + posthogInfo := response["result"] + posthogInfoByte, err := json.Marshal(posthogInfo) + if err != nil { + logger.Errorw("error in fetched posthog info, http call", "err", err) + return "", "", "", err + } + var datamap map[string]string + if err = json.Unmarshal(posthogInfoByte, &datamap); err != nil { + logger.Errorw("error while unmarshal data", "err", err) + return "", "", "", err + } + encodedApiKey := datamap[ResponseApiKey] + posthogUrl := datamap[ResponseUrlKey] + apiKey, err := base64.StdEncoding.DecodeString(encodedApiKey) + if err != nil { + return "", "", "", err + } + return encodedApiKey, string(apiKey), posthogUrl, err +} diff --git a/vendor/github.com/devtron-labs/common-lib/telemetry/bean.go b/vendor/github.com/devtron-labs/common-lib/telemetry/bean.go new file mode 100644 index 0000000000..b85621d0f3 --- /dev/null +++ b/vendor/github.com/devtron-labs/common-lib/telemetry/bean.go @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2024. Devtron Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package telemetry + +var ( + PosthogApiKey string = "" + PosthogEndpoint string = "https://app.posthog.com" + SummaryCronExpr string = "0 0 * * *" // Run once a day, midnight + HeartbeatCronExpr string = "0 0/6 * * *" + CacheExpiry int = 1440 + PosthogEncodedApiKey string = "" + IsOptOut bool = false +) + +const ( + TelemetryApiKeyEndpoint string = "aHR0cHM6Ly90ZWxlbWV0cnkuZGV2dHJvbi5haS9kZXZ0cm9uL3RlbGVtZXRyeS9wb3N0aG9nSW5mbw==" + TelemetryOptOutApiBaseUrl string = "aHR0cHM6Ly90ZWxlbWV0cnkuZGV2dHJvbi5haS9kZXZ0cm9uL3RlbGVtZXRyeS9vcHQtb3V0" + ResponseApiKey string = "PosthogApiKey" + ResponseUrlKey string = "PosthogEndpoint" +) diff --git a/vendor/github.com/devtron-labs/common-lib/utils/http/HttpUtil.go b/vendor/github.com/devtron-labs/common-lib/utils/http/HttpUtil.go index 933b97f4f9..9f8524e489 100644 --- a/vendor/github.com/devtron-labs/common-lib/utils/http/HttpUtil.go +++ b/vendor/github.com/devtron-labs/common-lib/utils/http/HttpUtil.go @@ -17,11 +17,13 @@ package http import ( + "context" "crypto/tls" "crypto/x509" "encoding/json" "github.com/pkg/errors" - "io/ioutil" + "go.opentelemetry.io/otel" + "io" "net/http" "os" ) @@ -83,8 +85,10 @@ func CertPoolFromFile(filename string) (*x509.CertPool, error) { return cp, nil } -func HttpRequest(url string) (map[string]interface{}, error) { - req, err := http.NewRequest(http.MethodGet, url, nil) +func HttpRequest(ctx context.Context, url string) (map[string]interface{}, error) { + newCtx, span := otel.Tracer("common").Start(ctx, "http.HttpRequest") + defer span.End() + req, err := http.NewRequestWithContext(newCtx, http.MethodGet, url, nil) if err != nil { return nil, err } @@ -95,7 +99,7 @@ func HttpRequest(url string) (map[string]interface{}, error) { return nil, err } if res.StatusCode >= 200 && res.StatusCode <= 299 { - resBody, err := ioutil.ReadAll(res.Body) + resBody, err := io.ReadAll(res.Body) if err != nil { return nil, err } diff --git a/vendor/modules.txt b/vendor/modules.txt index ae3dc39f9b..2e26f2c11c 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -472,7 +472,7 @@ github.com/davecgh/go-spew/spew # github.com/deckarep/golang-set v1.8.0 ## explicit; go 1.17 github.com/deckarep/golang-set -# github.com/devtron-labs/authenticator v0.4.35-0.20240809073103-6e11da8083f8 => github.com/devtron-labs/devtron-services/authenticator v0.0.0-20250403171407-721f466f49ce +# github.com/devtron-labs/authenticator v0.4.35-0.20240809073103-6e11da8083f8 => github.com/devtron-labs/devtron-services/authenticator v0.0.0-20250407184841-36bb51a7d2fa ## explicit; go 1.21 github.com/devtron-labs/authenticator/apiToken github.com/devtron-labs/authenticator/client @@ -480,7 +480,7 @@ github.com/devtron-labs/authenticator/jwt github.com/devtron-labs/authenticator/middleware github.com/devtron-labs/authenticator/oidc github.com/devtron-labs/authenticator/password -# github.com/devtron-labs/common-lib v0.18.1-0.20241001061923-eda545dc839e => github.com/devtron-labs/devtron-services/common-lib v0.0.0-20250403171407-721f466f49ce +# github.com/devtron-labs/common-lib v0.18.1-0.20241001061923-eda545dc839e => github.com/devtron-labs/devtron-services/common-lib v0.0.0-20250407184841-36bb51a7d2fa ## explicit; go 1.21 github.com/devtron-labs/common-lib/async github.com/devtron-labs/common-lib/blob-storage @@ -497,6 +497,7 @@ github.com/devtron-labs/common-lib/middlewares github.com/devtron-labs/common-lib/pubsub-lib github.com/devtron-labs/common-lib/pubsub-lib/metrics github.com/devtron-labs/common-lib/pubsub-lib/model +github.com/devtron-labs/common-lib/telemetry github.com/devtron-labs/common-lib/utils github.com/devtron-labs/common-lib/utils/bean github.com/devtron-labs/common-lib/utils/grpc @@ -2352,8 +2353,8 @@ xorm.io/xorm/names xorm.io/xorm/schemas xorm.io/xorm/tags # github.com/argoproj/argo-workflows/v3 => github.com/devtron-labs/argo-workflows/v3 v3.5.13 -# github.com/devtron-labs/authenticator => github.com/devtron-labs/devtron-services/authenticator v0.0.0-20250403171407-721f466f49ce -# github.com/devtron-labs/common-lib => github.com/devtron-labs/devtron-services/common-lib v0.0.0-20250403171407-721f466f49ce +# github.com/devtron-labs/authenticator => github.com/devtron-labs/devtron-services/authenticator v0.0.0-20250407184841-36bb51a7d2fa +# github.com/devtron-labs/common-lib => github.com/devtron-labs/devtron-services/common-lib v0.0.0-20250407184841-36bb51a7d2fa # github.com/go-check/check => github.com/go-check/check v0.0.0-20180628173108-788fd7840127 # github.com/googleapis/gnostic => github.com/googleapis/gnostic v0.5.5 # k8s.io/api => k8s.io/api v0.29.7 diff --git a/wire_gen.go b/wire_gen.go index b9702bc9da..d5261faa8e 100644 --- a/wire_gen.go +++ b/wire_gen.go @@ -12,6 +12,7 @@ import ( "github.com/devtron-labs/authenticator/middleware" "github.com/devtron-labs/common-lib/cloud-provider-identifier" "github.com/devtron-labs/common-lib/pubsub-lib" + "github.com/devtron-labs/common-lib/telemetry" "github.com/devtron-labs/common-lib/utils/grpc" "github.com/devtron-labs/common-lib/utils/k8s" apiToken2 "github.com/devtron-labs/devtron/api/apiToken" @@ -90,8 +91,7 @@ import ( "github.com/devtron-labs/devtron/client/grafana" "github.com/devtron-labs/devtron/client/lens" "github.com/devtron-labs/devtron/client/proxy" - "github.com/devtron-labs/devtron/client/telemetry" - "github.com/devtron-labs/devtron/client/telemetry/posthog" + telemetry2 "github.com/devtron-labs/devtron/client/telemetry" 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/appStatus" @@ -929,12 +929,12 @@ func InitializeApp() (*App, error) { ssoLoginServiceImpl := sso.NewSSOLoginServiceImpl(sugaredLogger, ssoLoginRepositoryImpl, k8sServiceImpl, environmentVariables, userAuthOidcHelperImpl) ssoLoginRestHandlerImpl := sso2.NewSsoLoginRestHandlerImpl(validate, sugaredLogger, enforcerImpl, userServiceImpl, ssoLoginServiceImpl) ssoLoginRouterImpl := sso2.NewSsoLoginRouterImpl(ssoLoginRestHandlerImpl) - posthogClient, err := posthog.NewPosthogClient(sugaredLogger) + posthogClient, err := telemetry.NewPosthogClient(sugaredLogger) if err != nil { return nil, err } providerIdentifierServiceImpl := providerIdentifier.NewProviderIdentifierServiceImpl(sugaredLogger) - telemetryEventClientImplExtended, err := telemetry.NewTelemetryEventClientImplExtended(sugaredLogger, httpClient, clusterServiceImplExtended, k8sServiceImpl, acdAuthConfig, environmentServiceImpl, userServiceImpl, appListingRepositoryImpl, posthogClient, serviceImpl, ciPipelineConfigReadServiceImpl, pipelineRepositoryImpl, gitProviderRepositoryImpl, attributesRepositoryImpl, ssoLoginServiceImpl, appRepositoryImpl, ciWorkflowRepositoryImpl, cdWorkflowRepositoryImpl, dockerArtifactStoreRepositoryImpl, gitMaterialReadServiceImpl, ciTemplateRepositoryImpl, chartRepositoryImpl, userAuditServiceImpl, ciBuildConfigServiceImpl, moduleRepositoryImpl, serverDataStoreServerDataStore, helmAppClientImpl, installedAppReadServiceImpl, userAttributesRepositoryImpl, providerIdentifierServiceImpl, cronLoggerImpl, gitOpsConfigReadServiceImpl) + telemetryEventClientImplExtended, err := telemetry2.NewTelemetryEventClientImplExtended(sugaredLogger, httpClient, clusterServiceImplExtended, k8sServiceImpl, acdAuthConfig, environmentServiceImpl, userServiceImpl, appListingRepositoryImpl, posthogClient, serviceImpl, ciPipelineConfigReadServiceImpl, pipelineRepositoryImpl, gitProviderRepositoryImpl, attributesRepositoryImpl, ssoLoginServiceImpl, appRepositoryImpl, ciWorkflowRepositoryImpl, cdWorkflowRepositoryImpl, dockerArtifactStoreRepositoryImpl, gitMaterialReadServiceImpl, ciTemplateRepositoryImpl, chartRepositoryImpl, userAuditServiceImpl, ciBuildConfigServiceImpl, moduleRepositoryImpl, serverDataStoreServerDataStore, helmAppClientImpl, installedAppReadServiceImpl, userAttributesRepositoryImpl, providerIdentifierServiceImpl, cronLoggerImpl, gitOpsConfigReadServiceImpl) if err != nil { return nil, err } From ae11bb21674b1da0b90a5daf5c1332b5d1f51deb Mon Sep 17 00:00:00 2001 From: Ash-exp Date: Tue, 8 Apr 2025 00:45:56 +0530 Subject: [PATCH 17/19] chore: kubewatch const renamed --- pkg/eventProcessor/bean/workflowEventBean.go | 2 +- .../in/WorkflowEventProcessorService.go | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pkg/eventProcessor/bean/workflowEventBean.go b/pkg/eventProcessor/bean/workflowEventBean.go index 3f401845c4..ad150af539 100644 --- a/pkg/eventProcessor/bean/workflowEventBean.go +++ b/pkg/eventProcessor/bean/workflowEventBean.go @@ -117,7 +117,7 @@ type DevtronAppReleaseContextType struct { } type CiCdStatus struct { - DevtronAdministratorInstance string `json:"devtronAdministratorInstance"` + DevtronOwnerInstance string `json:"devtronOwnerInstance"` *v1alpha1.WorkflowStatus } diff --git a/pkg/eventProcessor/in/WorkflowEventProcessorService.go b/pkg/eventProcessor/in/WorkflowEventProcessorService.go index 9816c31920..fd90d10631 100644 --- a/pkg/eventProcessor/in/WorkflowEventProcessorService.go +++ b/pkg/eventProcessor/in/WorkflowEventProcessorService.go @@ -398,14 +398,14 @@ func (impl *WorkflowEventProcessorImpl) SubscribeCIWorkflowStatusUpdate() error impl.logger.Errorw("error while unmarshalling wf status update", "err", err, "msg", msg.Data) return } - if len(wfStatus.DevtronAdministratorInstance) != 0 { + if len(wfStatus.DevtronOwnerInstance) != 0 { devtronUCID, _, err := impl.ucid.GetUCIDWithOutCache() if err != nil { impl.logger.Errorw("error in getting UCID", "err", err) return } - if wfStatus.DevtronAdministratorInstance != devtronUCID { - impl.logger.Warnw("mis match in UCID. skipping...", "devtronAdministratorInstance", wfStatus.DevtronAdministratorInstance, "devtronUCID", devtronUCID) + if wfStatus.DevtronOwnerInstance != devtronUCID { + impl.logger.Warnw("mis match in UCID. skipping...", "devtronAdministratorInstance", wfStatus.DevtronOwnerInstance, "devtronUCID", devtronUCID) return } } @@ -457,14 +457,14 @@ func (impl *WorkflowEventProcessorImpl) SubscribeCDWorkflowStatusUpdate() error impl.logger.Error("Error while unmarshalling wfStatus json object", "error", err) return } - if len(wfStatus.DevtronAdministratorInstance) != 0 { + if len(wfStatus.DevtronOwnerInstance) != 0 { devtronUCID, _, err := impl.ucid.GetUCIDWithOutCache() if err != nil { impl.logger.Errorw("error in getting UCID", "err", err) return } - if wfStatus.DevtronAdministratorInstance != devtronUCID { - impl.logger.Warnw("mis match in UCID. skipping...", "devtronAdministratorInstance", wfStatus.DevtronAdministratorInstance, "devtronUCID", devtronUCID) + if wfStatus.DevtronOwnerInstance != devtronUCID { + impl.logger.Warnw("mis match in UCID. skipping...", "devtronAdministratorInstance", wfStatus.DevtronOwnerInstance, "devtronUCID", devtronUCID) return } } From 13a26e15dc973dc72222a533b01cd5ce21e30dd6 Mon Sep 17 00:00:00 2001 From: Ash-exp Date: Tue, 8 Apr 2025 01:07:26 +0530 Subject: [PATCH 18/19] chore: removed posthug module --- client/telemetry/posthog/PosthogClient.go | 99 ----------------------- client/telemetry/posthog/bean.go | 34 -------- cmd/external-app/wire_gen.go | 10 +-- 3 files changed, 5 insertions(+), 138 deletions(-) delete mode 100644 client/telemetry/posthog/PosthogClient.go delete mode 100644 client/telemetry/posthog/bean.go diff --git a/client/telemetry/posthog/PosthogClient.go b/client/telemetry/posthog/PosthogClient.go deleted file mode 100644 index 7e6213864f..0000000000 --- a/client/telemetry/posthog/PosthogClient.go +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2020-2024. Devtron Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package posthog - -import ( - "context" - "encoding/base64" - "encoding/json" - "go.opentelemetry.io/otel" - "time" - - "github.com/devtron-labs/devtron/util" - "github.com/patrickmn/go-cache" - "github.com/posthog/posthog-go" - "go.uber.org/zap" -) - -type PosthogClient struct { - Client posthog.Client - cache *cache.Cache -} - -func (p *PosthogClient) GetCache() *cache.Cache { - return p.cache -} - -func NewPosthogClient(logger *zap.SugaredLogger) (*PosthogClient, error) { - if PosthogApiKey == "" { - encodedApiKey, apiKey, posthogUrl, err := getPosthogApiKey(context.Background(), TelemetryApiKeyEndpoint, logger) - if err != nil { - logger.Errorw("exception caught while getting api key", "err", err) - } else { - PosthogApiKey = apiKey - PosthogEncodedApiKey = encodedApiKey - PosthogEndpoint = posthogUrl - } - } - - client, err := posthog.NewWithConfig(PosthogApiKey, posthog.Config{Endpoint: PosthogEndpoint}) - //defer client.Close() - if err != nil { - logger.Errorw("exception caught while creating posthog client", "err", err) - } - d := time.Duration(CacheExpiry) - c := cache.New(d*time.Minute, d*time.Minute) - pgClient := &PosthogClient{ - Client: client, - cache: c, - } - return pgClient, nil -} - -func getPosthogApiKey(ctx context.Context, encodedPosthogApiKeyUrl string, logger *zap.SugaredLogger) (string, string, string, error) { - newCtx, span := otel.Tracer("orchestrator").Start(ctx, "telemetry.getPosthogApiKey") - defer span.End() - decodedPosthogApiKeyUrl, err := base64.StdEncoding.DecodeString(encodedPosthogApiKeyUrl) - if err != nil { - logger.Errorw("error fetching posthog api key, decode error", "err", err) - return "", "", "", err - } - apiKeyUrl := string(decodedPosthogApiKeyUrl) - response, err := util.HttpRequest(newCtx, apiKeyUrl) - if err != nil { - logger.Errorw("error fetching posthog api key, http call", "err", err) - return "", "", "", err - } - posthogInfo := response["result"] - posthogInfoByte, err := json.Marshal(posthogInfo) - if err != nil { - logger.Errorw("error in fetched posthog info, http call", "err", err) - return "", "", "", err - } - var datamap map[string]string - if err = json.Unmarshal(posthogInfoByte, &datamap); err != nil { - logger.Errorw("error while unmarshal data", "err", err) - return "", "", "", err - } - encodedApiKey := datamap[ResponseApiKey] - posthogUrl := datamap[ResponseUrlKey] - apiKey, err := base64.StdEncoding.DecodeString(encodedApiKey) - if err != nil { - return "", "", "", err - } - return encodedApiKey, string(apiKey), posthogUrl, err -} diff --git a/client/telemetry/posthog/bean.go b/client/telemetry/posthog/bean.go deleted file mode 100644 index 8910b7d8fe..0000000000 --- a/client/telemetry/posthog/bean.go +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2024. Devtron Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package posthog - -var ( - PosthogApiKey string = "" - PosthogEndpoint string = "https://app.posthog.com" - SummaryCronExpr string = "0 0 * * *" // Run once a day, midnight - HeartbeatCronExpr string = "0 0/6 * * *" - CacheExpiry int = 1440 - PosthogEncodedApiKey string = "" - IsOptOut bool = false -) - -const ( - TelemetryApiKeyEndpoint string = "aHR0cHM6Ly90ZWxlbWV0cnkuZGV2dHJvbi5haS9kZXZ0cm9uL3RlbGVtZXRyeS9wb3N0aG9nSW5mbw==" - TelemetryOptOutApiBaseUrl string = "aHR0cHM6Ly90ZWxlbWV0cnkuZGV2dHJvbi5haS9kZXZ0cm9uL3RlbGVtZXRyeS9vcHQtb3V0" - ResponseApiKey string = "PosthogApiKey" - ResponseUrlKey string = "PosthogEndpoint" -) diff --git a/cmd/external-app/wire_gen.go b/cmd/external-app/wire_gen.go index 0190d93983..14934dea14 100644 --- a/cmd/external-app/wire_gen.go +++ b/cmd/external-app/wire_gen.go @@ -11,6 +11,7 @@ import ( "github.com/devtron-labs/authenticator/client" "github.com/devtron-labs/authenticator/middleware" "github.com/devtron-labs/common-lib/cloud-provider-identifier" + "github.com/devtron-labs/common-lib/telemetry" "github.com/devtron-labs/common-lib/utils/grpc" "github.com/devtron-labs/common-lib/utils/k8s" apiToken2 "github.com/devtron-labs/devtron/api/apiToken" @@ -51,8 +52,7 @@ import ( "github.com/devtron-labs/devtron/client/argocdServer/config" "github.com/devtron-labs/devtron/client/argocdServer/repoCredsK8sClient" "github.com/devtron-labs/devtron/client/dashboard" - "github.com/devtron-labs/devtron/client/telemetry" - posthog "github.com/devtron-labs/common-lib/telemetry" + telemetry2 "github.com/devtron-labs/devtron/client/telemetry" repository5 "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/appStatus" @@ -386,13 +386,14 @@ func InitializeApp() (*App, error) { chartProviderRouterImpl := chartProvider2.NewChartProviderRouterImpl(chartProviderRestHandlerImpl) dockerRegRestHandlerImpl := restHandler.NewDockerRegRestHandlerImpl(dockerRegistryConfigImpl, sugaredLogger, chartProviderServiceImpl, userServiceImpl, validate, enforcerImpl, teamServiceImpl, deleteServiceImpl) dockerRegRouterImpl := router.NewDockerRegRouterImpl(dockerRegRestHandlerImpl) - posthogClient, err := posthog.NewPosthogClient(sugaredLogger) + posthogClient, err := telemetry.NewPosthogClient(sugaredLogger) if err != nil { return nil, err } serviceImpl := ucid.NewServiceImpl(sugaredLogger, k8sServiceImpl, acdAuthConfig) providerIdentifierServiceImpl := providerIdentifier.NewProviderIdentifierServiceImpl(sugaredLogger) - telemetryEventClientImpl, err := telemetry.NewTelemetryEventClientImpl(sugaredLogger, httpClient, clusterServiceImpl, k8sServiceImpl, acdAuthConfig, userServiceImpl, attributesRepositoryImpl, ssoLoginServiceImpl, posthogClient, serviceImpl, moduleRepositoryImpl, serverDataStoreServerDataStore, userAuditServiceImpl, helmAppClientImpl, providerIdentifierServiceImpl, cronLoggerImpl, installedAppReadServiceEAImpl, environmentVariables) + userAttributesRepositoryImpl := repository5.NewUserAttributesRepositoryImpl(db) + telemetryEventClientImpl, err := telemetry2.NewTelemetryEventClientImpl(sugaredLogger, httpClient, clusterServiceImpl, k8sServiceImpl, acdAuthConfig, userServiceImpl, attributesRepositoryImpl, ssoLoginServiceImpl, posthogClient, serviceImpl, moduleRepositoryImpl, serverDataStoreServerDataStore, userAuditServiceImpl, helmAppClientImpl, providerIdentifierServiceImpl, cronLoggerImpl, installedAppReadServiceEAImpl, environmentVariables, userAttributesRepositoryImpl) if err != nil { return nil, err } @@ -449,7 +450,6 @@ func InitializeApp() (*App, error) { webhookHelmServiceImpl := webhookHelm.NewWebhookHelmServiceImpl(sugaredLogger, helmAppServiceImpl, clusterServiceImpl, chartRepositoryServiceImpl, attributesServiceImpl) webhookHelmRestHandlerImpl := webhookHelm2.NewWebhookHelmRestHandlerImpl(sugaredLogger, webhookHelmServiceImpl, userServiceImpl, enforcerImpl, validate) webhookHelmRouterImpl := webhookHelm2.NewWebhookHelmRouterImpl(webhookHelmRestHandlerImpl) - userAttributesRepositoryImpl := repository5.NewUserAttributesRepositoryImpl(db) userAttributesServiceImpl := attributes.NewUserAttributesServiceImpl(sugaredLogger, userAttributesRepositoryImpl) userAttributesRestHandlerImpl := restHandler.NewUserAttributesRestHandlerImpl(sugaredLogger, enforcerImpl, userServiceImpl, userAttributesServiceImpl) userAttributesRouterImpl := router.NewUserAttributesRouterImpl(userAttributesRestHandlerImpl) From 0204c134f82d3a0cea5c7ae87ca8abbbf6f4d6c6 Mon Sep 17 00:00:00 2001 From: Ash-exp Date: Tue, 8 Apr 2025 01:11:27 +0530 Subject: [PATCH 19/19] chore: ci/cd workflow message datatype updated --- pkg/pipeline/CiHandler.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pkg/pipeline/CiHandler.go b/pkg/pipeline/CiHandler.go index 8fb4a4b8da..043cd0aeeb 100644 --- a/pkg/pipeline/CiHandler.go +++ b/pkg/pipeline/CiHandler.go @@ -1202,10 +1202,6 @@ func (impl *CiHandlerImpl) UpdateWorkflow(workflowStatus eventProcessorBean.CiCd if impl.stateChanged(status, podStatus, message, workflowStatus.FinishedAt.Time, savedWorkflow) { if !slices.Contains(cdWorkflowBean.WfrTerminalStatusList, savedWorkflow.PodStatus) { savedWorkflow.Message = message - // NOTE: we are doing this for a quick fix where ci pending message become larger than 250 and in db we had set the charter limit to 250 - if len(message) > 250 { - savedWorkflow.Message = message[:250] - } if !slices.Contains(cdWorkflowBean.WfrTerminalStatusList, savedWorkflow.Status) { savedWorkflow.FinishedOn = workflowStatus.FinishedAt.Time }