···
io.Copy(os.Stdout, reader)
err = e.StartSteps(ctx, w.Steps, wid, w.Image)
if errors.Is(err, ErrTimedOut) {
···
// All other errors are bubbled up.
// Fixed version of the step execution logic
func (e *Engine) StartSteps(ctx context.Context, steps []models.Step, wid models.WorkflowId, image string) error {
-
stepTimeoutStr := e.cfg.Pipelines.StepTimeout
-
stepTimeout, err := time.ParseDuration(stepTimeoutStr)
-
e.l.Error("failed to parse step timeout", "error", err, "timeout", stepTimeoutStr)
-
stepTimeout = 5 * time.Minute
-
e.l.Info("using step timeout", "timeout", stepTimeout)
for stepIdx, step := range steps {
envs := ConstructEnvs(step.Environment)
envs.AddEnv("HOME", workspaceDir)
e.l.Debug("envs for step", "step", step.Name, "envs", envs.Slice())
···
}, hostConfig, nil, nil, "")
return fmt.Errorf("creating container: %w", err)
···
return fmt.Errorf("connecting network: %w", err)
-
stepCtx, stepCancel := context.WithTimeout(ctx, stepTimeout)
-
err = e.docker.ContainerStart(stepCtx, resp.ID, container.StartOptions{})
e.l.Info("started container", "name", resp.ID, "step", step.Name)
···
// start tailing logs in background
tailDone := make(chan error, 1)
-
tailDone <- e.TailStep(stepCtx, resp.ID, wid, stepIdx)
// wait for container completion or timeout
···
-
state, waitErr = e.WaitStep(stepCtx, resp.ID)
···
// wait for tailing to complete
-
e.l.Warn("step timed out; killing container", "container", resp.ID, "timeout", stepTimeout)
-
_ = e.DestroyStep(ctx, resp.ID)
// wait for both goroutines to finish
···
io.Copy(os.Stdout, reader)
+
workflowTimeoutStr := e.cfg.Pipelines.WorkflowTimeout
+
workflowTimeout, err := time.ParseDuration(workflowTimeoutStr)
+
e.l.Error("failed to parse workflow timeout", "error", err, "timeout", workflowTimeoutStr)
+
workflowTimeout = 5 * time.Minute
+
e.l.Info("using workflow timeout", "timeout", workflowTimeout)
+
ctx, cancel := context.WithTimeout(ctx, workflowTimeout)
err = e.StartSteps(ctx, w.Steps, wid, w.Image)
if errors.Is(err, ErrTimedOut) {
···
// All other errors are bubbled up.
// Fixed version of the step execution logic
func (e *Engine) StartSteps(ctx context.Context, steps []models.Step, wid models.WorkflowId, image string) error {
for stepIdx, step := range steps {
envs := ConstructEnvs(step.Environment)
envs.AddEnv("HOME", workspaceDir)
e.l.Debug("envs for step", "step", step.Name, "envs", envs.Slice())
···
}, hostConfig, nil, nil, "")
+
defer e.DestroyStep(ctx, resp.ID)
return fmt.Errorf("creating container: %w", err)
···
return fmt.Errorf("connecting network: %w", err)
+
err = e.docker.ContainerStart(ctx, resp.ID, container.StartOptions{})
e.l.Info("started container", "name", resp.ID, "step", step.Name)
···
// start tailing logs in background
tailDone := make(chan error, 1)
+
tailDone <- e.TailStep(ctx, resp.ID, wid, stepIdx)
// wait for container completion or timeout
···
+
state, waitErr = e.WaitStep(ctx, resp.ID)
···
// wait for tailing to complete
+
e.l.Warn("step timed out; killing container", "container", resp.ID, "step", step.Name)
+
err = e.DestroyStep(context.Background(), resp.ID)
+
e.l.Error("failed to destroy step", "container", resp.ID, "error", err)
// wait for both goroutines to finish