Skip to content
Draft
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
20 changes: 20 additions & 0 deletions src/cmd/cli/command/compose.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ func makeComposeUpCmd() *cobra.Command {
return loadErr
}

// Don't trigger the debugger if the operation was canceled by the user (e.g., Ctrl-C)
if errors.Is(ctx.Err(), context.Canceled) {
return loadErr
}

term.Error("Cannot load project:", loadErr)
project, err := loader.CreateProjectForDebug()
if err != nil {
Expand Down Expand Up @@ -224,12 +229,22 @@ func handleComposeUpErr(ctx context.Context, err error, project *compose.Project
return err
}

// Don't trigger the debugger if the operation was canceled by the user (e.g., Ctrl-C)
if errors.Is(ctx.Err(), context.Canceled) {
return err
}

term.Error("Error:", cliClient.PrettyError(err))
track.Evt("Debug Prompted", P("composeErr", err))
return cli.InteractiveDebugForClientError(ctx, global.Client, project, err)
}

func handleTailAndMonitorErr(ctx context.Context, err error, client *cliClient.GrpcClient, debugConfig cli.DebugConfig) {
// Don't trigger the debugger if the operation was canceled by the user (e.g., Ctrl-C)
if errors.Is(ctx.Err(), context.Canceled) {
return
}

var errDeploymentFailed cliClient.ErrDeploymentFailed
if errors.As(err, &errDeploymentFailed) {
// Tail got canceled because of deployment failure: prompt to show the debugger
Expand Down Expand Up @@ -442,6 +457,11 @@ func makeComposeConfigCmd() *cobra.Command {
return loadErr
}

// Don't trigger the debugger if the operation was canceled by the user (e.g., Ctrl-C)
if errors.Is(ctx.Err(), context.Canceled) {
return loadErr
}

term.Error("Cannot load project:", loadErr)
project, err := loader.CreateProjectForDebug()
if err != nil {
Expand Down
71 changes: 71 additions & 0 deletions src/cmd/cli/command/compose_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
package command

import (
"context"
"errors"
"testing"

"github.com/DefangLabs/defang/src/pkg/cli"
cliClient "github.com/DefangLabs/defang/src/pkg/cli/client"
"github.com/DefangLabs/defang/src/pkg/cli/compose"
)

func TestInitializeTailCmd(t *testing.T) {
Expand All @@ -14,3 +20,68 @@ func TestInitializeTailCmd(t *testing.T) {
}
})
}

func TestHandleTailAndMonitorErr_ContextCanceled(t *testing.T) {
// Create a canceled context to simulate Ctrl-C
ctx, cancel := context.WithCancel(context.Background())
cancel()

// Create a deployment failure error
err := cliClient.ErrDeploymentFailed{
Service: "test-service",
Message: "deployment failed",
}

// Create a debug config
debugConfig := cli.DebugConfig{
Deployment: "test-deployment",
Project: &compose.Project{Name: "test-project"},
}

// This should not panic or prompt for debugging
handleTailAndMonitorErr(ctx, err, nil, debugConfig)
}

func TestHandleTailAndMonitorErr_NoContextCancellation(t *testing.T) {
// Create a normal context (not canceled)
ctx := context.Background()

// Create a deployment failure error
err := cliClient.ErrDeploymentFailed{
Service: "test-service",
Message: "deployment failed",
}

// Create a debug config
debugConfig := cli.DebugConfig{
Deployment: "test-deployment",
Project: &compose.Project{Name: "test-project"},
}

// Set NonInteractive to true to avoid actually prompting for debugging
oldNonInteractive := global.NonInteractive
global.NonInteractive = true
defer func() { global.NonInteractive = oldNonInteractive }()

// This should print a hint but not prompt for interactive debugging
handleTailAndMonitorErr(ctx, err, nil, debugConfig)
}

func TestHandleComposeUpErr_ContextCanceled(t *testing.T) {
// Create a canceled context to simulate Ctrl-C
ctx, cancel := context.WithCancel(context.Background())
cancel()

// Create a generic error
err := errors.New("some error during compose up")

// Create a test project
project := &compose.Project{Name: "test-project"}

// This should return the error without prompting for debugging
result := handleComposeUpErr(ctx, err, project, nil)

if result != err {
t.Errorf("Expected error to be returned as-is, got: %v", result)
}
}