From ad4b7196b18352e8d194fa179c9411740bdd31e2 Mon Sep 17 00:00:00 2001 From: Sander Simson Date: Mon, 3 Aug 2026 09:40:06 +0300 Subject: [PATCH] fix: run catch blocks only for failed steps Signed-off-by: Sander Simson --- pkg/runner/runner.go | 7 ++--- pkg/runner/step_test.go | 58 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 60 insertions(+), 5 deletions(-) diff --git a/pkg/runner/runner.go b/pkg/runner/runner.go index d148aca44..6d159212c 100644 --- a/pkg/runner/runner.go +++ b/pkg/runner/runner.go @@ -188,7 +188,7 @@ func (r *runner) run(ctx context.Context, m mainstart, nsOptions v1alpha2.Namesp Id: i + 1, } tc := tc.WithBinding("step", info) - if stop := r.runStep(ctx, t.Cleanup, t.Fail, t.Failed, tc, step, report); stop { + if stop := r.runStep(ctx, t.Cleanup, t.Fail, tc, step, report); stop { return } } @@ -239,7 +239,6 @@ func (r *runner) runStep( ctx context.Context, cleanup func(func()), fail func(), - failed func() bool, tc enginecontext.TestContext, step v1alpha1.TestStep, testReport *model.TestReport, @@ -248,6 +247,7 @@ func (r *runner) runStep( Name: step.Name, StartTime: time.Now(), } + stepFailed := false defer func() { report.EndTime = time.Now() testReport.Add(report) @@ -327,7 +327,7 @@ func (r *runner) runStep( } if catch := tc.Catch(); len(catch) != 0 { defer func() { - if failed() { + if stepFailed { logging.Log(ctx, logging.Catch, logging.BeginStatus, nil, color.BoldFgCyan) defer func() { logging.Log(ctx, logging.Catch, logging.EndStatus, nil, color.BoldFgCyan) @@ -352,6 +352,7 @@ func (r *runner) runStep( for i, operation := range step.Try { continueOnError, outputsTc, err := r.runOperation(ctx, tc, operation, i, cleaner, report) if err != nil { + stepFailed = true fail() if !continueOnError { return true diff --git a/pkg/runner/step_test.go b/pkg/runner/step_test.go index cddc7bf50..49c21331c 100644 --- a/pkg/runner/step_test.go +++ b/pkg/runner/step_test.go @@ -3,6 +3,7 @@ package runner import ( "context" "path/filepath" + "strings" "testing" "time" @@ -785,7 +786,6 @@ func TestStepProcessor_Run(t *testing.T) { } _failed := false fail := func() { _failed = true } - failed := func() bool { return _failed } cleanup := func(func()) {} ctx := context.Background() ctx = logging.WithLogger(ctx, &fakeLogger.Logger{}) @@ -802,9 +802,63 @@ func TestStepProcessor_Run(t *testing.T) { Exec: &config.Spec.Timeouts.Exec, }) runner := runner{} - got := runner.runStep(ctx, cleanup, fail, failed, tcontext, tc.stepSpec, &model.TestReport{}) + got := runner.runStep(ctx, cleanup, fail, tcontext, tc.stepSpec, &model.TestReport{}) assert.Equal(t, tc.want, got) assert.Equal(t, tc.expectedFail, _failed) }) } } + +func TestRunner_CatchIsLocalToStep(t *testing.T) { + logger := &fakeLogger.Logger{} + ctx := logging.WithLogger(context.Background(), logger) + failed := false + fail := func() { + failed = true + } + cleanup := func(func()) {} + continueOnError := true + execTimeout := metav1.Duration{Duration: 5 * time.Second} + + tc := enginecontext.MakeContext( + clock.RealClock{}, + apis.NewBindings(), + mocks.Registry{}, + ).WithTimeouts(v1alpha1.Timeouts{ + Exec: &execTimeout, + }) + + failingStep := v1alpha1.TestStep{ + TestStepSpec: v1alpha1.TestStepSpec{ + Try: []v1alpha1.Operation{{ + OperationBase: v1alpha1.OperationBase{ + ContinueOnError: &continueOnError, + }, + Command: &v1alpha1.Command{ + Entrypoint: "/bin/sh", + Args: []string{"-c", "exit 1"}, + }, + }}, + Catch: []v1alpha1.CatchFinally{{ + Command: &v1alpha1.Command{Entrypoint: "/bin/sh", Args: []string{"-c", "echo failed-step-catch"}}, + }}, + }, + } + successfulStep := v1alpha1.TestStep{ + TestStepSpec: v1alpha1.TestStepSpec{ + Try: []v1alpha1.Operation{{ + Command: &v1alpha1.Command{Entrypoint: "/bin/sh", Args: []string{"-c", "exit 0"}}, + }}, + Catch: []v1alpha1.CatchFinally{{ + Command: &v1alpha1.Command{Entrypoint: "/bin/sh", Args: []string{"-c", "echo successful-step-catch"}}, + }}, + }, + } + + r := runner{} + r.runStep(ctx, cleanup, fail, tc, failingStep, &model.TestReport{}) + r.runStep(ctx, cleanup, fail, tc, successfulStep, &model.TestReport{}) + + assert.True(t, failed) + assert.Equal(t, 1, strings.Count(strings.Join(logger.Logs, "\n"), "CATCH: BEGIN")) +}