Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
98c522b
Add support for merging `ReleaseOverride` into Helm values YAML durin…
prakash100198 Apr 23, 2026
56c0d41
Support reference chart-based manifest generation before saving the a…
prakash100198 Apr 24, 2026
b59a4c4
Merge pull request #6956 from devtron-labs/custom-chart-fix-oss
prakash100198 Apr 27, 2026
68fd036
Merge branch 'main' into main-sync-5-aug-2026-oss
prakash100198 Aug 5, 2026
5b3426e
sql script sync
prakash100198 Aug 5, 2026
2ba0ee2
Merge pull request #7008 from devtron-labs/main-sync-5-aug-2026-oss
prakash100198 Aug 5, 2026
5e19f16
looking up live usages of a scoped variable by name , so that users d…
prakash100198 Sep 2, 2026
2d0822b
perf: add ci_workflow status index (#7017)
bhupesh-devtron Sep 3, 2026
c868876
scope variable multi apps, envs fixes
prakash100198 Sep 9, 2026
d5d0d5c
Merge branch 'develop' into feat/prevent-scope-var-deletion-oss
prakash100198 Sep 12, 2026
805fe64
Merge pull request #7027 from devtron-labs/feat/prevent-scope-var-del…
prakash100198 Sep 15, 2026
ea5174e
feat: foreground (detach) delete of CD pipelines
Ash-exp Aug 3, 2026
f3b1f5f
chore: align migration sequence with enterprise
SATYAsasini Sep 15, 2026
34b39c5
Merge pull request #7037 from devtron-labs/feat-migration-foreground-…
SATYAsasini Sep 15, 2026
7b773ff
misc: main sync develop 16sep (#7039)
vivekanandan-devtron Sep 16, 2026
d413bb1
feat: scoped variable support for git repo and container repo (#7036)
bhupesh-devtron Sep 17, 2026
5e957a5
chore: update devtron-services deps to main for v0.47.0
Shivam-nagar23 Sep 21, 2026
9097ff6
Merge pull request #7044 from devtron-labs/chore/dep-update-rc-v0.47.0
Shivam-nagar23 Sep 21, 2026
2026102
Merge remote-tracking branch 'origin/main' into chore/sync-main-into-…
Shivam-nagar23 Sep 21, 2026
c83900e
chore(sql): resolve migration 36504600 collision and make argo/flux r…
Shivam-nagar23 Sep 21, 2026
fed83da
Merge pull request #7046 from devtron-labs/chore/sync-main-into-rc-v0…
Shivam-nagar23 Sep 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Wire.go
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,9 @@ func InitializeApp() (*App, error) {
pipeline.NewCiCdPipelineOrchestrator,
wire.Bind(new(pipeline.CiCdPipelineOrchestrator), new(*pipeline.CiCdPipelineOrchestratorImpl)),

pipeline.NewGitMaterialVariableSyncServiceImpl,
wire.Bind(new(pipeline.GitMaterialVariableSyncService), new(*pipeline.GitMaterialVariableSyncServiceImpl)),

// scoped variables start
variables.NewScopedVariableServiceImpl,
wire.Bind(new(variables.ScopedVariableService), new(*variables.ScopedVariableServiceImpl)),
Expand All @@ -367,6 +370,9 @@ func InitializeApp() (*App, error) {
variables.NewScopedVariableCMCSManagerImpl,
wire.Bind(new(variables.ScopedVariableCMCSManager), new(*variables.ScopedVariableCMCSManagerImpl)),

variables.NewRepoFieldVariableResolverImpl,
wire.Bind(new(variables.RepoFieldVariableResolver), new(*variables.RepoFieldVariableResolverImpl)),

// end

gitOpsConfig.NewDevtronAppGitOpConfigServiceImpl,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
bean2 "github.com/devtron-labs/devtron/pkg/build/pipeline/bean"
eventProcessorBean "github.com/devtron-labs/devtron/pkg/eventProcessor/bean"
constants2 "github.com/devtron-labs/devtron/pkg/pipeline/constants"
"github.com/devtron-labs/devtron/pkg/variables"
"github.com/devtron-labs/devtron/util/stringsUtil"
"golang.org/x/exp/maps"

Expand Down Expand Up @@ -124,7 +125,7 @@
}
createRequest.UserId = userId

handler.Logger.Infow("request payload, create ci config", "create request", createRequest)

Check failure on line 128 in api/restHandler/app/pipeline/configure/BuildPipelineRestHandler.go

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of duplicating this literal "create request" 3 times.

See more on https://sonarcloud.io/project/issues?id=devtron-labs_devtron&issues=AaDD4lxZUDJ0UtnK4X8k&open=AaDD4lxZUDJ0UtnK4X8k&pullRequest=7045

if !handler.validateRequestBody(w, createRequest, "create ci config") {
return
Expand Down Expand Up @@ -199,7 +200,7 @@
}
patchRequest.UserId = userId

handler.Logger.Debugw("update request ", "req", patchRequest)

Check failure on line 203 in api/restHandler/app/pipeline/configure/BuildPipelineRestHandler.go

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of duplicating this literal "update request " 3 times.

See more on https://sonarcloud.io/project/issues?id=devtron-labs_devtron&issues=AaDD4lxZUDJ0UtnK4X8g&open=AaDD4lxZUDJ0UtnK4X8g&pullRequest=7045

token := r.Header.Get("token")
_, authorized := handler.getAppAndCheckAuthForAction(w, patchRequest.AppId, token, casbin.ActionTrigger)
Expand All @@ -223,7 +224,7 @@
// Update the pipeline
err := handler.pipelineBuilder.PatchRegexCiPipeline(&patchRequest)
if err != nil {
handler.Logger.Errorw("service err, PatchCiPipelines", "err", err, "PatchCiPipelines", patchRequest)

Check failure on line 227 in api/restHandler/app/pipeline/configure/BuildPipelineRestHandler.go

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of duplicating this literal "service err, PatchCiPipelines" 4 times.

See more on https://sonarcloud.io/project/issues?id=devtron-labs_devtron&issues=AaDD4lxZUDJ0UtnK4X8h&open=AaDD4lxZUDJ0UtnK4X8h&pullRequest=7045
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
return
}
Expand Down Expand Up @@ -1000,7 +1001,7 @@
common.WriteJsonResp(w, nil, resp, http.StatusOK)
}

func (handler *PipelineConfigRestHandlerImpl) GetBuildHistory(w http.ResponseWriter, r *http.Request) {

Check failure on line 1004 in api/restHandler/app/pipeline/configure/BuildPipelineRestHandler.go

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this method to reduce its Cognitive Complexity from 19 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=devtron-labs_devtron&issues=AaDD4lxZUDJ0UtnK4X8l&open=AaDD4lxZUDJ0UtnK4X8l&pullRequest=7045
userId, err := handler.userAuthService.GetLoggedInUser(r)
if userId == 0 || err != nil {
common.HandleUnauthorized(w, r)
Expand All @@ -1027,7 +1028,7 @@
handler.Logger.Infow("request payload, GetBuildHistory", "pipelineId", pipelineId, "offset", offset)
ciPipeline, err := handler.ciPipelineRepository.FindById(pipelineId)
if err != nil {
handler.Logger.Errorw("service err, GetBuildHistory", "err", err, "pipelineId", pipelineId, "offset", offset)

Check failure on line 1031 in api/restHandler/app/pipeline/configure/BuildPipelineRestHandler.go

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of duplicating this literal "service err, GetBuildHistory" 3 times.

See more on https://sonarcloud.io/project/issues?id=devtron-labs_devtron&issues=AaDD4lxZUDJ0UtnK4X8f&open=AaDD4lxZUDJ0UtnK4X8f&pullRequest=7045
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
return
}
Expand Down Expand Up @@ -1363,6 +1364,11 @@
return
}
for _, gitMaterial := range createMaterialDto.Material {
// a @{{VAR_NAME}} reference isn't a real URL yet - skip the format check here,
// RepoFieldVariableResolver validates and resolves it before use
if variables.IsFullVariableReference(gitMaterial.Url) {
continue
}
validationResult, err := handler.ValidateGitMaterialUrl(gitMaterial.GitProviderId, gitMaterial.Url)
if err != nil {
handler.Logger.Errorw("service err, CreateMaterial", "err", err, "CreateMaterial", createMaterialDto)
Expand Down Expand Up @@ -1409,16 +1415,20 @@
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
return
}
validationResult, err := handler.ValidateGitMaterialUrl(updateMaterialDto.Material.GitProviderId, updateMaterialDto.Material.Url)
if err != nil {
handler.Logger.Errorw("service err, UpdateMaterial", "err", err, "UpdateMaterial", updateMaterialDto)
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
return
} else {
if !validationResult {
handler.Logger.Errorw("validation err, UpdateMaterial : invalid git material url", "err", err, "gitMaterialUrl", updateMaterialDto.Material.Url, "UpdateMaterial", updateMaterialDto)
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
// a @{{VAR_NAME}} reference isn't a real URL yet - skip the format check here,
// RepoFieldVariableResolver validates and resolves it before use
if !variables.IsFullVariableReference(updateMaterialDto.Material.Url) {
validationResult, err := handler.ValidateGitMaterialUrl(updateMaterialDto.Material.GitProviderId, updateMaterialDto.Material.Url)
if err != nil {
handler.Logger.Errorw("service err, UpdateMaterial", "err", err, "UpdateMaterial", updateMaterialDto)
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
return
} else {
if !validationResult {
handler.Logger.Errorw("validation err, UpdateMaterial : invalid git material url", "err", err, "gitMaterialUrl", updateMaterialDto.Material.Url, "UpdateMaterial", updateMaterialDto)
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
return
}
}
}
resourceObject := handler.enforcerUtil.GetAppRBACNameByAppId(updateMaterialDto.AppId)
Expand Down Expand Up @@ -1531,7 +1541,7 @@
vars := mux.Vars(r)
workflowId, err := strconv.Atoi(vars["workflowId"])
if err != nil {
handler.Logger.Errorw("request err, CancelWorkflow", "err", err, "workflowId", workflowId)

Check failure on line 1544 in api/restHandler/app/pipeline/configure/BuildPipelineRestHandler.go

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of duplicating this literal "request err, CancelWorkflow" 3 times.

See more on https://sonarcloud.io/project/issues?id=devtron-labs_devtron&issues=AaDD4lxZUDJ0UtnK4X8j&open=AaDD4lxZUDJ0UtnK4X8j&pullRequest=7045
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
return
}
Expand Down Expand Up @@ -1723,7 +1733,7 @@
if err != nil {
// response already written by ExtractIntPathParamWithContext
// common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
handler.Logger.Error("request err getting , FetchWorkflowDetails", "appId", appId, "err", err)

Check failure on line 1736 in api/restHandler/app/pipeline/configure/BuildPipelineRestHandler.go

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of duplicating this literal "request err getting , FetchWorkflowDetails" 3 times.

See more on https://sonarcloud.io/project/issues?id=devtron-labs_devtron&issues=AaDD4lxZUDJ0UtnK4X8i&open=AaDD4lxZUDJ0UtnK4X8i&pullRequest=7045
return
}
// pipelineId, err := strconv.Atoi(vars["pipelineId"])
Expand Down Expand Up @@ -1988,7 +1998,7 @@
common.WriteJsonResp(w, err, ciConf, http.StatusOK)
}

func (handler *PipelineConfigRestHandlerImpl) CreateUpdateImageTagging(w http.ResponseWriter, r *http.Request) {

Check failure on line 2001 in api/restHandler/app/pipeline/configure/BuildPipelineRestHandler.go

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this method to reduce its Cognitive Complexity from 22 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=devtron-labs_devtron&issues=AaDD4lxZUDJ0UtnK4X8m&open=AaDD4lxZUDJ0UtnK4X8m&pullRequest=7045
vars := mux.Vars(r)
token := r.Header.Get("token")
userId, err := handler.userAuthService.GetLoggedInUser(r)
Expand Down Expand Up @@ -2128,7 +2138,7 @@
common.WriteJsonResp(w, err, resp, http.StatusOK)
}

func (handler *PipelineConfigRestHandlerImpl) extractCipipelineMetaForImageTags(artifactId int) (externalCi bool, ciPipelineId int, appId int, err error) {

Check failure on line 2141 in api/restHandler/app/pipeline/configure/BuildPipelineRestHandler.go

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this method to reduce its Cognitive Complexity from 19 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=devtron-labs_devtron&issues=AaDD4lxZUDJ0UtnK4X8n&open=AaDD4lxZUDJ0UtnK4X8n&pullRequest=7045
externalCi = false
ciPipelineId = 0
appId = 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@
common.WriteJsonResp(w, err, createResp, http.StatusOK)
}

func (handler *PipelineConfigRestHandlerImpl) PatchCdPipeline(w http.ResponseWriter, r *http.Request) {

Check failure on line 282 in api/restHandler/app/pipeline/configure/DeploymentPipelineRestHandler.go

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this method to reduce its Cognitive Complexity from 27 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=devtron-labs_devtron&issues=AaDDz45tGoclI8RyInOS&open=AaDDz45tGoclI8RyInOS&pullRequest=7045
decoder := json.NewDecoder(r.Body)
userId, err := handler.userAuthService.GetLoggedInUser(r)
if userId == 0 || err != nil {
Expand All @@ -290,38 +290,61 @@
err = decoder.Decode(&cdPipeline)
cdPipeline.UserId = userId
if err != nil {
handler.Logger.Errorw("request err, PatchCdPipeline", "err", err, "payload", cdPipeline)

Check failure on line 293 in api/restHandler/app/pipeline/configure/DeploymentPipelineRestHandler.go

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of duplicating this literal "request err, PatchCdPipeline" 8 times.

See more on https://sonarcloud.io/project/issues?id=devtron-labs_devtron&issues=AaDD4l-gUDJ0UtnK4X8t&open=AaDD4l-gUDJ0UtnK4X8t&pullRequest=7045
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
return
}

v := r.URL.Query()
forceDelete := false
cascadeDelete := true
force := v.Get("force")
cascade := v.Get("cascade")
if len(force) > 0 && len(cascade) > 0 {
handler.Logger.Errorw("request err, PatchCdPipeline", "err", fmt.Errorf("cannot perform both cascade and force delete"), "payload", cdPipeline)
foreground := v.Get("foregroundDelete")
if len(force) > 0 && len(cascade) > 0 && len(foreground) > 0 {
err = fmt.Errorf("cannot perform force, cascade and foreground delete together")
handler.Logger.Errorw("request err, PatchCdPipeline", "err", err, "payload", cdPipeline)
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
return
} else if len(force) > 0 && len(cascade) > 0 {
err = fmt.Errorf("cannot perform both cascade and force delete")
handler.Logger.Errorw("request err, PatchCdPipeline", "err", err, "payload", cdPipeline)
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
return
} else if len(foreground) > 0 && len(cascade) > 0 {
err = fmt.Errorf("cannot perform both cascade and foreground delete")
handler.Logger.Errorw("request err, PatchCdPipeline", "err", err, "payload", cdPipeline)
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
return
} else if len(foreground) > 0 && len(force) > 0 {
err = fmt.Errorf("cannot perform both force and foreground delete")
handler.Logger.Errorw("request err, PatchCdPipeline", "err", err, "payload", cdPipeline)
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
return
}
if len(force) > 0 {
forceDelete, err = strconv.ParseBool(force)
if len(foreground) > 0 {
foregroundDelete, err := strconv.ParseBool(foreground)
if err != nil {
handler.Logger.Errorw("request err, PatchCdPipeline", "err", err, "payload", cdPipeline)
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
return
}
cdPipeline.ForegroundDelete = &foregroundDelete
} else if len(force) > 0 {
forceDelete, err := strconv.ParseBool(force)
if err != nil {
handler.Logger.Errorw("request err, PatchCdPipeline", "err", err, "payload", cdPipeline)
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
return
}
cdPipeline.ForceDelete = forceDelete
} else if len(cascade) > 0 {
cascadeDelete, err = strconv.ParseBool(cascade)
cascadeDelete, err := strconv.ParseBool(cascade)
if err != nil {
handler.Logger.Errorw("request err, PatchCdPipeline", "err", err, "payload", cdPipeline)
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
return
}
cdPipeline.NonCascadeDelete = !cascadeDelete
}
cdPipeline.ForceDelete = forceDelete
cdPipeline.NonCascadeDelete = !cascadeDelete
handler.Logger.Infow("request payload, PatchCdPipeline", "payload", cdPipeline)
err = handler.validator.StructPartial(cdPipeline, "AppId", "Action")
if err == nil {
Expand Down Expand Up @@ -668,7 +691,7 @@
}
validate, err2 := handler.deploymentTemplateValidationService.DeploymentTemplateValidate(r.Context(), envConfigProperties.EnvOverrideValues, chartRefId, scope)
if !validate {
handler.Logger.Errorw("validation err, UpdateAppOverride", "err", err2, "payload", envConfigProperties)

Check failure on line 694 in api/restHandler/app/pipeline/configure/DeploymentPipelineRestHandler.go

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of duplicating this literal "validation err, UpdateAppOverride" 4 times.

See more on https://sonarcloud.io/project/issues?id=devtron-labs_devtron&issues=AaDD4l-gUDJ0UtnK4X8q&open=AaDD4l-gUDJ0UtnK4X8q&pullRequest=7045
common.WriteJsonResp(w, err2, nil, http.StatusBadRequest)
return
}
Expand Down Expand Up @@ -782,7 +805,7 @@
token := r.Header.Get("token")
app, err := handler.pipelineBuilder.GetApp(appId)
if err != nil {
handler.Logger.Errorw("service err, GetEnvConfigOverride", "err", err, "payload", appId, environmentId, chartRefId)

Check failure on line 808 in api/restHandler/app/pipeline/configure/DeploymentPipelineRestHandler.go

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of duplicating this literal "service err, GetEnvConfigOverride" 3 times.

See more on https://sonarcloud.io/project/issues?id=devtron-labs_devtron&issues=AaDD4l-gUDJ0UtnK4X8s&open=AaDD4l-gUDJ0UtnK4X8s&pullRequest=7045
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
return
}
Expand Down Expand Up @@ -1023,7 +1046,7 @@
vars := mux.Vars(r)
appId, err := strconv.Atoi(vars["appId"])
if err != nil {
handler.Logger.Errorw("request err, GetCdPipelines", "err", err, "appId", appId)

Check failure on line 1049 in api/restHandler/app/pipeline/configure/DeploymentPipelineRestHandler.go

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of duplicating this literal "request err, GetCdPipelines" 3 times.

See more on https://sonarcloud.io/project/issues?id=devtron-labs_devtron&issues=AaDD4l-gUDJ0UtnK4X8v&open=AaDD4l-gUDJ0UtnK4X8v&pullRequest=7045
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
return
}
Expand All @@ -1031,7 +1054,7 @@
token := r.Header.Get("token")
app, err := handler.pipelineBuilder.GetApp(appId)
if err != nil {
handler.Logger.Errorw("service err, GetCdPipelines", "err", err, "appId", appId)

Check failure on line 1057 in api/restHandler/app/pipeline/configure/DeploymentPipelineRestHandler.go

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of duplicating this literal "service err, GetCdPipelines" 4 times.

See more on https://sonarcloud.io/project/issues?id=devtron-labs_devtron&issues=AaDD4l-gUDJ0UtnK4X8o&open=AaDD4l-gUDJ0UtnK4X8o&pullRequest=7045
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
return
}
Expand Down Expand Up @@ -1126,7 +1149,7 @@
if offsetQueryParam != "" {
offset, err = strconv.Atoi(offsetQueryParam)
if err != nil || offset < 0 {
handler.Logger.Errorw("request err, GetArtifactsForRollback", "offsetQueryParam", offsetQueryParam, "err", err)

Check failure on line 1152 in api/restHandler/app/pipeline/configure/DeploymentPipelineRestHandler.go

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of duplicating this literal "request err, GetArtifactsForRollback" 5 times.

See more on https://sonarcloud.io/project/issues?id=devtron-labs_devtron&issues=AaDD4l-gUDJ0UtnK4X8r&open=AaDD4l-gUDJ0UtnK4X8r&pullRequest=7045
common.WriteJsonResp(w, err, "invalid offset", http.StatusBadRequest)
return
}
Expand Down Expand Up @@ -1183,7 +1206,7 @@

appTags, err := handler.imageTaggingReadService.GetUniqueTagsByAppId(pipeline.AppId)
if err != nil {
handler.Logger.Errorw("service err, GetTagsByAppId", "appId", pipeline.AppId, "err", err)

Check failure on line 1209 in api/restHandler/app/pipeline/configure/DeploymentPipelineRestHandler.go

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of duplicating this literal "service err, GetTagsByAppId" 3 times.

See more on https://sonarcloud.io/project/issues?id=devtron-labs_devtron&issues=AaDD4l-gUDJ0UtnK4X8u&open=AaDD4l-gUDJ0UtnK4X8u&pullRequest=7045
common.WriteJsonResp(w, err, ciArtifactResponse, http.StatusInternalServerError)
return
}
Expand Down Expand Up @@ -1380,7 +1403,7 @@
token := r.Header.Get("token")
deploymentPipeline, err := handler.pipelineBuilder.FindPipelineById(cdPipelineId)
if err != nil {
handler.Logger.Errorw("service err, GetArtifactsForRollback", "err", err, "cdPipelineId", cdPipelineId)

Check failure on line 1406 in api/restHandler/app/pipeline/configure/DeploymentPipelineRestHandler.go

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of duplicating this literal "service err, GetArtifactsForRollback" 3 times.

See more on https://sonarcloud.io/project/issues?id=devtron-labs_devtron&issues=AaDD4l-gUDJ0UtnK4X8p&open=AaDD4l-gUDJ0UtnK4X8p&pullRequest=7045
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
return
}
Expand Down
90 changes: 73 additions & 17 deletions api/restHandler/scopedVariable/ScopedVariableRestHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@
"net/http"
"strconv"

"github.com/devtron-labs/common-lib/async"
"github.com/devtron-labs/devtron/api/restHandler/common"
util2 "github.com/devtron-labs/devtron/internal/util"
"github.com/devtron-labs/devtron/pkg/auth/authorisation/casbin"
"github.com/devtron-labs/devtron/pkg/auth/user"
"github.com/devtron-labs/devtron/pkg/bean"
Expand All @@ -42,31 +44,36 @@
CreateVariables(w http.ResponseWriter, r *http.Request)
GetScopedVariables(w http.ResponseWriter, r *http.Request)
GetJsonForVariables(w http.ResponseWriter, r *http.Request)
GetVariableUsage(w http.ResponseWriter, r *http.Request)
}

type ScopedVariableRestHandlerImpl struct {
logger *zap.SugaredLogger
userAuthService user.UserService
validator *validator.Validate
pipelineBuilder pipeline.PipelineBuilder
enforcerUtil rbac.EnforcerUtil
enforcer casbin.Enforcer
scopedVariableService variables.ScopedVariableService
logger *zap.SugaredLogger
userAuthService user.UserService
validator *validator.Validate
pipelineBuilder pipeline.PipelineBuilder
enforcerUtil rbac.EnforcerUtil
enforcer casbin.Enforcer
scopedVariableService variables.ScopedVariableService
gitMaterialVariableSyncService pipeline.GitMaterialVariableSyncService
asyncRunnable *async.Runnable
}
type JsonResponse struct {
Manifest *models.ScopedVariableManifest `json:"manifest"`
JsonSchema string `json:"jsonSchema"`
}

func NewScopedVariableRestHandlerImpl(logger *zap.SugaredLogger, userAuthService user.UserService, validator *validator.Validate, pipelineBuilder pipeline.PipelineBuilder, enforcerUtil rbac.EnforcerUtil, enforcer casbin.Enforcer, scopedVariableService variables.ScopedVariableService) *ScopedVariableRestHandlerImpl {
func NewScopedVariableRestHandlerImpl(logger *zap.SugaredLogger, userAuthService user.UserService, validator *validator.Validate, pipelineBuilder pipeline.PipelineBuilder, enforcerUtil rbac.EnforcerUtil, enforcer casbin.Enforcer, scopedVariableService variables.ScopedVariableService, gitMaterialVariableSyncService pipeline.GitMaterialVariableSyncService, asyncRunnable *async.Runnable) *ScopedVariableRestHandlerImpl {

Check warning on line 66 in api/restHandler/scopedVariable/ScopedVariableRestHandler.go

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

This function has 9 parameters, which is greater than the 7 authorized.

See more on https://sonarcloud.io/project/issues?id=devtron-labs_devtron&issues=AaDDz46cGoclI8RyInOT&open=AaDDz46cGoclI8RyInOT&pullRequest=7045
return &ScopedVariableRestHandlerImpl{
logger: logger,
userAuthService: userAuthService,
validator: validator,
pipelineBuilder: pipelineBuilder,
enforcerUtil: enforcerUtil,
enforcer: enforcer,
scopedVariableService: scopedVariableService,
logger: logger,
userAuthService: userAuthService,
validator: validator,
pipelineBuilder: pipelineBuilder,
enforcerUtil: enforcerUtil,
enforcer: enforcer,
scopedVariableService: scopedVariableService,
gitMaterialVariableSyncService: gitMaterialVariableSyncService,
asyncRunnable: asyncRunnable,
}
}
func (handler *ScopedVariableRestHandlerImpl) CreateVariables(w http.ResponseWriter, r *http.Request) {
Expand Down Expand Up @@ -94,7 +101,12 @@
return
}

payload := utils.ManifestToPayload(request.Manifest, userId)
payload, err := utils.ManifestToPayload(request.Manifest, userId)
if err != nil {
handler.logger.Errorw("invalid manifest in CreateVariables", "err", err)
common.WriteJsonResp(w, err, nil, http.StatusNotAcceptable)
return
}

// not logging bean object as it contains sensitive data
handler.logger.Infow("request payload received for variables")
Expand All @@ -108,15 +120,59 @@
//RBAC enforcer Ends
err = handler.scopedVariableService.CreateVariables(payload)
if err != nil {
if errors.As(err, &models.ValidationError{}) {
var deletionBlockedErr *models.VariableDeletionBlockedError
if errors.As(err, &deletionBlockedErr) {
apiErr := &util2.ApiError{
HttpStatusCode: http.StatusConflict,
Code: strconv.Itoa(http.StatusConflict),
InternalMessage: deletionBlockedErr.Error(),
UserMessage: deletionBlockedErr.Error(),
UserDetailMessage: deletionBlockedErr.UsageSummary(20),
}
common.WriteJsonResp(w, apiErr, nil, http.StatusConflict)
} else if errors.As(err, &models.ValidationError{}) {
common.WriteJsonResp(w, err, nil, http.StatusNotAcceptable)
} else {
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
}
return
}
// CreateVariables replaces the entire variable set, so any Git Material referencing a
// scoped variable may need its git-sensor copy refreshed - run off-thread since each
// push to git-sensor can take up to its own timeout ceiling, and this must not block
// the response for a save that already succeeded above.
handler.asyncRunnable.Execute(func() {
if syncErr := handler.gitMaterialVariableSyncService.ResyncGitMaterialsForVariableChange(); syncErr != nil {
handler.logger.Errorw("error re-syncing git materials after variable change", "err", syncErr)
}
})
common.WriteJsonResp(w, nil, nil, http.StatusOK)
}

func (handler *ScopedVariableRestHandlerImpl) GetVariableUsage(w http.ResponseWriter, r *http.Request) {
userId, err := handler.userAuthService.GetLoggedInUser(r)
if userId == 0 || err != nil {
common.HandleUnauthorized(w, r)
return
}

// RBAC enforcer applying
token := r.Header.Get("token")
if isSuperAdmin := handler.enforcer.Enforce(token, casbin.ResourceGlobal, casbin.ActionGet, "*"); !isSuperAdmin {

Check warning on line 161 in api/restHandler/scopedVariable/ScopedVariableRestHandler.go

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this unnecessary variable declaration and use the expression directly in the condition.

See more on https://sonarcloud.io/project/issues?id=devtron-labs_devtron&issues=AaDDz46cGoclI8RyInOU&open=AaDDz46cGoclI8RyInOU&pullRequest=7045
common.WriteJsonResp(w, errors.New("unauthorized"), nil, http.StatusForbidden)
return
}
//RBAC enforcer Ends

variableName := r.URL.Query().Get("name")
usages, err := handler.scopedVariableService.GetVariableUsage(variableName)
if err != nil {
handler.logger.Errorw("service err, GetVariableUsage", "variableName", variableName, "err", err)
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
return
}
common.WriteJsonResp(w, nil, usages, http.StatusOK)
}
func (handler *ScopedVariableRestHandlerImpl) GetScopedVariables(w http.ResponseWriter, r *http.Request) {
token := r.Header.Get("token")
isSuperAdmin := handler.enforcer.Enforce(token, casbin.ResourceGlobal, casbin.ActionGet, "*")
Expand Down
3 changes: 3 additions & 0 deletions api/router/ScopedVariableRouter.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,8 @@ func (impl ScopedVariableRouterImpl) InitScopedVariableRouter(router *mux.Router
router.Path("/variables/detail").
HandlerFunc(impl.scopedVariableRestHandler.GetJsonForVariables).
Methods("GET")
router.Path("/variables/usage").
HandlerFunc(impl.scopedVariableRestHandler.GetVariableUsage).
Methods("GET")

}
2 changes: 1 addition & 1 deletion env_gen.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions env_gen.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
| FEATURE_MIGRATE_ARGOCD_APPLICATION_ENABLE | bool |false | enable migration of external argocd application to devtron pipeline | | false |
| FEATURE_MIGRATE_FLUX_APPLICATION_ENABLE | bool |false | enable flux application services | | false |
| FLUX_CD_PIPELINE_STATUS_CHECK_ELIGIBLE_TIME | string |120 | eligible time for checking flux app status periodically and update in db, value is in seconds., default is 120, if wfr is updated within configured time i.e. FLUX_CD_PIPELINE_STATUS_CHECK_ELIGIBLE_TIME then do not include for this cron cycle. | | false |
| FOREGROUND_DELETE_CD_PIPELINE | bool |false | If enabled, deleting a CD pipeline will not delete the underlying deployed resource (helm release/argocd application/flux release) unless the request explicitly overrides it via payload. | | false |
| HELM_PIPELINE_STATUS_CHECK_ELIGIBLE_TIME | string |120 | eligible time for checking helm app status periodically and update in db, value is in seconds., default is 120, if wfr is updated within configured time i.e. HELM_PIPELINE_STATUS_CHECK_ELIGIBLE_TIME then do not include for this cron cycle. | | false |
| IS_INTERNAL_USE | bool |true | If enabled then cd pipeline and helm apps will not need the deployment app type mandatorily. Couple this flag with HIDE_GITOPS_OR_HELM_OPTION (in Dashborad) and if gitops is configured and allowed for the env, pipeline/ helm app will gitops else no-gitops. | | false |
| MIGRATE_DEPLOYMENT_CONFIG_DATA | bool |false | migrate deployment config data from charts table to deployment_config table | | false |
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ replace (
// Keep the left side unversioned: a versioned LHS stops matching whenever the
// require line is bumped, which silently un-pins this and breaks the linux build.
github.com/cyphar/filepath-securejoin => github.com/cyphar/filepath-securejoin v0.3.6 // indirect
github.com/devtron-labs/authenticator => github.com/devtron-labs/devtron-services/authenticator v0.0.0-20260803100101-66fcb35e4b0e
github.com/devtron-labs/common-lib => github.com/devtron-labs/devtron-services/common-lib v0.0.0-20260803100101-66fcb35e4b0e
github.com/devtron-labs/authenticator => github.com/devtron-labs/devtron-services/authenticator v0.0.0-20260921111017-f0b3fba15081
github.com/devtron-labs/common-lib => github.com/devtron-labs/devtron-services/common-lib v0.0.0-20260921111017-f0b3fba15081
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 => go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1
)
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -237,10 +237,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-20260803100101-66fcb35e4b0e h1:mfAbqKv+CswkCah0JCSzeTJThvjaNBt51TunM8lBsPU=
github.com/devtron-labs/devtron-services/authenticator v0.0.0-20260803100101-66fcb35e4b0e/go.mod h1:m/dMed6iiZQ/4iOJ6kIVWXQ+T71rJjU7DnCr9RcYh1w=
github.com/devtron-labs/devtron-services/common-lib v0.0.0-20260803100101-66fcb35e4b0e h1:gh/iIVC9FNpPE8C72duWZGNgwgE2jrYonpYDvty2cFM=
github.com/devtron-labs/devtron-services/common-lib v0.0.0-20260803100101-66fcb35e4b0e/go.mod h1:QZfnuGy0xqrYWhq3jCRe6fDDwIsrpbjAR2PXNrh0su8=
github.com/devtron-labs/devtron-services/authenticator v0.0.0-20260921111017-f0b3fba15081 h1:BPkaewVaxMTnIAHcxwsWgebl5GV7uc6R/a0tCBoTZn0=
github.com/devtron-labs/devtron-services/authenticator v0.0.0-20260921111017-f0b3fba15081/go.mod h1:m/dMed6iiZQ/4iOJ6kIVWXQ+T71rJjU7DnCr9RcYh1w=
github.com/devtron-labs/devtron-services/common-lib v0.0.0-20260921111017-f0b3fba15081 h1:niegDwFaPhH5b+7UP2QuGdR6rB43hFYqNY1pJ6ZbXQw=
github.com/devtron-labs/devtron-services/common-lib v0.0.0-20260921111017-f0b3fba15081/go.mod h1:QZfnuGy0xqrYWhq3jCRe6fDDwIsrpbjAR2PXNrh0su8=
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=
Expand Down
10 changes: 10 additions & 0 deletions pkg/bean/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -770,6 +770,16 @@ type CDPatchRequest struct {
UserId int32 `json:"-"`
ForceDelete bool `json:"-"`
NonCascadeDelete bool `json:"-"`
ForegroundDelete *bool `json:"-"`
}

// GetForegroundDelete resolves the effective foreground-delete flag for this
// request: the explicit query-param value if set, otherwise the provided env default.
func (r *CDPatchRequest) GetForegroundDelete(envDefault bool) bool {
if r.ForegroundDelete != nil {
return *r.ForegroundDelete
}
return envDefault
}

type CdPatchAction int
Expand Down
28 changes: 28 additions & 0 deletions pkg/bean/app_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package bean

import "testing"

func boolPtr(b bool) *bool { return &b }

func TestCDPatchRequest_GetForegroundDelete(t *testing.T) {
tests := []struct {
name string
field *bool
envDefault bool
want bool
}{
{"nil payload, env false", nil, false, false},
{"nil payload, env true", nil, true, true},
{"payload true overrides env false", boolPtr(true), false, true},
{"payload false overrides env true", boolPtr(false), true, false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := &CDPatchRequest{ForegroundDelete: tt.field}
if got := r.GetForegroundDelete(tt.envDefault); got != tt.want {
t.Errorf("GetForegroundDelete(%v) with field=%v = %v, want %v",
tt.envDefault, tt.field, got, tt.want)
}
})
}
}
Loading
Loading