@@ -29,6 +29,7 @@ import (
2929 eventProcessorBean "github.com/devtron-labs/devtron/pkg/eventProcessor/bean"
3030 "github.com/devtron-labs/devtron/pkg/pipeline/adapter"
3131 "github.com/devtron-labs/devtron/pkg/pipeline/constants"
32+ util2 "github.com/devtron-labs/devtron/pkg/pipeline/util"
3233 "github.com/devtron-labs/devtron/pkg/pipeline/workflowStatus"
3334 "github.com/devtron-labs/devtron/pkg/workflow/workflowStatusLatest"
3435 "regexp"
@@ -660,9 +661,10 @@ func (impl *CiHandlerImpl) FetchCiStatusForTriggerViewV1(appId int) ([]*pipeline
660661 return []* pipelineConfig.CiWorkflowStatus {}, nil
661662 }
662663
663- latestStatusEntries , err := impl .workflowStatusLatestService .GetCiWorkflowStatusLatestByPipelineIds (allPipelineIds )
664+ // Prepare pipeline status lookup data (handles linked CI pipelines)
665+ pipelines , pipelineIdForStatus , statusLookupPipelineIds , latestStatusEntries , err := impl .preparePipelineStatusLookup (allPipelineIds )
664666 if err != nil {
665- impl .Logger .Errorw ("error in checking latest status table , falling back to old method" , "appId" , appId , "err" , err )
667+ impl .Logger .Errorw ("error in preparing pipeline status lookup , falling back to old method" , "appId" , appId , "err" , err )
666668 return impl .ciWorkflowRepository .FIndCiWorkflowStatusesByAppId (appId )
667669 }
668670
@@ -674,19 +676,21 @@ func (impl *CiHandlerImpl) FetchCiStatusForTriggerViewV1(appId int) ([]*pipeline
674676 impl .Logger .Errorw ("error in fetching ci workflow status from latest ci workflow entries " , "latestStatusEntries" , latestStatusEntries , "err" , err )
675677 return nil , err
676678 } else {
677- allStatuses = append (allStatuses , statusesFromLatestTable ... )
679+ mappedStatuses := impl .mapStatusesToLinkedPipelines (statusesFromLatestTable , pipelines , pipelineIdForStatus )
680+ allStatuses = append (allStatuses , mappedStatuses ... )
678681 }
679682 }
680683
681- pipelinesNotInLatestTable := impl .getPipelineIdsNotInLatestTable (allPipelineIds , latestStatusEntries )
684+ pipelinesNotInLatestTable := impl .getPipelineIdsNotInLatestTable (statusLookupPipelineIds , latestStatusEntries )
682685
683686 if len (pipelinesNotInLatestTable ) > 0 {
684687 statusesFromOldQuery , err := impl .fetchCiStatusUsingFallbackMethod (pipelinesNotInLatestTable )
685688 if err != nil {
686689 impl .Logger .Errorw ("error in fetching using fallback method by pipelineIds" , "pipelineIds" , pipelinesNotInLatestTable , "err" , err )
687690 return nil , err
688691 } else {
689- allStatuses = append (allStatuses , statusesFromOldQuery ... )
692+ mappedStatuses := impl .mapStatusesToLinkedPipelines (statusesFromOldQuery , pipelines , pipelineIdForStatus )
693+ allStatuses = append (allStatuses , mappedStatuses ... )
690694 }
691695 }
692696
@@ -781,6 +785,38 @@ func (impl *CiHandlerImpl) fetchLastTriggeredWorkflowsHybrid(pipelineIds []int)
781785 return allWorkflows , nil
782786}
783787
788+ // preparePipelineStatusLookup prepares pipeline mapping for linked CI pipelines and returns status lookup data
789+ func (impl * CiHandlerImpl ) preparePipelineStatusLookup (pipelineIds []int ) (pipelines []* pipelineConfig.CiPipeline , pipelineIdForStatus map [int ]int , statusLookupPipelineIds []int , latestStatusEntries []* pipelineConfig.CiWorkflowStatusLatest , err error ) {
790+ pipelines , err = impl .ciPipelineRepository .FindByIdsIn (pipelineIds )
791+ if err != nil {
792+ impl .Logger .Errorw ("error in getting ci pipelines by ids" , "pipelineIds" , pipelineIds , "err" , err )
793+ return nil , nil , nil , nil , err
794+ }
795+
796+ pipelineIdForStatus = make (map [int ]int , len (pipelines )) // linkedPipelineId -> parentPipelineId (or self if not linked)
797+ statusLookupPipelineIds = make ([]int , 0 , len (pipelines ))
798+
799+ for _ , pipeline := range pipelines {
800+ if pipeline .ParentCiPipeline > 0 {
801+ // linked CI pipeline - use parent pipeline ID for status lookup
802+ pipelineIdForStatus [pipeline .Id ] = pipeline .ParentCiPipeline
803+ statusLookupPipelineIds = append (statusLookupPipelineIds , pipeline .ParentCiPipeline )
804+ } else {
805+ // regular CI pipeline - use its own ID
806+ pipelineIdForStatus [pipeline .Id ] = pipeline .Id
807+ statusLookupPipelineIds = append (statusLookupPipelineIds , pipeline .Id )
808+ }
809+ }
810+ statusLookupPipelineIds = util2 .RemoveDuplicateInts (statusLookupPipelineIds )
811+ latestStatusEntries , err = impl .workflowStatusLatestService .GetCiWorkflowStatusLatestByPipelineIds (statusLookupPipelineIds )
812+ if err != nil {
813+ impl .Logger .Errorw ("error in checking latest status table" , "statusLookupPipelineIds" , statusLookupPipelineIds , "err" , err )
814+ return nil , nil , nil , nil , err
815+ }
816+
817+ return pipelines , pipelineIdForStatus , statusLookupPipelineIds , latestStatusEntries , nil
818+ }
819+
784820// getPipelineIdsNotInLatestTable finds pipeline IDs that are NOT in the latest status table
785821func (impl * CiHandlerImpl ) getPipelineIdsNotInLatestTable (allPipelineIds []int , latestStatusEntries []* pipelineConfig.CiWorkflowStatusLatest ) []int {
786822 var pipelinesInLatestTable []int
@@ -801,6 +837,34 @@ func (impl *CiHandlerImpl) getPipelineIdsNotInLatestTable(allPipelineIds []int,
801837 return missingPipelineIds
802838}
803839
840+ // mapStatusesToLinkedPipelines maps parent pipeline statuses back to linked pipelines
841+ func (impl * CiHandlerImpl ) mapStatusesToLinkedPipelines (
842+ statuses []* pipelineConfig.CiWorkflowStatus ,
843+ pipelines []* pipelineConfig.CiPipeline ,
844+ pipelineIdForStatus map [int ]int ,
845+ ) []* pipelineConfig.CiWorkflowStatus {
846+ statusMap := make (map [int ]* pipelineConfig.CiWorkflowStatus )
847+ for _ , status := range statuses {
848+ statusMap [status .CiPipelineId ] = status
849+ }
850+
851+ var result []* pipelineConfig.CiWorkflowStatus
852+ for _ , pipeline := range pipelines {
853+ parentPipelineId := pipelineIdForStatus [pipeline .Id ]
854+ if parentStatus , exists := statusMap [parentPipelineId ]; exists {
855+ linkedStatus := & pipelineConfig.CiWorkflowStatus {
856+ CiPipelineId : pipeline .Id ,
857+ CiPipelineName : pipeline .Name ,
858+ CiStatus : parentStatus .CiStatus ,
859+ StorageConfigured : parentStatus .StorageConfigured ,
860+ CiWorkflowId : parentStatus .CiWorkflowId ,
861+ }
862+ result = append (result , linkedStatus )
863+ }
864+ }
865+ return result
866+ }
867+
804868func (impl * CiHandlerImpl ) FetchCiStatusForTriggerView (appId int ) ([]* pipelineConfig.CiWorkflowStatus , error ) {
805869 var ciWorkflowStatuses []* pipelineConfig.CiWorkflowStatus
806870
@@ -997,6 +1061,10 @@ func (impl *CiHandlerImpl) FetchCiStatusForTriggerViewForEnvironment(request res
9971061 appObjectArr = append (appObjectArr , object )
9981062 }
9991063 appResults , _ := request .CheckAuthBatch (token , appObjectArr , []string {})
1064+
1065+ linkedPipelineDetails := make (map [int ]* pipelineConfig.CiPipeline ) // linkedPipelineId -> pipeline object
1066+ parentToLinkedMap := make (map [int ][]int ) // parentPipelineId -> []linkedPipelineId
1067+
10001068 for _ , ciPipeline := range ciPipelines {
10011069 appObject := objects [ciPipeline .Id ] // here only app permission have to check
10021070 if ! appResults [appObject ] {
@@ -1005,7 +1073,15 @@ func (impl *CiHandlerImpl) FetchCiStatusForTriggerViewForEnvironment(request res
10051073 }
10061074 ciPipelineId := impl .getPipelineIdForTriggerView (ciPipeline )
10071075 ciPipelineIds = append (ciPipelineIds , ciPipelineId )
1076+
1077+ // Store mapping for linked CI pipelines
1078+ if ciPipeline .ParentCiPipeline > 0 {
1079+ linkedPipelineDetails [ciPipeline .Id ] = ciPipeline
1080+ // Add to slice of linked pipelines for this parent
1081+ parentToLinkedMap [ciPipelineId ] = append (parentToLinkedMap [ciPipelineId ], ciPipeline .Id )
1082+ }
10081083 }
1084+
10091085 if len (ciPipelineIds ) == 0 {
10101086 return ciWorkflowStatuses , nil
10111087 }
@@ -1015,24 +1091,34 @@ func (impl *CiHandlerImpl) FetchCiStatusForTriggerViewForEnvironment(request res
10151091 return ciWorkflowStatuses , err
10161092 }
10171093
1018- notTriggeredWorkflows := make (map [int ]bool )
1094+ // create workflow map for quick lookup
1095+ workflowMap := make (map [int ]* pipelineConfig.CiWorkflow )
1096+ for _ , workflow := range latestCiWorkflows {
1097+ workflowMap [workflow .CiPipelineId ] = workflow
1098+ }
1099+
1100+ triggeredWorkflows := make (map [int ]bool )
10191101
10201102 for _ , ciWorkflow := range latestCiWorkflows {
1021- ciWorkflowStatus := & pipelineConfig.CiWorkflowStatus {}
1022- ciWorkflowStatus .CiPipelineId = ciWorkflow .CiPipelineId
1023- ciWorkflowStatus .CiPipelineName = ciWorkflow .CiPipeline .Name
1024- ciWorkflowStatus .CiStatus = ciWorkflow .Status
1025- ciWorkflowStatus .StorageConfigured = ciWorkflow .BlobStorageEnabled
1026- ciWorkflowStatus .CiWorkflowId = ciWorkflow .Id
1027- ciWorkflowStatuses = append (ciWorkflowStatuses , ciWorkflowStatus )
1028- notTriggeredWorkflows [ciWorkflowStatus .CiPipelineId ] = true
1103+ // check if this workflow belongs to a parent pipeline that has linked CIs
1104+ if linkedPipelineIds , isParentOfLinked := parentToLinkedMap [ciWorkflow .CiPipelineId ]; isParentOfLinked {
1105+ // create workflow status for each linked pipeline
1106+ for _ , linkedPipelineId := range linkedPipelineIds {
1107+ ciWorkflowStatus := adapter .GetCiWorkflowStatusForLinkedCiPipeline (linkedPipelineId , linkedPipelineDetails [linkedPipelineId ].Name , ciWorkflow )
1108+ ciWorkflowStatuses = append (ciWorkflowStatuses , ciWorkflowStatus )
1109+ }
1110+ } else {
1111+ ciWorkflowStatus := adapter .GetCiWorkflowStatusFromCiWorkflow (ciWorkflow )
1112+ ciWorkflowStatuses = append (ciWorkflowStatuses , ciWorkflowStatus )
1113+ }
1114+ triggeredWorkflows [ciWorkflow .CiPipelineId ] = true
10291115 }
10301116
10311117 for _ , ciPipelineId := range ciPipelineIds {
1032- if _ , ok := notTriggeredWorkflows [ciPipelineId ]; ! ok {
1118+ if _ , ok := triggeredWorkflows [ciPipelineId ]; ! ok {
10331119 ciWorkflowStatus := & pipelineConfig.CiWorkflowStatus {}
10341120 ciWorkflowStatus .CiPipelineId = ciPipelineId
1035- ciWorkflowStatus .CiStatus = "Not Triggered"
1121+ ciWorkflowStatus .CiStatus = pipelineConfigBean . NotTriggered
10361122 ciWorkflowStatuses = append (ciWorkflowStatuses , ciWorkflowStatus )
10371123 }
10381124 }
0 commit comments