Skip to content
Merged
2 changes: 1 addition & 1 deletion cmd/external-app/wire_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

74 changes: 69 additions & 5 deletions pkg/pipeline/CiHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
eventProcessorBean "github.com/devtron-labs/devtron/pkg/eventProcessor/bean"
"github.com/devtron-labs/devtron/pkg/pipeline/adapter"
"github.com/devtron-labs/devtron/pkg/pipeline/constants"
util2 "github.com/devtron-labs/devtron/pkg/pipeline/util"
"github.com/devtron-labs/devtron/pkg/pipeline/workflowStatus"
"github.com/devtron-labs/devtron/pkg/workflow/workflowStatusLatest"
"regexp"
Expand Down Expand Up @@ -660,9 +661,10 @@ func (impl *CiHandlerImpl) FetchCiStatusForTriggerViewV1(appId int) ([]*pipeline
return []*pipelineConfig.CiWorkflowStatus{}, nil
}

latestStatusEntries, err := impl.workflowStatusLatestService.GetCiWorkflowStatusLatestByPipelineIds(allPipelineIds)
// Prepare pipeline status lookup data (handles linked CI pipelines)
pipelines, pipelineIdForStatus, statusLookupPipelineIds, latestStatusEntries, err := impl.preparePipelineStatusLookup(allPipelineIds)
if err != nil {
impl.Logger.Errorw("error in checking latest status table, falling back to old method", "appId", appId, "err", err)
impl.Logger.Errorw("error in preparing pipeline status lookup, falling back to old method", "appId", appId, "err", err)
return impl.ciWorkflowRepository.FIndCiWorkflowStatusesByAppId(appId)
}

Expand All @@ -674,19 +676,21 @@ func (impl *CiHandlerImpl) FetchCiStatusForTriggerViewV1(appId int) ([]*pipeline
impl.Logger.Errorw("error in fetching ci workflow status from latest ci workflow entries ", "latestStatusEntries", latestStatusEntries, "err", err)
return nil, err
} else {
allStatuses = append(allStatuses, statusesFromLatestTable...)
mappedStatuses := impl.mapStatusesToLinkedPipelines(statusesFromLatestTable, pipelines, pipelineIdForStatus)
allStatuses = append(allStatuses, mappedStatuses...)
}
}

pipelinesNotInLatestTable := impl.getPipelineIdsNotInLatestTable(allPipelineIds, latestStatusEntries)
pipelinesNotInLatestTable := impl.getPipelineIdsNotInLatestTable(statusLookupPipelineIds, latestStatusEntries)

if len(pipelinesNotInLatestTable) > 0 {
statusesFromOldQuery, err := impl.fetchCiStatusUsingFallbackMethod(pipelinesNotInLatestTable)
if err != nil {
impl.Logger.Errorw("error in fetching using fallback method by pipelineIds", "pipelineIds", pipelinesNotInLatestTable, "err", err)
return nil, err
} else {
allStatuses = append(allStatuses, statusesFromOldQuery...)
mappedStatuses := impl.mapStatusesToLinkedPipelines(statusesFromOldQuery, pipelines, pipelineIdForStatus)
allStatuses = append(allStatuses, mappedStatuses...)
}
}

Expand Down Expand Up @@ -781,6 +785,38 @@ func (impl *CiHandlerImpl) fetchLastTriggeredWorkflowsHybrid(pipelineIds []int)
return allWorkflows, nil
}

