Skip to content

Commit 98dd439

Browse files
fix: cloning app with seq cd pipeline fix (#3926)
* setting parent id and type in cd clone dto req. * ignoring parentid if parent is ci_pipeline type * mapping ref vs new cd pipeline in case of cloning app * minor fix * passing source to new pipeline id mapping and refpipline id with webhook type cd * minor fix * fix * external ci workflow cloning fix * minor fix * creating appWorkflow in app clone service layer rather than in pipelinebuilder for app clone * minor fixes * removing pointer map in cdPipelineConfigObject * further refactoring * minor fix * more refactoring * createWfMapping to createWfInstances * minor refactoring in AppCloneService * error handling
1 parent 6fee8b7 commit 98dd439

File tree

4 files changed

+158
-88
lines changed

4 files changed

+158
-88
lines changed

pkg/appClone/AppCloneService.go

Lines changed: 113 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ type AppCloneServiceImpl struct {
5353
pipelineStageService pipeline.PipelineStageService
5454
ciTemplateService pipeline.CiTemplateService
5555
appRepository app2.AppRepository
56+
ciPipelineRepository pipelineConfig.CiPipelineRepository
57+
pipelineRepository pipelineConfig.PipelineRepository
58+
appWorkflowRepository appWorkflow2.AppWorkflowRepository
5659
}
5760

5861
func NewAppCloneServiceImpl(logger *zap.SugaredLogger,
@@ -65,7 +68,8 @@ func NewAppCloneServiceImpl(logger *zap.SugaredLogger,
6568
propertiesConfigService pipeline.PropertiesConfigService,
6669
ciTemplateOverrideRepository pipelineConfig.CiTemplateOverrideRepository,
6770
pipelineStageService pipeline.PipelineStageService, ciTemplateService pipeline.CiTemplateService,
68-
appRepository app2.AppRepository) *AppCloneServiceImpl {
71+
appRepository app2.AppRepository, ciPipelineRepository pipelineConfig.CiPipelineRepository,
72+
pipelineRepository pipelineConfig.PipelineRepository, appWorkflowRepository appWorkflow2.AppWorkflowRepository) *AppCloneServiceImpl {
6973
return &AppCloneServiceImpl{
7074
logger: logger,
7175
pipelineBuilder: pipelineBuilder,
@@ -78,6 +82,9 @@ func NewAppCloneServiceImpl(logger *zap.SugaredLogger,
7882
pipelineStageService: pipelineStageService,
7983
ciTemplateService: ciTemplateService,
8084
appRepository: appRepository,
85+
ciPipelineRepository: ciPipelineRepository,
86+
pipelineRepository: pipelineRepository,
87+
appWorkflowRepository: appWorkflowRepository,
8188
}
8289
}
8390

@@ -90,6 +97,16 @@ type CloneRequest struct {
9097
AppType helper.AppType `json:"appType"`
9198
}
9299

100+
type CreateWorkflowMappingDto struct {
101+
oldAppId int
102+
newAppId int
103+
userId int32
104+
newWfId int
105+
gitMaterialMapping map[int]int
106+
isSameProject bool
107+
externalCiPipelineId int
108+
}
109+
93110
func (impl *AppCloneServiceImpl) CloneApp(createReq *bean.CreateAppDTO, context context.Context) (*bean.CreateAppDTO, error) {
94111
//validate template app
95112
templateApp, err := impl.appRepository.FindById(createReq.TemplateId)
@@ -587,6 +604,7 @@ func (impl *AppCloneServiceImpl) CreateWf(oldAppId, newAppId int, userId int32,
587604
return nil, err
588605
}
589606
impl.logger.Debugw("workflow found", "wf", refAppWFs)
607+
590608
for _, refAppWF := range refAppWFs {
591609
thisWf := appWorkflow.AppWorkflowDto{
592610
Id: 0,
@@ -595,24 +613,38 @@ func (impl *AppCloneServiceImpl) CreateWf(oldAppId, newAppId int, userId int32,
595613
AppWorkflowMappingDto: nil, //first create new mapping then add it
596614
UserId: userId,
597615
}
616+
thisWf, err = impl.appWorkflowService.CreateAppWorkflow(thisWf)
617+
if err != nil {
618+
impl.logger.Errorw("error in creating workflow without external-ci", "err", err)
619+
return nil, err
620+
}
598621

599622
isExternalCiPresent := false
600623
for _, awm := range refAppWF.AppWorkflowMappingDto {
601624
if awm.Type == appWorkflow2.WEBHOOK {
602625
isExternalCiPresent = true
626+
break
603627
}
604628
}
605-
606-
if !isExternalCiPresent {
607-
thisWf, err = impl.appWorkflowService.CreateAppWorkflow(thisWf)
608-
impl.logger.Debugw("workflow found", thisWf)
629+
createWorkflowMappingDto := CreateWorkflowMappingDto{
630+
newAppId: newAppId,
631+
oldAppId: oldAppId,
632+
newWfId: thisWf.Id,
633+
userId: userId,
634+
}
635+
var externalCiPipelineId int
636+
if isExternalCiPresent {
637+
externalCiPipelineId, err = impl.createExternalCiAndAppWorkflowMapping(createWorkflowMappingDto)
609638
if err != nil {
610-
impl.logger.Errorw("errir in creating workflow without extenal-ci", "err", err)
639+
impl.logger.Errorw("error in createExternalCiAndAppWorkflowMapping", "err", err)
611640
return nil, err
612641
}
613642
}
643+
createWorkflowMappingDto.gitMaterialMapping = gitMaterialMapping
644+
createWorkflowMappingDto.isSameProject = isSameProject
645+
createWorkflowMappingDto.externalCiPipelineId = externalCiPipelineId
614646

615-
err = impl.createWfMappings(refAppWF.AppWorkflowMappingDto, oldAppId, newAppId, userId, thisWf.Id, gitMaterialMapping, ctx, isSameProject)
647+
err = impl.createWfInstances(refAppWF.AppWorkflowMappingDto, createWorkflowMappingDto, ctx)
616648
if err != nil {
617649
impl.logger.Errorw("error in creating workflow mapping", "err", err)
618650
return nil, err
@@ -621,7 +653,28 @@ func (impl *AppCloneServiceImpl) CreateWf(oldAppId, newAppId int, userId int32,
621653
return nil, nil
622654
}
623655

624-
func (impl *AppCloneServiceImpl) createWfMappings(refWfMappings []appWorkflow.AppWorkflowMappingDto, oldAppId, newAppId int, userId int32, thisWfId int, gitMaterialMapping map[int]int, ctx context.Context, isSameProject bool) error {
656+
func (impl *AppCloneServiceImpl) createExternalCiAndAppWorkflowMapping(createWorkflowMappingDto CreateWorkflowMappingDto) (int, error) {
657+
dbConnection := impl.pipelineRepository.GetConnection()
658+
tx, err := dbConnection.Begin()
659+
if err != nil {
660+
impl.logger.Errorw("error in beginning transaction", "err", err)
661+
return 0, err
662+
}
663+
// Rollback tx on error.
664+
defer tx.Rollback()
665+
externalCiPipelineId, err := impl.pipelineBuilder.CreateExternalCiAndAppWorkflowMapping(createWorkflowMappingDto.newAppId, createWorkflowMappingDto.newWfId, createWorkflowMappingDto.userId, tx)
666+
if err != nil {
667+
impl.logger.Errorw("error in creating new external ci pipeline and new app workflow mapping", "refAppId", createWorkflowMappingDto.oldAppId, "newAppId", createWorkflowMappingDto.newAppId, "err", err)
668+
return 0, err
669+
}
670+
err = tx.Commit()
671+
if err != nil {
672+
return 0, err
673+
}
674+
return externalCiPipelineId, nil
675+
}
676+
677+
func (impl *AppCloneServiceImpl) createWfInstances(refWfMappings []appWorkflow.AppWorkflowMappingDto, createWorkflowMappingDto CreateWorkflowMappingDto, ctx context.Context) error {
625678
impl.logger.Debugw("wf mapping cloning", "refWfMappings", refWfMappings)
626679
var ciMapping []appWorkflow.AppWorkflowMappingDto
627680
var cdMappings []appWorkflow.AppWorkflowMappingDto
@@ -637,23 +690,30 @@ func (impl *AppCloneServiceImpl) createWfMappings(refWfMappings []appWorkflow.Ap
637690
return fmt.Errorf("unsupported wf type: %s", appWf.Type)
638691
}
639692
}
640-
refApp, err := impl.pipelineBuilder.GetApp(oldAppId)
693+
sourceToNewPipelineIdMapping := make(map[int]int)
694+
refApp, err := impl.pipelineBuilder.GetApp(createWorkflowMappingDto.oldAppId)
695+
if err != nil {
696+
impl.logger.Errorw("error in getting app from refAppId", "refAppId", createWorkflowMappingDto.oldAppId)
697+
return err
698+
}
641699
if len(webhookMappings) > 0 {
642-
if isSameProject {
700+
if createWorkflowMappingDto.isSameProject {
643701
for _, refwebhookMappings := range cdMappings {
644702
cdCloneReq := &cloneCdPipelineRequest{
645-
refCdPipelineId: refwebhookMappings.ComponentId,
646-
refAppId: oldAppId,
647-
appId: newAppId,
648-
userId: userId,
649-
ciPipelineId: 0,
650-
appWfId: thisWfId,
651-
refAppName: refApp.AppName,
703+
refCdPipelineId: refwebhookMappings.ComponentId,
704+
refAppId: createWorkflowMappingDto.oldAppId,
705+
appId: createWorkflowMappingDto.newAppId,
706+
userId: createWorkflowMappingDto.userId,
707+
ciPipelineId: 0,
708+
appWfId: createWorkflowMappingDto.newWfId,
709+
refAppName: refApp.AppName,
710+
sourceToNewPipelineId: sourceToNewPipelineIdMapping,
711+
externalCiPipelineId: createWorkflowMappingDto.externalCiPipelineId,
652712
}
653713
pipeline, err := impl.CreateCdPipeline(cdCloneReq, ctx)
654714
impl.logger.Debugw("cd pipeline created", "pipeline", pipeline)
655715
if err != nil {
656-
impl.logger.Errorw("error in getting cd-pipeling", "err", err)
716+
impl.logger.Errorw("error in getting cd-pipeline", "refAppId", createWorkflowMappingDto.oldAppId, "newAppId", createWorkflowMappingDto.newAppId, "err", err)
657717
return err
658718
}
659719
}
@@ -667,7 +727,7 @@ func (impl *AppCloneServiceImpl) createWfMappings(refWfMappings []appWorkflow.Ap
667727
impl.logger.Warn("no ci pipeline found")
668728
return nil
669729
} else if len(ciMapping) != 1 {
670-
impl.logger.Warn("more than one cd pipeline not supported")
730+
impl.logger.Warn("more than one ci pipeline not supported")
671731
return nil
672732
}
673733

@@ -679,12 +739,12 @@ func (impl *AppCloneServiceImpl) createWfMappings(refWfMappings []appWorkflow.Ap
679739
impl.logger.Debugw("creating ci", "ref", refCiMapping)
680740

681741
cloneCiPipelineRequest := &cloneCiPipelineRequest{
682-
refAppId: oldAppId,
742+
refAppId: createWorkflowMappingDto.oldAppId,
683743
refCiPipelineId: refCiMapping.ComponentId,
684-
userId: userId,
685-
appId: newAppId,
686-
wfId: thisWfId,
687-
gitMaterialMapping: gitMaterialMapping,
744+
userId: createWorkflowMappingDto.userId,
745+
appId: createWorkflowMappingDto.newAppId,
746+
wfId: createWorkflowMappingDto.newWfId,
747+
gitMaterialMapping: createWorkflowMappingDto.gitMaterialMapping,
688748
refAppName: refApp.AppName,
689749
}
690750
ci, err = impl.CreateCiPipeline(cloneCiPipelineRequest)
@@ -694,16 +754,18 @@ func (impl *AppCloneServiceImpl) createWfMappings(refWfMappings []appWorkflow.Ap
694754
}
695755
impl.logger.Debugw("ci created", "ci", ci)
696756
}
697-
if isSameProject {
757+
758+
if createWorkflowMappingDto.isSameProject {
698759
for _, refCdMapping := range cdMappings {
699760
cdCloneReq := &cloneCdPipelineRequest{
700-
refCdPipelineId: refCdMapping.ComponentId,
701-
refAppId: oldAppId,
702-
appId: newAppId,
703-
userId: userId,
704-
ciPipelineId: ci.CiPipelines[0].Id,
705-
appWfId: thisWfId,
706-
refAppName: refApp.AppName,
761+
refCdPipelineId: refCdMapping.ComponentId,
762+
refAppId: createWorkflowMappingDto.oldAppId,
763+
appId: createWorkflowMappingDto.newAppId,
764+
userId: createWorkflowMappingDto.userId,
765+
ciPipelineId: ci.CiPipelines[0].Id,
766+
appWfId: createWorkflowMappingDto.newWfId,
767+
refAppName: refApp.AppName,
768+
sourceToNewPipelineId: sourceToNewPipelineIdMapping,
707769
}
708770
pipeline, err := impl.CreateCdPipeline(cdCloneReq, ctx)
709771
if err != nil {
@@ -868,13 +930,15 @@ func (impl *AppCloneServiceImpl) CreateCiPipeline(req *cloneCiPipelineRequest) (
868930
}
869931

870932
type cloneCdPipelineRequest struct {
871-
refCdPipelineId int
872-
refAppId int
873-
appId int
874-
userId int32
875-
ciPipelineId int
876-
appWfId int
877-
refAppName string
933+
refCdPipelineId int
934+
refAppId int
935+
appId int
936+
userId int32
937+
ciPipelineId int
938+
appWfId int
939+
refAppName string
940+
sourceToNewPipelineId map[int]int
941+
externalCiPipelineId int
878942
}
879943

880944
func (impl *AppCloneServiceImpl) CreateCdPipeline(req *cloneCdPipelineRequest, ctx context.Context) (*bean.CdPipelines, error) {
@@ -892,6 +956,7 @@ func (impl *AppCloneServiceImpl) CreateCdPipeline(req *cloneCdPipelineRequest, c
892956
if refCdPipeline == nil {
893957
return nil, fmt.Errorf("no cd pipeline found")
894958
}
959+
refCdPipeline.SourceToNewPipelineId = req.sourceToNewPipelineId
895960
pipelineName := refCdPipeline.Name
896961
if strings.HasPrefix(pipelineName, req.refAppName) {
897962
pipelineName = strings.Replace(pipelineName, req.refAppName+"-", "", 1)
@@ -922,35 +987,6 @@ func (impl *AppCloneServiceImpl) CreateCdPipeline(req *cloneCdPipelineRequest, c
922987
deploymentAppType = util.PIPELINE_DEPLOYMENT_TYPE_HELM
923988
}
924989

925-
if refCdPipeline.ParentPipelineType == "WEBHOOK" {
926-
cdPipeline := &bean.CDPipelineConfigObject{
927-
Id: 0,
928-
EnvironmentId: refCdPipeline.EnvironmentId,
929-
CiPipelineId: 0,
930-
TriggerType: refCdPipeline.TriggerType,
931-
Name: pipelineName,
932-
Strategies: refCdPipeline.Strategies,
933-
Namespace: refCdPipeline.Namespace,
934-
AppWorkflowId: 0,
935-
DeploymentTemplate: refCdPipeline.DeploymentTemplate,
936-
PreStage: refCdPipeline.PreStage, //FIXME
937-
PostStage: refCdPipeline.PostStage,
938-
PreStageConfigMapSecretNames: refCdPipeline.PreStageConfigMapSecretNames,
939-
PostStageConfigMapSecretNames: refCdPipeline.PostStageConfigMapSecretNames,
940-
RunPostStageInEnv: refCdPipeline.RunPostStageInEnv,
941-
RunPreStageInEnv: refCdPipeline.RunPreStageInEnv,
942-
DeploymentAppType: refCdPipeline.DeploymentAppType,
943-
ParentPipelineId: 0,
944-
ParentPipelineType: refCdPipeline.ParentPipelineType,
945-
}
946-
cdPipelineReq := &bean.CdPipelines{
947-
Pipelines: []*bean.CDPipelineConfigObject{cdPipeline},
948-
AppId: req.appId,
949-
UserId: req.userId,
950-
}
951-
cdPipelineRes, err := impl.pipelineBuilder.CreateCdPipelines(cdPipelineReq, ctx)
952-
return cdPipelineRes, err
953-
}
954990
cdPipeline := &bean.CDPipelineConfigObject{
955991
Id: 0,
956992
EnvironmentId: refCdPipeline.EnvironmentId,
@@ -970,6 +1006,15 @@ func (impl *AppCloneServiceImpl) CreateCdPipeline(req *cloneCdPipelineRequest, c
9701006
DeploymentAppType: deploymentAppType,
9711007
PreDeployStage: refCdPipeline.PreDeployStage,
9721008
PostDeployStage: refCdPipeline.PostDeployStage,
1009+
SourceToNewPipelineId: refCdPipeline.SourceToNewPipelineId,
1010+
RefPipelineId: refCdPipeline.Id,
1011+
ParentPipelineType: refCdPipeline.ParentPipelineType,
1012+
}
1013+
if refCdPipeline.ParentPipelineType == "WEBHOOK" {
1014+
cdPipeline.CiPipelineId = 0
1015+
cdPipeline.ParentPipelineId = req.externalCiPipelineId
1016+
} else if refCdPipeline.ParentPipelineType != appWorkflow.CI_PIPELINE_TYPE {
1017+
cdPipeline.ParentPipelineId = refCdPipeline.ParentPipelineId
9731018
}
9741019
cdPipelineReq := &bean.CdPipelines{
9751020
Pipelines: []*bean.CDPipelineConfigObject{cdPipeline},

pkg/bean/app.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,9 @@ type CDPipelineConfigObject struct {
529529
ManifestStorageType string `json:"manifestStorageType"`
530530
PreDeployStage *bean.PipelineStageDto `json:"preDeployStage,omitempty"`
531531
PostDeployStage *bean.PipelineStageDto `json:"postDeployStage,omitempty"`
532+
SourceToNewPipelineId map[int]int `json:"sourceToNewPipelineId,omitempty"`
533+
RefPipelineId int `json:"refPipelineId,omitempty"`
534+
ExternalCiPipelineId int `json:"externalCiPipelineId,omitempty"`
532535
}
533536

534537
type PreStageConfigMapSecretNames struct {

0 commit comments

Comments
 (0)