Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions cli/azd/cmd/middleware/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"log"
"slices"

"github.com/AlecAivazis/survey/v2/terminal"
"github.com/azure/azure-dev/cli/azd/cmd/actions"
"github.com/azure/azure-dev/cli/azd/pkg/ioc"
"github.com/spf13/pflag"
Expand Down Expand Up @@ -99,6 +100,11 @@ func (r *MiddlewareRunner) RunAction(

var middleware Middleware
if err := actionContainer.ResolveNamed(middlewareName, &middleware); err != nil {
// Check if the error is an interrupt error (user cancelled a prompt)
// In this case, we should not continue and return the error immediately
if errors.Is(err, terminal.InterruptErr) {
return nil, err
}
Comment on lines +103 to +107
Copy link
Contributor

@weikanglim weikanglim Jan 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would we consider terminating on all errors here? I could imagine if the LoginGuard for example, were to fail to construct, we wouldn't want to skip the guard completely and run the main logic.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Separate proposal #6517

log.Printf("failed resolving middleware '%s' : %v\n", middlewareName, err)
}

Expand Down
36 changes: 36 additions & 0 deletions cli/azd/cmd/middleware/middleware_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"fmt"
"testing"

"github.com/AlecAivazis/survey/v2/terminal"
"github.com/azure/azure-dev/cli/azd/cmd/actions"
"github.com/azure/azure-dev/cli/azd/test/mocks"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -161,6 +162,41 @@ func Test_Middleware_RunAction(t *testing.T) {
require.Nil(t, result)
require.NoError(t, err)
})

// Test that interrupt errors during middleware resolution are propagated and not ignored
t.Run("interrupt error during middleware resolution", func(t *testing.T) {
mockContext := mocks.NewMockContext(context.Background())
middlewareRunner := NewMiddlewareRunner(mockContext.Container)

// Register a middleware constructor that returns an interrupt error
// This simulates what happens when a user cancels a prompt during dependency initialization
err := middlewareRunner.Use("interrupt-middleware", func() (Middleware, error) {
return nil, terminal.InterruptErr
})
require.NoError(t, err)

// Register an action that should not run if interrupt occurs
actionRan := false
err = mockContext.Container.RegisterNamedTransient("test-action", func() actions.Action {
return &testAction{
runFunc: func(ctx context.Context) (*actions.ActionResult, error) {
actionRan = true
return &actions.ActionResult{
Message: &actions.ResultMessage{Header: "Action"},
}, nil
},
}
})
require.NoError(t, err)

result, err := middlewareRunner.RunAction(*mockContext.Context, &Options{Name: "test"}, "test-action")

// Verify that the interrupt error is returned and the action does not run
require.Nil(t, result)
require.Error(t, err)
require.ErrorIs(t, err, terminal.InterruptErr)
require.False(t, actionRan)
})
}

func registerAction(t *testing.T, mockContext *mocks.MockContext, name string, runLog *[]string) *bool {
Expand Down
4 changes: 2 additions & 2 deletions cli/azd/extensions/azure.ai.finetune/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ require (
github.com/braydonk/yaml v0.9.0
github.com/fatih/color v1.18.0
github.com/openai/openai-go/v3 v3.2.0
github.com/sethvargo/go-retry v0.3.0
github.com/spf13/cobra v1.10.1
gopkg.in/yaml.v3 v3.0.1
)

require (
Expand Down Expand Up @@ -61,7 +63,6 @@ require (
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/sethvargo/go-retry v0.3.0 // indirect
github.com/spf13/pflag v1.0.10 // indirect
github.com/stretchr/testify v1.11.1 // indirect
github.com/theckman/yacspin v0.13.12 // indirect
Expand All @@ -86,5 +87,4 @@ require (
google.golang.org/genproto/googleapis/rpc v0.0.0-20251007200510-49b9836ed3ff // indirect
google.golang.org/grpc v1.76.0 // indirect
google.golang.org/protobuf v1.36.10 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
Loading