// Copyright 2022 Harness Inc. All rights reserved. // Use of this source code is governed by the Polyform Free Trial License // that can be found in the LICENSE.md file for this repository. package manager import ( "context" "time" "github.com/harness/gitness/internal/pipeline/events" "github.com/harness/gitness/internal/pipeline/scheduler" "github.com/harness/gitness/internal/store" "github.com/harness/gitness/livelog" gitness_store "github.com/harness/gitness/store" "github.com/harness/gitness/types" "github.com/harness/gitness/types/enum" "github.com/rs/zerolog/log" ) type teardown struct { Executions store.ExecutionStore Events events.EventsStreamer Logs livelog.LogStream Scheduler scheduler.Scheduler Repos store.RepoStore Steps store.StepStore Stages store.StageStore } func (t *teardown) do(ctx context.Context, stage *types.Stage) error { log := log.With(). Int64("stage.id", stage.ID). Logger() log.Debug().Msg("manager: stage is complete. teardown") execution, err := t.Executions.Find(noContext, stage.ExecutionID) if err != nil { log.Error().Err(err).Msg("manager: cannot find the execution") return err } log = log.With(). Int64("execution.number", execution.Number). Int64("execution.id", execution.ID). Int64("repo.id", execution.RepoID). Str("stage.status", stage.Status). Logger() repo, err := t.Repos.Find(noContext, execution.RepoID) if err != nil { log.Error().Err(err).Msg("manager: cannot find the repository") return err } for _, step := range stage.Steps { if len(step.Error) > 500 { step.Error = step.Error[:500] } err := t.Steps.Update(noContext, step) if err != nil { log = log.With(). Str("step.name", step.Name). Int64("step.id", step.ID). Err(err). Logger() log.Error().Msg("manager: cannot persist the step") return err } } if len(stage.Error) > 500 { stage.Error = stage.Error[:500] } err = t.Stages.Update(noContext, stage) if err != nil { log.Error().Err(err). Msg("manager: cannot update the stage") return err } for _, step := range stage.Steps { t.Logs.Delete(noContext, step.ID) } stages, err := t.Stages.ListWithSteps(noContext, execution.ID) if err != nil { log.Warn().Err(err). Msg("manager: cannot get stages") return err } if isexecutionComplete(stages) == false { log.Warn().Err(err). Msg("manager: execution pending completion of additional stages") return nil } log.Info().Msg("manager: execution is finished, teardown") execution.Status = enum.CIStatusSuccess execution.Finished = time.Now().UnixMilli() for _, sibling := range stages { if sibling.Status == enum.CIStatusKilled { execution.Status = enum.CIStatusKilled break } if sibling.Status == enum.CIStatusFailure { execution.Status = enum.CIStatusFailure break } if sibling.Status == enum.CIStatusError { execution.Status = enum.CIStatusError break } } if execution.Started == 0 { execution.Started = execution.Finished } err = t.Executions.Update(noContext, execution) if err == gitness_store.ErrVersionConflict { log.Warn().Err(err). Msg("manager: execution updated by another goroutine") return nil } if err != nil { log.Warn().Err(err). Msg("manager: cannot update the execution") return err } execution.Stages = stages err = t.Events.Publish(noContext, repo.ParentID, executionEvent(enum.ExecutionCompleted, execution)) if err != nil { log.Warn().Err(err). Msg("manager: could not publish execution completed event") } return nil } func isexecutionComplete(stages []*types.Stage) bool { for _, stage := range stages { switch stage.Status { case enum.CIStatusPending, enum.CIStatusRunning, enum.CIStatusWaitingOnDeps, enum.CIStatusDeclined, enum.CIStatusBlocked: return false } } return true }