From 2b793aefd0ea606226198c40c94fc0a733575a7e Mon Sep 17 00:00:00 2001 From: Shivam-nagar23 Date: Mon, 2 Jun 2025 16:17:57 +0530 Subject: [PATCH] fix: prevent deletion of git material used in overridden CI templates --- .../CiTemplateOverrideRepository.go | 18 ++++++++++++++++++ pkg/build/pipeline/CiTemplateReadService.go | 5 +++++ pkg/pipeline/CiMaterialConfigService.go | 14 ++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/internal/sql/repository/pipelineConfig/CiTemplateOverrideRepository.go b/internal/sql/repository/pipelineConfig/CiTemplateOverrideRepository.go index 1ed57025ae..eb2c70e376 100644 --- a/internal/sql/repository/pipelineConfig/CiTemplateOverrideRepository.go +++ b/internal/sql/repository/pipelineConfig/CiTemplateOverrideRepository.go @@ -21,6 +21,7 @@ import ( repository2 "github.com/devtron-labs/devtron/pkg/build/git/gitMaterial/repository" "github.com/devtron-labs/devtron/pkg/sql" "github.com/go-pg/pg" + "github.com/go-pg/pg/orm" "go.uber.org/zap" ) @@ -47,6 +48,7 @@ type CiTemplateOverrideRepository interface { FindByAppId(appId int) ([]*CiTemplateOverride, error) FindByCiPipelineIds(ciPipelineIds []int) ([]*CiTemplateOverride, error) FindByCiPipelineId(ciPipelineId int) (*CiTemplateOverride, error) + FindIfTemplateOverrideExistsByCiPipelineIdsAndGitMaterialId(ciPipelineIds []int, gitMaterialId int) (bool, error) } type CiTemplateOverrideRepositoryImpl struct { @@ -125,3 +127,19 @@ func (repo *CiTemplateOverrideRepositoryImpl) FindByCiPipelineId(ciPipelineId in } return ciTemplateOverride, nil } + +func (repo *CiTemplateOverrideRepositoryImpl) FindIfTemplateOverrideExistsByCiPipelineIdsAndGitMaterialId(ciPipelineIds []int, gitMaterialId int) (bool, error) { + count, err := repo.dbConnection.Model((*CiTemplateOverride)(nil)). + Where("ci_pipeline_id in (?)", pg.In(ciPipelineIds)). + WhereGroup(func(q *orm.Query) (*orm.Query, error) { + return q.Where("git_material_id = ?", gitMaterialId).WhereOr("build_context_git_material_id = ?", gitMaterialId), nil + }). + Where("active = ?", true). + Count() + if err != nil { + repo.logger.Errorw("error in checking if template override exists", "ciPipelineIds", ciPipelineIds, "gitMaterialId", gitMaterialId, "err", err) + return false, err + } + return count > 0, nil + +} diff --git a/pkg/build/pipeline/CiTemplateReadService.go b/pkg/build/pipeline/CiTemplateReadService.go index 632b94c46d..e615ae8331 100644 --- a/pkg/build/pipeline/CiTemplateReadService.go +++ b/pkg/build/pipeline/CiTemplateReadService.go @@ -18,6 +18,7 @@ type CiTemplateReadService interface { GetAppliedDockerConfigForCiPipeline(ciPipelineId, appId int, isOverridden bool) (*types.DockerArtifactStoreBean, error) GetBaseDockerConfigForCiPipeline(appId int) (*types.DockerArtifactStoreBean, error) FindByAppIds(appIds []int) (map[int]*bean.CiTemplateBean, error) + CheckIfTemplateOverrideExists(ciPipelineIds []int, gitMaterialId int) (bool, error) } type CiTemplateReadServiceImpl struct { @@ -181,3 +182,7 @@ func (impl *CiTemplateReadServiceImpl) FindByAppIds(appIds []int) (map[int]*bean } return ciTemplateMap, nil } + +func (impl *CiTemplateReadServiceImpl) CheckIfTemplateOverrideExists(ciPipelineIds []int, gitMaterialId int) (bool, error) { + return impl.CiTemplateOverrideRepository.FindIfTemplateOverrideExistsByCiPipelineIdsAndGitMaterialId(ciPipelineIds, gitMaterialId) +} diff --git a/pkg/pipeline/CiMaterialConfigService.go b/pkg/pipeline/CiMaterialConfigService.go index be05f2ef4c..fa8e988884 100644 --- a/pkg/pipeline/CiMaterialConfigService.go +++ b/pkg/pipeline/CiMaterialConfigService.go @@ -20,15 +20,18 @@ import ( "fmt" "github.com/devtron-labs/devtron/internal/sql/constants" "github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig" + util2 "github.com/devtron-labs/devtron/internal/util" "github.com/devtron-labs/devtron/pkg/bean" "github.com/devtron-labs/devtron/pkg/build/git/gitMaterial/read" "github.com/devtron-labs/devtron/pkg/build/git/gitMaterial/repository" "github.com/devtron-labs/devtron/pkg/build/pipeline" "github.com/devtron-labs/devtron/pkg/pipeline/history" "github.com/devtron-labs/devtron/pkg/sql" + "github.com/devtron-labs/devtron/util/sliceUtil" "github.com/go-pg/pg" "github.com/juju/errors" "go.uber.org/zap" + "net/http" "strings" "time" ) @@ -123,6 +126,17 @@ func (impl *CiMaterialConfigServiceImpl) DeleteMaterial(request *bean.UpdateMate return fmt.Errorf("cannot delete git material, is being used in docker config") } } + pipelineIds := sliceUtil.NewSliceFromFuncExec(pipelines, func(dbPipeline *pipelineConfig.CiPipeline) int { + return dbPipeline.Id + }) + exist, err := impl.ciTemplateService.CheckIfTemplateOverrideExists(pipelineIds, request.Material.Id) + if err != nil { + impl.logger.Errorw("error in checking if template override exists", "pipelineIds", pipelineIds, "gitMaterialId", request.Material.Id, "err", err) + return err + } + if exist { + return util2.GetApiErrorAdapter(http.StatusBadRequest, "400", "cannot delete git material, is being used in overridden ci template", "cannot delete git material, is being used in overridden ci template") + } } existingMaterial, err := impl.gitMaterialReadService.FindById(request.Material.Id) if err != nil {