// preparePipelineStatusLookup prepares pipeline mapping for linked CI pipelines and returns status lookup data
func (impl *CiHandlerImpl) preparePipelineStatusLookup(pipelineIds []int) (pipelines []*pipelineConfig.CiPipeline, pipelineIdForStatus map[int]int, statusLookupPipelineIds []int, latestStatusEntries []*pipelineConfig.CiWorkflowStatusLatest, err error) {
pipelines, err = impl.ciPipelineRepository.FindByIdsIn(pipelineIds)
if err != nil {
impl.Logger.Errorw("error in getting ci pipelines by ids", "pipelineIds", pipelineIds, "err", err)
return nil, nil, nil, nil, err
}

pipelineIdForStatus = make(map[int]int, len(pipelines)) // linkedPipelineId -> parentPipelineId (or self if not linked)
statusLookupPipelineIds = make([]int, 0, len(pipelines))

for _, pipeline := range pipelines {
if pipeline.ParentCiPipeline > 0 {
// linked CI pipeline - use parent pipeline ID for status lookup
pipelineIdForStatus[pipeline.Id] = pipeline.ParentCiPipeline
statusLookupPipelineIds = append(statusLookupPipelineIds, pipeline.ParentCiPipeline)
} else {
// regular CI pipeline - use its own ID
pipelineIdForStatus[pipeline.Id] = pipeline.Id
statusLookupPipelineIds = append(statusLookupPipelineIds, pipeline.Id)
}
}
statusLookupPipelineIds = util2.RemoveDuplicateInts(statusLookupPipelineIds)
latestStatusEntries, err = impl.workflowStatusLatestService.GetCiWorkflowStatusLatestByPipelineIds(statusLookupPipelineIds)
if err != nil {
impl.Logger.Errorw("error in checking latest status table", "statusLookupPipelineIds", statusLookupPipelineIds, "err", err)
return nil, nil, nil, nil, err
}

return pipelines, pipelineIdForStatus, statusLookupPipelineIds, latestStatusEntries, nil
}

// getPipelineIdsNotInLatestTable finds pipeline IDs that are NOT in the latest status table
func (impl *CiHandlerImpl) getPipelineIdsNotInLatestTable(allPipelineIds []int, latestStatusEntries []*pipelineConfig.CiWorkflowStatusLatest) []int {
var pipelinesInLatestTable []int
Expand All @@ -801,6 +837,34 @@ func (impl *CiHandlerImpl) getPipelineIdsNotInLatestTable(allPipelineIds []int,
return missingPipelineIds
}

// mapStatusesToLinkedPipelines maps parent pipeline statuses back to linked pipelines
func (impl *CiHandlerImpl) mapStatusesToLinkedPipelines(
statuses []*pipelineConfig.CiWorkflowStatus,
pipelines []*pipelineConfig.CiPipeline,
pipelineIdForStatus map[int]int,
) []*pipelineConfig.CiWorkflowStatus {
statusMap := make(map[int]*pipelineConfig.CiWorkflowStatus)
for _, status := range statuses {
statusMap[status.CiPipelineId] = status
}

var result []*pipelineConfig.CiWorkflowStatus
for _, pipeline := range pipelines {
parentPipelineId := pipelineIdForStatus[pipeline.Id]
if parentStatus, exists := statusMap[parentPipelineId]; exists {
linkedStatus := &pipelineConfig.CiWorkflowStatus{
CiPipelineId: pipeline.Id,
CiPipelineName: pipeline.Name,
CiStatus: parentStatus.CiStatus,
StorageConfigured: parentStatus.StorageConfigured,
CiWorkflowId: parentStatus.CiWorkflowId,
}
result = append(result, linkedStatus)
}
}
return result
}

func (impl *CiHandlerImpl) FetchCiStatusForTriggerView(appId int) ([]*pipelineConfig.CiWorkflowStatus, error) {
var ciWorkflowStatuses []*pipelineConfig.CiWorkflowStatus

Expand Down
13 changes: 13 additions & 0 deletions pkg/pipeline/util/CiCdUtil.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,16 @@ func GetWorkflowCacheConfigWithBackwardCompatibility(WorkflowCacheConfig common.
}
}
}

// RemoveDuplicateInts helper function to remove duplicate integers from slice
func RemoveDuplicateInts(slice []int) []int {
keys := make(map[int]bool)
var result []int
for _, item := range slice {
if !keys[item] {
keys[item] = true
result = append(result, item)
}
}
return result
}
2 changes: 1 addition & 1 deletion wire_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading