func()

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)
}