Skip to content

fix: app clone breaking if ci pipeline have same name #4461

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Dec 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions api/restHandler/CoreAppRestHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -1559,6 +1559,10 @@ func (handler CoreAppRestHandlerImpl) createWorkflows(ctx context.Context, appId
//Creating CI pipeline starts
ciPipeline, err := handler.createCiPipeline(appId, userId, workflowId, workflow.CiPipeline)
if err != nil {
if err.Error() == bean2.PIPELINE_NAME_ALREADY_EXISTS_ERROR {
handler.logger.Errorw("service err, DeleteAppWorkflow ", "err", err)
return err, http.StatusBadRequest
}
err1 := handler.appWorkflowService.DeleteAppWorkflow(workflowId, userId)
if err1 != nil {
handler.logger.Errorw("service err, DeleteAppWorkflow ")
Expand Down
5 changes: 5 additions & 0 deletions api/restHandler/app/BuildPipelineRestHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,11 @@ func (handler PipelineConfigRestHandlerImpl) PatchCiPipelines(w http.ResponseWri
}
createResp, err := handler.pipelineBuilder.PatchCiPipeline(&patchRequest)
if err != nil {
if err.Error() == bean1.PIPELINE_NAME_ALREADY_EXISTS_ERROR {
handler.Logger.Errorw("service err, pipeline name already exist ", "err", err)
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
return
}
handler.Logger.Errorw("service err, PatchCiPipelines", "err", err, "PatchCiPipelines", patchRequest)
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
return
Expand Down
262 changes: 139 additions & 123 deletions pkg/appClone/AppCloneService.go
Original file line number Diff line number Diff line change
Expand Up @@ -794,133 +794,149 @@ func (impl *AppCloneServiceImpl) CreateCiPipeline(req *cloneCiPipelineRequest) (
if err != nil {
return nil, err
}
for _, refCiPipeline := range refCiConfig.CiPipelines {
if refCiPipeline.Id == req.refCiPipelineId {
pipelineName := refCiPipeline.Name
if strings.HasPrefix(pipelineName, req.refAppName) {
pipelineName = strings.Replace(pipelineName, req.refAppName+"-ci-", "", 1)
}
var ciMaterilas []*bean.CiMaterial
for _, refCiMaterial := range refCiPipeline.CiMaterial {
//FIXME
gitMaterialId := req.gitMaterialMapping[refCiMaterial.GitMaterialId]
if refCiPipeline.ParentCiPipeline != 0 {
gitMaterialId = refCiMaterial.GitMaterialId
}
ciMaterial := &bean.CiMaterial{
GitMaterialId: gitMaterialId,
Id: 0,
Source: &bean.SourceTypeConfig{
Type: refCiMaterial.Source.Type,
Value: refCiMaterial.Source.Value,
Regex: refCiMaterial.Source.Regex,
},
}
ciMaterilas = append(ciMaterilas, ciMaterial)
}
var beforeDockerBuildScripts []*bean.CiScript
var afterDockerBuildScripts []*bean.CiScript

for _, script := range refCiPipeline.BeforeDockerBuildScripts {
ciScript := &bean.CiScript{
Id: 0,
Index: script.Index,
Name: script.Name,
Script: script.Script,
OutputLocation: script.OutputLocation,
}
beforeDockerBuildScripts = append(beforeDockerBuildScripts, ciScript)
}
for _, script := range refCiPipeline.AfterDockerBuildScripts {
ciScript := &bean.CiScript{
Id: 0,
Index: script.Index,
Name: script.Name,
Script: script.Script,
OutputLocation: script.OutputLocation,
}
afterDockerBuildScripts = append(afterDockerBuildScripts, ciScript)
}

//getting pre stage and post stage details
preStageDetail, postStageDetail, err := impl.pipelineStageService.GetCiPipelineStageDataDeepCopy(refCiPipeline.Id)
if err != nil {
impl.logger.Errorw("error in getting pre & post stage detail by ciPipelineId", "err", err, "ciPipelineId", refCiPipeline.Id)
return nil, err
}
ciPatchReq := &bean.CiPatchRequest{
CiPipeline: &bean.CiPipeline{
IsManual: refCiPipeline.IsManual,
DockerArgs: refCiPipeline.DockerArgs,
IsExternal: refCiPipeline.IsExternal,
ExternalCiConfig: bean.ExternalCiConfig{},
CiMaterial: ciMaterilas,
Name: pipelineName,
Id: 0,
Version: refCiPipeline.Version,
Active: refCiPipeline.Active,
Deleted: refCiPipeline.Deleted,
BeforeDockerBuild: refCiPipeline.BeforeDockerBuild,
AfterDockerBuild: refCiPipeline.AfterDockerBuild,
BeforeDockerBuildScripts: beforeDockerBuildScripts,
AfterDockerBuildScripts: afterDockerBuildScripts,
ParentCiPipeline: refCiPipeline.ParentCiPipeline,
IsDockerConfigOverridden: refCiPipeline.IsDockerConfigOverridden,
PreBuildStage: preStageDetail,
PostBuildStage: postStageDetail,
EnvironmentId: refCiPipeline.EnvironmentId,
ScanEnabled: refCiPipeline.ScanEnabled,
PipelineType: refCiPipeline.PipelineType,
},
AppId: req.appId,
Action: bean.CREATE,
AppWorkflowId: req.wfId,
UserId: req.userId,
IsCloneJob: true,
}
if refCiPipeline.EnvironmentId != 0 {
ciPatchReq.IsJob = true
}
if !refCiPipeline.IsExternal && refCiPipeline.IsDockerConfigOverridden {
//get template override
templateOverrideBean, err := impl.ciTemplateService.FindTemplateOverrideByCiPipelineId(refCiPipeline.Id)
if err != nil {
return nil, err
}
templateOverride := templateOverrideBean.CiTemplateOverride
ciBuildConfig := templateOverrideBean.CiBuildConfig
//getting new git material for this app
//gitMaterial, err := impl.materialRepository.FindByAppIdAndCheckoutPath(req.appId, templateOverride.GitMaterial.CheckoutPath)
if len(req.gitMaterialMapping) == 0 {
impl.logger.Errorw("no git materials found for the app", "appId", req.appId)
return nil, fmt.Errorf("no git materials found for the app, %d", req.appId)
}
gitMaterialId := req.gitMaterialMapping[ciBuildConfig.GitMaterialId]
buildContextGitMaterialId := req.gitMaterialMapping[ciBuildConfig.BuildContextGitMaterialId]
if gitMaterialId == 0 {
for _, id := range req.gitMaterialMapping {
gitMaterialId = id
break
}
}
if buildContextGitMaterialId == 0 {
buildContextGitMaterialId = gitMaterialId
}
ciBuildConfig.GitMaterialId = gitMaterialId
ciBuildConfig.BuildContextGitMaterialId = buildContextGitMaterialId
templateOverride.GitMaterialId = gitMaterialId
ciBuildConfig.Id = 0
ciPatchReq.CiPipeline.DockerConfigOverride = bean.DockerConfigOverride{
DockerRegistry: templateOverride.DockerRegistryId,
DockerRepository: templateOverride.DockerRepository,
CiBuildConfig: ciBuildConfig,
}
}
var refCiPipeline *bean.CiPipeline
var uniqueId int
for id, reqCiPipeline := range refCiConfig.CiPipelines {
if reqCiPipeline.Id == req.refCiPipelineId {
refCiPipeline = reqCiPipeline
uniqueId = id
break
}
}
if refCiPipeline == nil {
return nil, nil
}
pipelineName := refCiPipeline.Name
if strings.HasPrefix(pipelineName, req.refAppName) {
pipelineName = strings.Replace(pipelineName, req.refAppName+"-ci-", "", 1)
}

return impl.pipelineBuilder.PatchCiPipeline(ciPatchReq)
pipelineExists, err := impl.ciPipelineRepository.CheckIfPipelineExistsByNameAndAppId(pipelineName, req.appId)
if err != nil && err != pg.ErrNoRows {
impl.logger.Errorw("error in fetching pipeline by name, FindByName", "err", err, "patch cipipeline name", pipelineName)
return nil, err
}
if pipelineExists {
pipelineName = fmt.Sprintf("%s-%d", pipelineName, uniqueId) // making pipeline name unique
}
var ciMaterilas []*bean.CiMaterial
for _, refCiMaterial := range refCiPipeline.CiMaterial {
//FIXME
gitMaterialId := req.gitMaterialMapping[refCiMaterial.GitMaterialId]
if refCiPipeline.ParentCiPipeline != 0 {
gitMaterialId = refCiMaterial.GitMaterialId
}
ciMaterial := &bean.CiMaterial{
GitMaterialId: gitMaterialId,
Id: 0,
Source: &bean.SourceTypeConfig{
Type: refCiMaterial.Source.Type,
Value: refCiMaterial.Source.Value,
Regex: refCiMaterial.Source.Regex,
},
}
ciMaterilas = append(ciMaterilas, ciMaterial)
}
var beforeDockerBuildScripts []*bean.CiScript
var afterDockerBuildScripts []*bean.CiScript

for _, script := range refCiPipeline.BeforeDockerBuildScripts {
ciScript := &bean.CiScript{
Id: 0,
Index: script.Index,
Name: script.Name,
Script: script.Script,
OutputLocation: script.OutputLocation,
}
beforeDockerBuildScripts = append(beforeDockerBuildScripts, ciScript)
}
for _, script := range refCiPipeline.AfterDockerBuildScripts {
ciScript := &bean.CiScript{
Id: 0,
Index: script.Index,
Name: script.Name,
Script: script.Script,
OutputLocation: script.OutputLocation,
}
afterDockerBuildScripts = append(afterDockerBuildScripts, ciScript)
}

//getting pre stage and post stage details
preStageDetail, postStageDetail, err := impl.pipelineStageService.GetCiPipelineStageDataDeepCopy(refCiPipeline.Id)
if err != nil {
impl.logger.Errorw("error in getting pre & post stage detail by ciPipelineId", "err", err, "ciPipelineId", refCiPipeline.Id)
return nil, err
}
ciPatchReq := &bean.CiPatchRequest{
CiPipeline: &bean.CiPipeline{
IsManual: refCiPipeline.IsManual,
DockerArgs: refCiPipeline.DockerArgs,
IsExternal: refCiPipeline.IsExternal,
ExternalCiConfig: bean.ExternalCiConfig{},
CiMaterial: ciMaterilas,
Name: pipelineName,
Id: 0,
Version: refCiPipeline.Version,
Active: refCiPipeline.Active,
Deleted: refCiPipeline.Deleted,
BeforeDockerBuild: refCiPipeline.BeforeDockerBuild,
AfterDockerBuild: refCiPipeline.AfterDockerBuild,
BeforeDockerBuildScripts: beforeDockerBuildScripts,
AfterDockerBuildScripts: afterDockerBuildScripts,
ParentCiPipeline: refCiPipeline.ParentCiPipeline,
IsDockerConfigOverridden: refCiPipeline.IsDockerConfigOverridden,
PreBuildStage: preStageDetail,
PostBuildStage: postStageDetail,
EnvironmentId: refCiPipeline.EnvironmentId,
ScanEnabled: refCiPipeline.ScanEnabled,
PipelineType: refCiPipeline.PipelineType,
},
AppId: req.appId,
Action: bean.CREATE,
AppWorkflowId: req.wfId,
UserId: req.userId,
IsCloneJob: true,
}
if refCiPipeline.EnvironmentId != 0 {
ciPatchReq.IsJob = true
}
if !refCiPipeline.IsExternal && refCiPipeline.IsDockerConfigOverridden {
//get template override
templateOverrideBean, err := impl.ciTemplateService.FindTemplateOverrideByCiPipelineId(refCiPipeline.Id)
if err != nil {
return nil, err
}
templateOverride := templateOverrideBean.CiTemplateOverride
ciBuildConfig := templateOverrideBean.CiBuildConfig
//getting new git material for this app
//gitMaterial, err := impl.materialRepository.FindByAppIdAndCheckoutPath(req.appId, templateOverride.GitMaterial.CheckoutPath)
if len(req.gitMaterialMapping) == 0 {
impl.logger.Errorw("no git materials found for the app", "appId", req.appId)
return nil, fmt.Errorf("no git materials found for the app, %d", req.appId)
}
gitMaterialId := req.gitMaterialMapping[ciBuildConfig.GitMaterialId]
buildContextGitMaterialId := req.gitMaterialMapping[ciBuildConfig.BuildContextGitMaterialId]
if gitMaterialId == 0 {
for _, id := range req.gitMaterialMapping {
gitMaterialId = id
break
}
}
if buildContextGitMaterialId == 0 {
buildContextGitMaterialId = gitMaterialId
}
ciBuildConfig.GitMaterialId = gitMaterialId
ciBuildConfig.BuildContextGitMaterialId = buildContextGitMaterialId
templateOverride.GitMaterialId = gitMaterialId
ciBuildConfig.Id = 0
ciPatchReq.CiPipeline.DockerConfigOverride = bean.DockerConfigOverride{
DockerRegistry: templateOverride.DockerRegistryId,
DockerRepository: templateOverride.DockerRepository,
CiBuildConfig: ciBuildConfig,
}
}
return nil, fmt.Errorf("ci pipeline not found ")
return impl.pipelineBuilder.PatchCiPipeline(ciPatchReq)
}

type cloneCdPipelineRequest struct {
Expand Down
2 changes: 1 addition & 1 deletion pkg/pipeline/BuildPipelineConfigService.go
Original file line number Diff line number Diff line change
Expand Up @@ -1237,7 +1237,7 @@ func (impl *CiPipelineConfigServiceImpl) handlePipelineCreate(request *bean.CiPa

if pipelineExists {
impl.logger.Errorw("pipeline name already exist", "err", err, "patch cipipeline name", request.CiPipeline.Name)
return nil, fmt.Errorf("pipeline name already exist")
return nil, fmt.Errorf(bean3.PIPELINE_NAME_ALREADY_EXISTS_ERROR)
}

if request.IsSwitchCiPipelineRequest() {
Expand Down
2 changes: 2 additions & 0 deletions pkg/pipeline/bean/CiBuildConfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ const (
const Main = "main"
const UniquePlaceHolderForAppName = "$etron"

const PIPELINE_NAME_ALREADY_EXISTS_ERROR = "pipeline name already exist"

type CiBuildConfigBean struct {
Id int `json:"id"`
GitMaterialId int `json:"gitMaterialId,omitempty" validate:"required"`
Expand Down