Skip to content

Commit eac9dc6

Browse files
feat: multiple images handling for single workflow for ECR Plugin Poll Images (#4027)
* container registry handling for ci_job ci pipeline * Handling multiple images from Ci Complete event * parent ci workflow id * getting workflows without parent_ci_workflow_id * Setting pod status as successful * getting all workflows * adding new api for getting all artifacts * parent ci workflow fetching null * remving parent_ci_workflow_id from workflow_response * Excluding parent workflow ci artifact * query change * query * self review * self review * self review comments * review comments * IT case for fetching ci artifact for ci job type * handling nil pointer for docker registry id * reverting pipeline builder for now * reverting pipeline builder for now * pushing changes for docker config update * checking len before querying * review comments * script number change * review comments logging errors --------- Co-authored-by: ayushmaheshwari <[email protected]>
1 parent fd8d491 commit eac9dc6

File tree

13 files changed

+218
-13
lines changed

13 files changed

+218
-13
lines changed

api/restHandler/app/BuildPipelineRestHandler.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ type DevtronAppBuildRestHandler interface {
5252
HandleWorkflowWebhook(w http.ResponseWriter, r *http.Request)
5353
GetBuildLogs(w http.ResponseWriter, r *http.Request)
5454
FetchWorkflowDetails(w http.ResponseWriter, r *http.Request)
55+
GetArtifactsForCiJob(w http.ResponseWriter, r *http.Request)
5556
// CancelWorkflow CancelBuild
5657
CancelWorkflow(w http.ResponseWriter, r *http.Request)
5758

@@ -1567,6 +1568,51 @@ func (handler PipelineConfigRestHandlerImpl) FetchWorkflowDetails(w http.Respons
15671568
common.WriteJsonResp(w, err, resp, http.StatusOK)
15681569
}
15691570

1571+
func (handler PipelineConfigRestHandlerImpl) GetArtifactsForCiJob(w http.ResponseWriter, r *http.Request) {
1572+
userId, err := handler.userAuthService.GetLoggedInUser(r)
1573+
if userId == 0 || err != nil {
1574+
common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized)
1575+
return
1576+
}
1577+
vars := mux.Vars(r)
1578+
pipelineId, err := strconv.Atoi(vars["pipelineId"])
1579+
if err != nil {
1580+
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
1581+
return
1582+
}
1583+
buildId, err := strconv.Atoi(vars["workflowId"])
1584+
if err != nil || buildId == 0 {
1585+
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
1586+
return
1587+
}
1588+
handler.Logger.Infow("request payload, GetArtifactsForCiJob", "pipelineId", pipelineId, "buildId", buildId, "buildId", buildId)
1589+
ciPipeline, err := handler.ciPipelineRepository.FindById(pipelineId)
1590+
if err != nil {
1591+
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
1592+
return
1593+
}
1594+
//RBAC
1595+
token := r.Header.Get("token")
1596+
object := handler.enforcerUtil.GetAppRBACNameByAppId(ciPipeline.AppId)
1597+
if ok := handler.enforcer.Enforce(token, casbin.ResourceApplications, casbin.ActionGet, object); !ok {
1598+
common.WriteJsonResp(w, err, "Unauthorized User", http.StatusForbidden)
1599+
return
1600+
}
1601+
//RBAC
1602+
resp, err := handler.ciHandler.FetchArtifactsForCiJob(buildId)
1603+
if err != nil {
1604+
handler.Logger.Errorw("service err, FetchArtifactsForCiJob", "err", err, "pipelineId", pipelineId, "buildId", buildId, "buildId", buildId)
1605+
if util.IsErrNoRows(err) {
1606+
err = &util.ApiError{Code: "404", HttpStatusCode: http.StatusNotFound, UserMessage: "no artifact found"}
1607+
common.WriteJsonResp(w, err, nil, http.StatusOK)
1608+
} else {
1609+
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
1610+
}
1611+
return
1612+
}
1613+
common.WriteJsonResp(w, err, resp, http.StatusOK)
1614+
}
1615+
15701616
func (handler PipelineConfigRestHandlerImpl) GetCiPipelineByEnvironment(w http.ResponseWriter, r *http.Request) {
15711617
vars := mux.Vars(r)
15721618
userId, err := handler.userAuthService.GetLoggedInUser(r)

api/router/PipelineConfigRouter.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ func (router PipelineConfigRouterImpl) initPipelineConfigRouter(configRouter *mu
109109
configRouter.Path("/ci-pipeline/refresh-material/{gitMaterialId}").HandlerFunc(router.restHandler.RefreshMaterials).Methods("GET")
110110

111111
configRouter.Path("/{appId}/ci-pipeline/{pipelineId}/workflow/{workflowId}").HandlerFunc(router.restHandler.FetchWorkflowDetails).Methods("GET")
112+
configRouter.Path("/ci-pipeline/{pipelineId}/workflow/{workflowId}/ci-job/artifacts").HandlerFunc(router.restHandler.GetArtifactsForCiJob).Methods("GET")
112113
configRouter.Path("/ci-pipeline/{pipelineId}/artifacts/{workflowId}").HandlerFunc(router.restHandler.DownloadCiWorkflowArtifacts).Methods("GET")
113114

114115
configRouter.Path("/ci-pipeline/{pipelineId}/git-changes/{ciMaterialId}").HandlerFunc(router.restHandler.FetchChanges).Methods("GET")

api/router/pubsub/CiEventHandler.go

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -118,19 +118,26 @@ func (impl *CiEventHandlerImpl) Subscribe() error {
118118
}
119119
} else if ciCompleteEvent.ImageDetailsFromCR != nil {
120120
if len(ciCompleteEvent.ImageDetailsFromCR.ImageDetails) > 0 {
121-
detail := util.GetLatestImageAccToImagePushedAt(ciCompleteEvent.ImageDetailsFromCR.ImageDetails)
122-
request, err := impl.BuildCIArtifactRequestForImageFromCR(detail, ciCompleteEvent.ImageDetailsFromCR.Region, ciCompleteEvent)
121+
imageDetails := util.GetReverseSortedImageDetails(ciCompleteEvent.ImageDetailsFromCR.ImageDetails)
122+
digestWorkflowMap, err := impl.webhookService.HandleMultipleImagesFromEvent(imageDetails, *ciCompleteEvent.WorkflowId)
123123
if err != nil {
124-
impl.logger.Error("Error while creating request for pipelineID", "pipelineId", ciCompleteEvent.PipelineId, "err", err)
124+
impl.logger.Errorw("error in getting digest workflow map", "err", err, "workflowId", ciCompleteEvent.WorkflowId)
125125
return
126126
}
127-
resp, err := impl.webhookService.HandleCiSuccessEvent(ciCompleteEvent.PipelineId, request, detail.ImagePushedAt)
128-
if err != nil {
129-
impl.logger.Error("Error while sending event for CI success for pipelineID", "pipelineId",
130-
ciCompleteEvent.PipelineId, "request", request, "err", err)
131-
return
127+
for _, detail := range imageDetails {
128+
request, err := impl.BuildCIArtifactRequestForImageFromCR(detail, ciCompleteEvent.ImageDetailsFromCR.Region, ciCompleteEvent, digestWorkflowMap[*detail.ImageDigest].Id)
129+
if err != nil {
130+
impl.logger.Error("Error while creating request for pipelineID", "pipelineId", ciCompleteEvent.PipelineId, "err", err)
131+
return
132+
}
133+
resp, err := impl.webhookService.HandleCiSuccessEvent(ciCompleteEvent.PipelineId, request, detail.ImagePushedAt)
134+
if err != nil {
135+
impl.logger.Error("Error while sending event for CI success for pipelineID", "pipelineId",
136+
ciCompleteEvent.PipelineId, "request", request, "err", err)
137+
return
138+
}
139+
impl.logger.Debug("response of handle ci success event for multiple images from plugin", "resp", resp)
132140
}
133-
impl.logger.Debug(resp)
134141
}
135142

136143
} else {
@@ -219,7 +226,7 @@ func (impl *CiEventHandlerImpl) BuildCiArtifactRequest(event CiCompleteEvent) (*
219226
return request, nil
220227
}
221228

222-
func (impl *CiEventHandlerImpl) BuildCIArtifactRequestForImageFromCR(imageDetails types.ImageDetail, region string, event CiCompleteEvent) (*pipeline.CiArtifactWebhookRequest, error) {
229+
func (impl *CiEventHandlerImpl) BuildCIArtifactRequestForImageFromCR(imageDetails types.ImageDetail, region string, event CiCompleteEvent, workflowId int) (*pipeline.CiArtifactWebhookRequest, error) {
223230
if event.TriggeredBy == 0 {
224231
event.TriggeredBy = 1 // system triggered event
225232
}
@@ -229,7 +236,7 @@ func (impl *CiEventHandlerImpl) BuildCIArtifactRequestForImageFromCR(imageDetail
229236
DataSource: event.DataSource,
230237
PipelineName: event.PipelineName,
231238
UserId: event.TriggeredBy,
232-
WorkflowId: event.WorkflowId,
239+
WorkflowId: &workflowId,
233240
IsArtifactUploaded: event.IsArtifactUploaded,
234241
}
235242
return request, nil

internal/sql/repository/CiArtifactRepository.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ type CiArtifactRepository interface {
7171
GetByImageDigest(imageDigest string) (artifact *CiArtifact, err error)
7272
GetByIds(ids []int) ([]*CiArtifact, error)
7373
GetArtifactByCdWorkflowId(cdWorkflowId int) (artifact *CiArtifact, err error)
74+
GetArtifactsByParentCiWorkflowId(parentCiWorkflowId int) ([]string, error)
7475
}
7576

7677
type CiArtifactRepositoryImpl struct {
@@ -569,3 +570,15 @@ func (impl CiArtifactRepositoryImpl) GetArtifactByCdWorkflowId(cdWorkflowId int)
569570
Select()
570571
return artifact, err
571572
}
573+
574+
// GetArtifactsByParentCiWorkflowId will get all artifacts of child workflow sorted by descending order to fetch latest at top, child workflow required for handling container image polling plugin as there can be multiple images from a single parent workflow, which are accommodated in child workflows
575+
func (impl CiArtifactRepositoryImpl) GetArtifactsByParentCiWorkflowId(parentCiWorkflowId int) ([]string, error) {
576+
var artifacts []string
577+
query := "SELECT cia.image FROM ci_artifact cia where cia.ci_workflow_id in (SELECT wf.id from ci_workflow wf where wf.parent_ci_workflow_id = ? ) ORDER BY cia.created_on DESC ;"
578+
_, err := impl.dbConnection.Query(&artifacts, query, parentCiWorkflowId)
579+
if err != nil {
580+
impl.logger.Errorw("error occurred while fetching artifacts for parent ci workflow id", "err", err)
581+
return nil, err
582+
}
583+
return artifacts, err
584+
}

internal/sql/repository/pipelineConfig/CiWorkflowRepository.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ type CiWorkflow struct {
7272
CiBuildType string `sql:"ci_build_type"`
7373
EnvironmentId int `sql:"environment_id"`
7474
ReferenceCiWorkflowId int `sql:"ref_ci_workflow_id"`
75+
ParentCiWorkFlowId int `sql:"parent_ci_workflow_id"`
7576
CiPipeline *CiPipeline
7677
}
7778

@@ -99,6 +100,7 @@ type WorkflowWithArtifact struct {
99100
EnvironmentId int `json:"environmentId"`
100101
EnvironmentName string `json:"environmentName"`
101102
RefCiWorkflowId int `json:"referenceCiWorkflowId"`
103+
ParentCiWorkflowId int `json:"parent_ci_workflow_id"`
102104
}
103105

104106
type GitCommit struct {
@@ -168,9 +170,10 @@ func (impl *CiWorkflowRepositoryImpl) FindByStatusesIn(activeStatuses []string)
168170
return ciWorkFlows, err
169171
}
170172

173+
// FindByPipelineId gets only those workflowWithArtifact whose parent_ci_workflow_id is null, this is done to accommodate multiple ci_artifacts through a single workflow(parent), making child workflows for other ci_artifacts (this has been done due to design understanding and db constraint) single workflow single ci-artifact
171174
func (impl *CiWorkflowRepositoryImpl) FindByPipelineId(pipelineId int, offset int, limit int) ([]WorkflowWithArtifact, error) {
172175
var wfs []WorkflowWithArtifact
173-
queryTemp := "select cia.id as ci_artifact_id, env.environment_name, cia.image, cia.is_artifact_uploaded, wf.*, u.email_id from ci_workflow wf left join users u on u.id = wf.triggered_by left join ci_artifact cia on wf.id = cia.ci_workflow_id left join environment env on env.id = wf.environment_id where wf.ci_pipeline_id = ? order by wf.started_on desc offset ? limit ?;"
176+
queryTemp := "select cia.id as ci_artifact_id, env.environment_name, cia.image, cia.is_artifact_uploaded, wf.*, u.email_id from ci_workflow wf left join users u on u.id = wf.triggered_by left join ci_artifact cia on wf.id = cia.ci_workflow_id left join environment env on env.id = wf.environment_id where wf.ci_pipeline_id = ? and parent_ci_workflow_id is null order by wf.started_on desc offset ? limit ?;"
174177
_, err := impl.dbConnection.Query(&wfs, queryTemp, pipelineId, offset, limit)
175178
if err != nil {
176179
return nil, err

pkg/pipeline/BuildPipelineConfigService.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -802,6 +802,39 @@ func (impl PipelineBuilderImpl) UpdateCiTemplate(updateRequest *bean.CiConfigReq
802802
}
803803

804804
originalCiConf.CiBuildConfig = ciBuildConfig
805+
//TODO: below update code is a hack for ci_job and should be reviewed
806+
807+
// updating ci_template_override for ci_pipeline type = CI_JOB because for this pipeling ci_template and ci_template_override are kept same as
808+
pipelines, err := impl.ciPipelineRepository.FindByAppId(originalCiConf.AppId)
809+
if err != nil && err != pg.ErrNoRows {
810+
impl.logger.Errorw("error in finding pipeline for app")
811+
}
812+
ciPipelineIds := make([]int, 0)
813+
ciPipelineIdsMap := make(map[int]*pipelineConfig.CiPipeline)
814+
for ind, p := range pipelines {
815+
ciPipelineIds[ind] = p.Id
816+
ciPipelineIdsMap[p.Id] = p
817+
}
818+
var ciTemplateOverrides []*pipelineConfig.CiTemplateOverride
819+
if len(ciPipelineIds) > 0 {
820+
ciTemplateOverrides, err = impl.ciTemplateOverrideRepository.FindByCiPipelineIds(ciPipelineIds)
821+
if err != nil && err != pg.ErrNoRows {
822+
impl.logger.Errorw("error in fetching ci tempalate by pipeline ids", "err", err, "ciPipelineIds", ciPipelineIds)
823+
}
824+
}
825+
for _, ciTemplateOverride := range ciTemplateOverrides {
826+
if _, ok := ciPipelineIdsMap[ciTemplateOverride.CiPipelineId]; ok {
827+
if ciPipelineIdsMap[ciTemplateOverride.CiPipelineId].PipelineType == string(bean.CI_JOB) {
828+
ciTemplateOverride.DockerRepository = updateRequest.DockerRepository
829+
ciTemplateOverride.DockerRegistryId = updateRequest.DockerRegistry
830+
_, err = impl.ciTemplateOverrideRepository.Update(ciTemplateOverride)
831+
if err != nil {
832+
impl.logger.Errorw("error in updating ci template for ci_job", "err", err)
833+
}
834+
}
835+
}
836+
}
837+
// update completed for ci_pipeline_type = ci_job
805838

806839
err = impl.CiTemplateHistoryService.SaveHistory(ciTemplateBean, "update")
807840

pkg/pipeline/CiHandler.go

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ type CiHandler interface {
6464
FetchMaterialsByPipelineId(pipelineId int, showAll bool) ([]pipelineConfig.CiPipelineMaterialResponse, error)
6565
FetchMaterialsByPipelineIdAndGitMaterialId(pipelineId int, gitMaterialId int, showAll bool) ([]pipelineConfig.CiPipelineMaterialResponse, error)
6666
FetchWorkflowDetails(appId int, pipelineId int, buildId int) (WorkflowResponse, error)
67-
67+
FetchArtifactsForCiJob(buildId int) (*ArtifactsForCiJob, error)
6868
//FetchBuildById(appId int, pipelineId int) (WorkflowResponse, error)
6969
CancelBuild(workflowId int) (int, error)
7070

@@ -171,6 +171,10 @@ type WorkflowResponse struct {
171171
ReferenceWorkflowId int `json:"referenceWorkflowId"`
172172
}
173173

174+
type ArtifactsForCiJob struct {
175+
Artifacts []string `json:"artifacts"`
176+
}
177+
174178
type GitTriggerInfoResponse struct {
175179
CiMaterials []pipelineConfig.CiPipelineMaterialResponse `json:"ciMaterials"`
176180
TriggeredByEmail string `json:"triggeredByEmail"`
@@ -740,6 +744,17 @@ func (impl *CiHandlerImpl) FetchWorkflowDetails(appId int, pipelineId int, build
740744
return workflowResponse, nil
741745
}
742746

747+
func (impl *CiHandlerImpl) FetchArtifactsForCiJob(buildId int) (*ArtifactsForCiJob, error) {
748+
artifacts, err := impl.ciArtifactRepository.GetArtifactsByParentCiWorkflowId(buildId)
749+
if err != nil {
750+
impl.Logger.Errorw("error in fetching artifacts by parent ci workflow id", "err", err, "buildId", buildId)
751+
return nil, err
752+
}
753+
artifactsResponse := &ArtifactsForCiJob{
754+
Artifacts: artifacts,
755+
}
756+
return artifactsResponse, nil
757+
}
743758
func (impl *CiHandlerImpl) GetRunningWorkflowLogs(pipelineId int, workflowId int) (*bufio.Reader, func() error, error) {
744759
ciWorkflow, err := impl.ciWorkflowRepository.FindById(workflowId)
745760
if err != nil {

pkg/pipeline/CiHandlerIT_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package pipeline
2+
3+
import (
4+
"github.com/devtron-labs/devtron/internal/sql/repository"
5+
"github.com/devtron-labs/devtron/internal/util"
6+
"github.com/devtron-labs/devtron/pkg/sql"
7+
"github.com/stretchr/testify/assert"
8+
"testing"
9+
"time"
10+
)
11+
12+
func TestCiHandlerImpl_FetchArtifactsForCiJob(t *testing.T) {
13+
t.SkipNow()
14+
ciHandler := initCiHandler()
15+
16+
t.Run("Fetch Ci Artifacts For Ci Job type", func(tt *testing.T) {
17+
buildId := 304 // Mocked because child workflows are only created dynamic based on number of images which are available after polling
18+
time.Sleep(5 * time.Second)
19+
_, err := ciHandler.FetchArtifactsForCiJob(buildId)
20+
assert.Nil(t, err)
21+
22+
})
23+
}
24+
25+
func initCiHandler() *CiHandlerImpl {
26+
sugaredLogger, _ := util.InitLogger()
27+
config, _ := sql.GetConfig()
28+
db, _ := sql.NewDbConnection(config, sugaredLogger)
29+
ciArtifactRepositoryImpl := repository.NewCiArtifactRepositoryImpl(db, sugaredLogger)
30+
ciHandlerImpl := NewCiHandlerImpl(sugaredLogger, nil, nil, nil, nil, nil, nil, ciArtifactRepositoryImpl, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
31+
return ciHandlerImpl
32+
}

pkg/pipeline/PipelineBuilder.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,13 +576,15 @@ func (impl *PipelineBuilderImpl) getCiTemplateVariables(appId int) (ciConfig *be
576576
}
577577

578578
var regHost string
579+
var templateDockerRegistryId string
579580
dockerRegistry := template.DockerRegistry
580581
if dockerRegistry != nil {
581582
regHost, err = dockerRegistry.GetRegistryLocation()
582583
if err != nil {
583584
impl.logger.Errorw("invalid reg url", "err", err)
584585
return nil, err
585586
}
587+
templateDockerRegistryId = dockerRegistry.Id
586588
}
587589
ciConfig = &bean.CiConfigRequest{
588590
Id: template.Id,
@@ -599,6 +601,7 @@ func (impl *PipelineBuilderImpl) getCiTemplateVariables(appId int) (ciConfig *be
599601
CreatedBy: template.CreatedBy,
600602
CreatedOn: template.CreatedOn,
601603
CiGitMaterialId: template.GitMaterialId,
604+
DockerRegistry: templateDockerRegistryId,
602605
}
603606
if dockerRegistry != nil {
604607
ciConfig.DockerRegistry = dockerRegistry.Id

pkg/pipeline/WebhookService.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"encoding/json"
2424
"fmt"
2525
"github.com/argoproj/argo-workflows/v3/pkg/apis/workflow/v1alpha1"
26+
"github.com/aws/aws-sdk-go-v2/service/ecr/types"
2627
"github.com/devtron-labs/devtron/client/events"
2728
"github.com/devtron-labs/devtron/internal/sql/repository"
2829
"github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig"
@@ -55,6 +56,7 @@ type WebhookService interface {
5556
HandleCiSuccessEvent(ciPipelineId int, request *CiArtifactWebhookRequest, imagePushedAt *time.Time) (id int, err error)
5657
HandleExternalCiWebhook(externalCiId int, request *CiArtifactWebhookRequest, auth func(token string, projectObject string, envObject string) bool) (id int, err error)
5758
HandleCiStepFailedEvent(ciPipelineId int, request *CiArtifactWebhookRequest) (err error)
59+
HandleMultipleImagesFromEvent(imageDetails []types.ImageDetail, ciWorkflowId int) (map[string]*pipelineConfig.CiWorkflow, error)
5860
}
5961

6062
type WebhookServiceImpl struct {
@@ -399,3 +401,44 @@ func (impl *WebhookServiceImpl) BuildPayload(request *CiArtifactWebhookRequest,
399401
payload.DockerImageUrl = request.Image
400402
return payload
401403
}
404+
405+
// HandleMultipleImagesFromEvent handles multiple images from plugin and creates ci workflow for n-1 images for mapping in ci_artifact
406+
func (impl *WebhookServiceImpl) HandleMultipleImagesFromEvent(imageDetails []types.ImageDetail, ciWorkflowId int) (map[string]*pipelineConfig.CiWorkflow, error) {
407+
ciWorkflow, err := impl.ciWorkflowRepository.FindById(ciWorkflowId)
408+
if err != nil {
409+
impl.logger.Errorw("error in finding ci workflow by id ", "err", err, "ciWorkFlowId", ciWorkflowId)
410+
return nil, err
411+
}
412+
413+
//creating n-1 workflows for rest images, oldest will be mapped to original workflow id.
414+
digestWorkflowMap := make(map[string]*pipelineConfig.CiWorkflow)
415+
// mapping oldest to original ciworkflowId
416+
digestWorkflowMap[*imageDetails[0].ImageDigest] = ciWorkflow
417+
for i := 1; i < len(imageDetails); i++ {
418+
workflow := &pipelineConfig.CiWorkflow{
419+
Name: ciWorkflow.Name + fmt.Sprintf("-child-%d", i),
420+
Status: ciWorkflow.Status,
421+
PodStatus: string(v1alpha1.NodeSucceeded),
422+
StartedOn: time.Now(),
423+
Namespace: ciWorkflow.Namespace,
424+
LogLocation: ciWorkflow.LogLocation,
425+
TriggeredBy: ciWorkflow.TriggeredBy,
426+
CiPipelineId: ciWorkflow.CiPipelineId,
427+
CiArtifactLocation: ciWorkflow.CiArtifactLocation,
428+
BlobStorageEnabled: ciWorkflow.BlobStorageEnabled,
429+
PodName: ciWorkflow.PodName,
430+
CiBuildType: ciWorkflow.CiBuildType,
431+
ParentCiWorkFlowId: ciWorkflow.Id,
432+
GitTriggers: ciWorkflow.GitTriggers,
433+
Message: ciWorkflow.Message,
434+
}
435+
err = impl.ciWorkflowRepository.SaveWorkFlow(workflow)
436+
if err != nil {
437+
impl.logger.Errorw("error in saving workflow for child workflow", "err", err, "parentCiWorkflowId", ciWorkflowId)
438+
return nil, err
439+
}
440+
digestWorkflowMap[*imageDetails[i].ImageDigest] = workflow
441+
442+
}
443+
return digestWorkflowMap, nil
444+
}

0 commit comments

Comments
 (0)