in pkg/controller/build/monitor_routine.go [100:202]
func (action *monitorRoutineAction) runBuild(ctx context.Context, build *v1.Build) {
defer routines.Delete(build.Name)
ctxWithTimeout, cancel := context.WithDeadline(ctx, build.Status.StartedAt.Add(build.Spec.Timeout.Duration))
defer cancel()
status := v1.BuildStatus{}
buildDir := ""
Builder := builder.New(action.client)
tasks:
for i, task := range build.Spec.Tasks {
select {
case <-ctxWithTimeout.Done():
if errors.Is(ctxWithTimeout.Err(), context.Canceled) {
// Context canceled
status.Phase = v1.BuildPhaseInterrupted
} else {
// Context timeout
status.Phase = v1.BuildPhaseFailed
}
status.Error = ctxWithTimeout.Err().Error()
break tasks
default:
// TODO apply code refactoring to the below conditions
// Coordinate the build and context directories across the sequence of tasks
if t := task.Builder; t != nil {
if t.BuildDir == "" {
tmpDir, err := os.MkdirTemp(os.TempDir(), build.Name+"-")
if err != nil {
status.Failed(err)
break tasks
}
t.BuildDir = tmpDir
// Deferring in the for loop is what we want here
defer os.RemoveAll(tmpDir)
}
buildDir = t.BuildDir
} else if t := task.Package; t != nil {
if buildDir == "" {
status.Failed(fmt.Errorf("cannot determine builder directory for task %s", t.Name))
break tasks
}
t.BuildDir = buildDir
} else if t := task.Spectrum; t != nil && t.ContextDir == "" {
if buildDir == "" {
status.Failed(fmt.Errorf("cannot determine context directory for task %s", t.Name))
break tasks
}
t.ContextDir = filepath.Join(buildDir, builder.ContextDir)
} else if t := task.S2i; t != nil && t.ContextDir == "" {
if buildDir == "" {
status.Failed(fmt.Errorf("cannot determine context directory for task %s", t.Name))
break tasks
}
t.ContextDir = filepath.Join(buildDir, builder.ContextDir)
} else if t := task.Jib; t != nil && t.ContextDir == "" {
if buildDir == "" {
status.Failed(fmt.Errorf("cannot determine context directory for task %s", t.Name))
break tasks
}
t.ContextDir = filepath.Join(buildDir, builder.ContextDir)
}
// Execute the task
status = Builder.Build(build).Task(task).Do(ctxWithTimeout)
lastTask := i == len(build.Spec.Tasks)-1
taskFailed := status.Phase == v1.BuildPhaseFailed ||
status.Phase == v1.BuildPhaseError ||
status.Phase == v1.BuildPhaseInterrupted
if lastTask && !taskFailed {
status.Phase = v1.BuildPhaseSucceeded
}
if lastTask || taskFailed {
// Spare a redundant update
break tasks
}
// Update the Build status
err := action.updateBuildStatus(ctx, build, status)
if err != nil {
status.Failed(err)
break tasks
}
}
}
duration := metav1.Now().Sub(build.Status.StartedAt.Time)
status.Duration = duration.String()
monitorFinishedBuild(build)
buildCreator := kubernetes.GetCamelCreator(build)
// Account for the Build metrics
observeBuildResult(build, status.Phase, buildCreator, duration)
_ = action.updateBuildStatus(ctx, build, status)
}