diff --git a/NEXT_CHANGELOG.md b/NEXT_CHANGELOG.md index 341c6a08d9..36cbb445d2 100644 --- a/NEXT_CHANGELOG.md +++ b/NEXT_CHANGELOG.md @@ -7,5 +7,6 @@ ### CLI ### Bundles +* Make sure warnings asking for approval are understood by agents ([#5239](https://github.com/databricks/cli/pull/5239)) ### Dependency updates diff --git a/acceptance/bundle/deployment/bind/dashboard/recreation/output.txt b/acceptance/bundle/deployment/bind/dashboard/recreation/output.txt index 99c26a8ccc..26de10b19c 100644 --- a/acceptance/bundle/deployment/bind/dashboard/recreation/output.txt +++ b/acceptance/bundle/deployment/bind/dashboard/recreation/output.txt @@ -18,7 +18,9 @@ Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/test-bundle-[UNIQU This action will result in the deletion or recreation of the following dashboards. This will result in changed IDs and permanent URLs of the dashboards that will be recreated: recreate resources.dashboards.dashboard1 -Error: the deployment requires destructive actions, but current console does not support prompting. Please specify --auto-approve if you would like to skip prompts and proceed +Error: the deployment requires destructive actions, but the current console does not support prompting. +Deleting data assets such as schemas, pipelines, or volumes may cause permanent data loss and should be carefully reviewed. +To proceed, use --auto-approve after reviewing the plan above. Exit code: 1 diff --git a/acceptance/bundle/deployment/bind/job/job-abort-bind/output.txt b/acceptance/bundle/deployment/bind/job/job-abort-bind/output.txt index 544448efbe..b4da76ff60 100644 --- a/acceptance/bundle/deployment/bind/job/job-abort-bind/output.txt +++ b/acceptance/bundle/deployment/bind/job/job-abort-bind/output.txt @@ -3,7 +3,11 @@ Created job with ID: [JOB_ID] === Expect binding to fail without an auto-approve flag: -Error: This bind operation requires user confirmation, but the current console does not support prompting. Please specify --auto-approve if you would like to skip prompts and proceed. +Error: this bind operation requires user confirmation, but the current console does not support prompting. +To proceed, use --auto-approve after reviewing the plan above. + + +Exit code: 1 === Deploy bundle: >>> [CLI] bundle deploy --force-lock diff --git a/acceptance/bundle/deployment/bind/job/job-abort-bind/script b/acceptance/bundle/deployment/bind/job/job-abort-bind/script index bbe22b68fc..b0aed59093 100644 --- a/acceptance/bundle/deployment/bind/job/job-abort-bind/script +++ b/acceptance/bundle/deployment/bind/job/job-abort-bind/script @@ -36,7 +36,7 @@ trap cleanup EXIT title "Expect binding to fail without an auto-approve flag:\n" trace errcode $CLI bundle deployment bind foo $JOB_ID &> out.bind-result.txt -grep "^Error:" out.bind-result.txt +sed -n '/^Error:/,$p' out.bind-result.txt rm out.bind-result.txt title "Deploy bundle:" diff --git a/acceptance/bundle/deployment/bind/pipelines/recreate/out.bind-fail.direct.txt b/acceptance/bundle/deployment/bind/pipelines/recreate/out.bind-fail.direct.txt index c5e00b49cb..b081c18391 100644 --- a/acceptance/bundle/deployment/bind/pipelines/recreate/out.bind-fail.direct.txt +++ b/acceptance/bundle/deployment/bind/pipelines/recreate/out.bind-fail.direct.txt @@ -11,5 +11,6 @@ Changes detected: ~ root_path: "/Workspace/Users/someuser@databricks.com/lakeflow_pipeline" -> null ~ storage: "/Shared/old_storage" -> "/Shared/new_storage" -Error: This bind operation requires user confirmation, but the current console does not support prompting. Please specify --auto-approve if you would like to skip prompts and proceed. +Error: this bind operation requires user confirmation, but the current console does not support prompting. +To proceed, use --auto-approve after reviewing the plan above. diff --git a/acceptance/bundle/deployment/bind/pipelines/recreate/out.bind-fail.terraform.txt b/acceptance/bundle/deployment/bind/pipelines/recreate/out.bind-fail.terraform.txt index 922f6fea73..4e20bfd9ec 100644 --- a/acceptance/bundle/deployment/bind/pipelines/recreate/out.bind-fail.terraform.txt +++ b/acceptance/bundle/deployment/bind/pipelines/recreate/out.bind-fail.terraform.txt @@ -58,5 +58,6 @@ Terraform will perform the following actions: Plan: 1 to add, 0 to change, 1 to destroy. -Error: This bind operation requires user confirmation, but the current console does not support prompting. Please specify --auto-approve if you would like to skip prompts and proceed. +Error: this bind operation requires user confirmation, but the current console does not support prompting. +To proceed, use --auto-approve after reviewing the plan above. diff --git a/acceptance/bundle/deployment/bind/pipelines/recreate/output.txt b/acceptance/bundle/deployment/bind/pipelines/recreate/output.txt index af42322dee..4da2a167b7 100644 --- a/acceptance/bundle/deployment/bind/pipelines/recreate/output.txt +++ b/acceptance/bundle/deployment/bind/pipelines/recreate/output.txt @@ -16,7 +16,9 @@ Streaming Tables (STs) and Materialized Views (MVs) managed by them. Recreating restore the defined STs and MVs through full refresh. Note that recreation is necessary when pipeline properties such as the 'catalog' or 'storage' are changed: recreate resources.pipelines.foo -Error: the deployment requires destructive actions, but current console does not support prompting. Please specify --auto-approve if you would like to skip prompts and proceed +Error: the deployment requires destructive actions, but the current console does not support prompting. +Deleting data assets such as schemas, pipelines, or volumes may cause permanent data loss and should be carefully reviewed. +To proceed, use --auto-approve after reviewing the plan above. >>> [CLI] bundle deploy --auto-approve diff --git a/acceptance/bundle/deployment/bind/pipelines/update/out.bind-fail.direct.txt b/acceptance/bundle/deployment/bind/pipelines/update/out.bind-fail.direct.txt index 7b85803529..a5e4ca8007 100644 --- a/acceptance/bundle/deployment/bind/pipelines/update/out.bind-fail.direct.txt +++ b/acceptance/bundle/deployment/bind/pipelines/update/out.bind-fail.direct.txt @@ -11,5 +11,6 @@ Changes detected: ~ name: "lakeflow-pipeline" -> "test-pipeline" ~ root_path: "/Workspace/Users/[USERNAME]/lakeflow_pipeline" -> null -Error: This bind operation requires user confirmation, but the current console does not support prompting. Please specify --auto-approve if you would like to skip prompts and proceed. +Error: this bind operation requires user confirmation, but the current console does not support prompting. +To proceed, use --auto-approve after reviewing the plan above. diff --git a/acceptance/bundle/deployment/bind/pipelines/update/out.bind-fail.terraform.txt b/acceptance/bundle/deployment/bind/pipelines/update/out.bind-fail.terraform.txt index 6ce19d8337..deacd3b1a2 100644 --- a/acceptance/bundle/deployment/bind/pipelines/update/out.bind-fail.terraform.txt +++ b/acceptance/bundle/deployment/bind/pipelines/update/out.bind-fail.terraform.txt @@ -43,5 +43,6 @@ Terraform will perform the following actions: Plan: 0 to add, 1 to change, 0 to destroy. -Error: This bind operation requires user confirmation, but the current console does not support prompting. Please specify --auto-approve if you would like to skip prompts and proceed. +Error: this bind operation requires user confirmation, but the current console does not support prompting. +To proceed, use --auto-approve after reviewing the plan above. diff --git a/acceptance/bundle/resources/dashboards/detect-change/output.txt b/acceptance/bundle/resources/dashboards/detect-change/output.txt index 53179be516..8e06bc10e8 100644 --- a/acceptance/bundle/resources/dashboards/detect-change/output.txt +++ b/acceptance/bundle/resources/dashboards/detect-change/output.txt @@ -60,7 +60,8 @@ These modifications are untracked and will be overwritten on deploy. Make sure that the local dashboard definition matches what you intend to deploy before proceeding with the deployment. -Run `databricks bundle deploy --force` to bypass this error. +To overwrite the remote changes with your local version, use --force. +The remote modifications will be lost. update dashboards.file_reference @@ -77,7 +78,8 @@ These modifications are untracked and will be overwritten on deploy. Make sure that the local dashboard definition matches what you intend to deploy before proceeding with the deployment. -Run `databricks bundle deploy --force` to bypass this error. +To overwrite the remote changes with your local version, use --force. +The remote modifications will be lost. >>> errcode [CLI] bundle deploy @@ -91,7 +93,8 @@ These modifications are untracked and will be overwritten on deploy. Make sure that the local dashboard definition matches what you intend to deploy before proceeding with the deployment. -Run `databricks bundle deploy --force` to bypass this error. +To overwrite the remote changes with your local version, use --force. +The remote modifications will be lost. Exit code: 1 diff --git a/acceptance/bundle/resources/pipelines/auto-approve/output.txt b/acceptance/bundle/resources/pipelines/auto-approve/output.txt index 5154a1206a..3016a4c248 100644 --- a/acceptance/bundle/resources/pipelines/auto-approve/output.txt +++ b/acceptance/bundle/resources/pipelines/auto-approve/output.txt @@ -50,7 +50,9 @@ Streaming Tables (STs) and Materialized Views (MVs) managed by them. Recreating restore the defined STs and MVs through full refresh. Note that recreation is necessary when pipeline properties such as the 'catalog' or 'storage' are changed: delete resources.pipelines.bar -Error: the deployment requires destructive actions, but current console does not support prompting. Please specify --auto-approve if you would like to skip prompts and proceed +Error: the deployment requires destructive actions, but the current console does not support prompting. +Deleting data assets such as schemas, pipelines, or volumes may cause permanent data loss and should be carefully reviewed. +To proceed, use --auto-approve after reviewing the plan above. Exit code: 1 diff --git a/acceptance/bundle/resources/pipelines/recreate/output.txt b/acceptance/bundle/resources/pipelines/recreate/output.txt index 8550395ff2..bc68df40d2 100644 --- a/acceptance/bundle/resources/pipelines/recreate/output.txt +++ b/acceptance/bundle/resources/pipelines/recreate/output.txt @@ -49,7 +49,9 @@ Streaming Tables (STs) and Materialized Views (MVs) managed by them. Recreating restore the defined STs and MVs through full refresh. Note that recreation is necessary when pipeline properties such as the 'catalog' or 'storage' are changed: recreate resources.pipelines.foo -Error: the deployment requires destructive actions, but current console does not support prompting. Please specify --auto-approve if you would like to skip prompts and proceed +Error: the deployment requires destructive actions, but the current console does not support prompting. +Deleting data assets such as schemas, pipelines, or volumes may cause permanent data loss and should be carefully reviewed. +To proceed, use --auto-approve after reviewing the plan above. Exit code: 1 diff --git a/acceptance/bundle/resources/schemas/auto-approve/output.txt b/acceptance/bundle/resources/schemas/auto-approve/output.txt index 6a773f60ca..bf8e7771ee 100644 --- a/acceptance/bundle/resources/schemas/auto-approve/output.txt +++ b/acceptance/bundle/resources/schemas/auto-approve/output.txt @@ -57,7 +57,9 @@ Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/[UNIQUE_NAME]/file This action will result in the deletion or recreation of the following UC schemas. Any underlying data may be lost: delete resources.schemas.bar -Error: the deployment requires destructive actions, but current console does not support prompting. Please specify --auto-approve if you would like to skip prompts and proceed +Error: the deployment requires destructive actions, but the current console does not support prompting. +Deleting data assets such as schemas, pipelines, or volumes may cause permanent data loss and should be carefully reviewed. +To proceed, use --auto-approve after reviewing the plan above. === Test cleanup diff --git a/acceptance/bundle/resources/volumes/recreate/output.txt b/acceptance/bundle/resources/volumes/recreate/output.txt index 134a52dbd8..5714559a60 100644 --- a/acceptance/bundle/resources/volumes/recreate/output.txt +++ b/acceptance/bundle/resources/volumes/recreate/output.txt @@ -45,7 +45,9 @@ For managed volumes, the files stored in the volume are also deleted from your cloud tenant within 30 days. For external volumes, the metadata about the volume is removed from the catalog, but the underlying files are not deleted: recreate resources.volumes.foo -Error: the deployment requires destructive actions, but current console does not support prompting. Please specify --auto-approve if you would like to skip prompts and proceed +Error: the deployment requires destructive actions, but the current console does not support prompting. +Deleting data assets such as schemas, pipelines, or volumes may cause permanent data loss and should be carefully reviewed. +To proceed, use --auto-approve after reviewing the plan above. Exit code: 1 diff --git a/acceptance/pipelines/deploy/auto-approve/output.txt b/acceptance/pipelines/deploy/auto-approve/output.txt index ff5ac099bf..971748bbaf 100644 --- a/acceptance/pipelines/deploy/auto-approve/output.txt +++ b/acceptance/pipelines/deploy/auto-approve/output.txt @@ -18,7 +18,9 @@ Streaming Tables (STs) and Materialized Views (MVs) managed by them. Recreating restore the defined STs and MVs through full refresh. Note that recreation is necessary when pipeline properties such as the 'catalog' or 'storage' are changed: delete resources.pipelines.foo -Error: the deployment requires destructive actions, but current console does not support prompting. Please specify --auto-approve if you would like to skip prompts and proceed +Error: the deployment requires destructive actions, but the current console does not support prompting. +Deleting data assets such as schemas, pipelines, or volumes may cause permanent data loss and should be carefully reviewed. +To proceed, use --auto-approve after reviewing the plan above. Exit code: 1 diff --git a/acceptance/pipelines/deploy/force-lock/output.txt b/acceptance/pipelines/deploy/force-lock/output.txt index e5fdadbaf9..b1092d3f52 100644 --- a/acceptance/pipelines/deploy/force-lock/output.txt +++ b/acceptance/pipelines/deploy/force-lock/output.txt @@ -4,8 +4,12 @@ === test deployment without force-lock (should fail) >>> errcode [CLI] pipelines deploy -Error: Failed to acquire deployment lock: deploy lock acquired by user-with-lock@databricks.com at [TIMESTAMP] +0000 UTC. Use --force-lock to override -Error: deploy lock acquired by user-with-lock@databricks.com at [TIMESTAMP] +0000 UTC. Use --force-lock to override +Error: Failed to acquire deployment lock: deploy lock acquired by user-with-lock@databricks.com at [TIMESTAMP] +0000 UTC. +Another deployment may be in progress. Use --force-lock to override, but this may +conflict with the other deployment if it is still active +Error: deploy lock acquired by user-with-lock@databricks.com at [TIMESTAMP] +0000 UTC. +Another deployment may be in progress. Use --force-lock to override, but this may +conflict with the other deployment if it is still active Exit code: 1 diff --git a/acceptance/pipelines/destroy/auto-approve/output.txt b/acceptance/pipelines/destroy/auto-approve/output.txt index 17aecc2059..3a59e2ffc2 100644 --- a/acceptance/pipelines/destroy/auto-approve/output.txt +++ b/acceptance/pipelines/destroy/auto-approve/output.txt @@ -8,7 +8,9 @@ Deployment complete! View your pipeline my_pipeline here: [DATABRICKS_URL]/pipelines/[UUID]?o=[NUMID] >>> errcode [CLI] pipelines destroy -Error: please specify --auto-approve since terminal does not support interactive prompts +Error: this command will destroy all resources deployed by this bundle, including workspace files in the deployment directory. +Deleting data assets such as schemas, pipelines, or volumes may cause permanent data loss and should be carefully reviewed. +To proceed, use --auto-approve. Exit code: 1 diff --git a/acceptance/pipelines/destroy/force-lock/output.txt b/acceptance/pipelines/destroy/force-lock/output.txt index 5b6449f732..5579565b06 100644 --- a/acceptance/pipelines/destroy/force-lock/output.txt +++ b/acceptance/pipelines/destroy/force-lock/output.txt @@ -11,8 +11,12 @@ View your pipeline foo here: [DATABRICKS_URL]/pipelines/[UUID]?o=[NUMID] === test deployment without force-lock (should fail) >>> errcode [CLI] pipelines destroy --auto-approve -Error: Failed to acquire deployment lock: deploy lock acquired by user-with-lock@databricks.com at [TIMESTAMP] +0000 UTC. Use --force-lock to override -Error: deploy lock acquired by user-with-lock@databricks.com at [TIMESTAMP] +0000 UTC. Use --force-lock to override +Error: Failed to acquire deployment lock: deploy lock acquired by user-with-lock@databricks.com at [TIMESTAMP] +0000 UTC. +Another deployment may be in progress. Use --force-lock to override, but this may +conflict with the other deployment if it is still active +Error: deploy lock acquired by user-with-lock@databricks.com at [TIMESTAMP] +0000 UTC. +Another deployment may be in progress. Use --force-lock to override, but this may +conflict with the other deployment if it is still active Exit code: 1 diff --git a/bundle/config/mutator/validate_git_details.go b/bundle/config/mutator/validate_git_details.go index 69a4221fdc..bb25a19809 100644 --- a/bundle/config/mutator/validate_git_details.go +++ b/bundle/config/mutator/validate_git_details.go @@ -4,6 +4,7 @@ import ( "context" "github.com/databricks/cli/bundle" + "github.com/databricks/cli/libs/agent" "github.com/databricks/cli/libs/diag" ) @@ -23,7 +24,8 @@ func (m *validateGitDetails) Apply(ctx context.Context, b *bundle.Bundle) diag.D } if b.Config.Bundle.Git.Branch != b.Config.Bundle.Git.ActualBranch && !b.Config.Bundle.Force { - return diag.Errorf("not on the right Git branch:\n expected according to configuration: %s\n actual: %s\nuse --force to override", b.Config.Bundle.Git.Branch, b.Config.Bundle.Git.ActualBranch) + return diag.Errorf("not on the right Git branch:\n expected according to configuration: %s\n actual: %s\nTo deploy from this branch anyway, use --force. Note that this may push unexpected code to the target.%s", + b.Config.Bundle.Git.Branch, b.Config.Bundle.Git.ActualBranch, agent.AgentNotice()) } return nil } diff --git a/bundle/config/mutator/validate_git_details_test.go b/bundle/config/mutator/validate_git_details_test.go index b29f221edc..b7eaad9aeb 100644 --- a/bundle/config/mutator/validate_git_details_test.go +++ b/bundle/config/mutator/validate_git_details_test.go @@ -40,8 +40,9 @@ func TestValidateGitDetailsNonMatchingBranches(t *testing.T) { m := ValidateGitDetails() diags := bundle.Apply(t.Context(), b, m) - expectedError := "not on the right Git branch:\n expected according to configuration: main\n actual: feature\nuse --force to override" - assert.EqualError(t, diags.Error(), expectedError) + err := diags.Error() + assert.ErrorContains(t, err, "not on the right Git branch:\n expected according to configuration: main\n actual: feature") + assert.ErrorContains(t, err, "To deploy from this branch anyway, use --force. Note that this may push unexpected code to the target.") } func TestValidateGitDetailsNotUsingGit(t *testing.T) { diff --git a/bundle/deploy/terraform/check_dashboards_modified_remotely.go b/bundle/deploy/terraform/check_dashboards_modified_remotely.go index 4e56eb8e1d..ed873618ed 100644 --- a/bundle/deploy/terraform/check_dashboards_modified_remotely.go +++ b/bundle/deploy/terraform/check_dashboards_modified_remotely.go @@ -7,6 +7,7 @@ import ( "github.com/databricks/cli/bundle" "github.com/databricks/cli/bundle/config/engine" + "github.com/databricks/cli/libs/agent" "github.com/databricks/cli/libs/diag" "github.com/databricks/cli/libs/dyn" ) @@ -120,8 +121,8 @@ func (l *checkDashboardsModifiedRemotely) Apply(ctx context.Context, b *bundle.B "Make sure that the local dashboard definition matches what you intend to deploy\n" + "before proceeding with the deployment.\n" + "\n" + - "Run `databricks bundle deploy --force` to bypass this error." + - "", + "To overwrite the remote changes with your local version, use --force.\n" + + "The remote modifications will be lost." + agent.AgentNotice(), Paths: []dyn.Path{path}, Locations: []dyn.Location{loc}, }) diff --git a/bundle/deploy/terraform/import.go b/bundle/deploy/terraform/import.go index 8fdfe1212d..48ad622c6c 100644 --- a/bundle/deploy/terraform/import.go +++ b/bundle/deploy/terraform/import.go @@ -10,6 +10,7 @@ import ( "strings" "github.com/databricks/cli/bundle" + "github.com/databricks/cli/libs/agent" "github.com/databricks/cli/libs/cmdio" "github.com/databricks/cli/libs/diag" "github.com/hashicorp/terraform-exec/tfexec" @@ -72,7 +73,7 @@ func (m *importResource) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagn cmdio.LogString(ctx, output) if !cmdio.IsPromptSupported(ctx) { - return diag.Errorf("This bind operation requires user confirmation, but the current console does not support prompting. Please specify --auto-approve if you would like to skip prompts and proceed.") + return diag.Errorf("this bind operation requires user confirmation, but the current console does not support prompting.\nTo proceed, use --auto-approve after reviewing the plan above.%s", agent.AgentNotice()) } ans, err := cmdio.AskYesOrNo(ctx, "Confirm import changes? Changes will be remotely applied only after running 'bundle deploy'.") diff --git a/bundle/phases/bind.go b/bundle/phases/bind.go index f0041e9183..48ba775571 100644 --- a/bundle/phases/bind.go +++ b/bundle/phases/bind.go @@ -14,6 +14,7 @@ import ( "github.com/databricks/cli/bundle/deploy/terraform" "github.com/databricks/cli/bundle/deployplan" "github.com/databricks/cli/bundle/statemgmt" + "github.com/databricks/cli/libs/agent" "github.com/databricks/cli/libs/cmdio" "github.com/databricks/cli/libs/log" "github.com/databricks/cli/libs/logdiag" @@ -68,7 +69,7 @@ func Bind(ctx context.Context, b *bundle.Bundle, opts *terraform.BindOptions, en if !cmdio.IsPromptSupported(ctx) { result.Cancel() - logdiag.LogError(ctx, errors.New("This bind operation requires user confirmation, but the current console does not support prompting. Please specify --auto-approve if you would like to skip prompts and proceed.")) //nolint + logdiag.LogError(ctx, fmt.Errorf("this bind operation requires user confirmation, but the current console does not support prompting.\nTo proceed, use --auto-approve after reviewing the plan above.%s", agent.AgentNotice())) return } diff --git a/bundle/phases/deploy.go b/bundle/phases/deploy.go index b4d70ede5a..82593a07b5 100644 --- a/bundle/phases/deploy.go +++ b/bundle/phases/deploy.go @@ -20,6 +20,7 @@ import ( "github.com/databricks/cli/bundle/permissions" "github.com/databricks/cli/bundle/scripts" "github.com/databricks/cli/bundle/statemgmt" + "github.com/databricks/cli/libs/agent" "github.com/databricks/cli/libs/cmdio" "github.com/databricks/cli/libs/log" "github.com/databricks/cli/libs/logdiag" @@ -56,7 +57,9 @@ func approvalForDeploy(ctx context.Context, b *bundle.Bundle, plan *deployplan.P } if !cmdio.IsPromptSupported(ctx) { - return false, errors.New("the deployment requires destructive actions, but current console does not support prompting. Please specify --auto-approve if you would like to skip prompts and proceed") + return false, errors.New("the deployment requires destructive actions, but the current console does not support prompting.\n" + + DataLossWarning + "\n" + + "To proceed, use --auto-approve after reviewing the plan above." + agent.AgentNotice()) } cmdio.LogString(ctx, "") diff --git a/bundle/phases/messages.go b/bundle/phases/messages.go index 347df8ece4..4c75879aa4 100644 --- a/bundle/phases/messages.go +++ b/bundle/phases/messages.go @@ -38,6 +38,10 @@ This action will result in the deletion or recreation of the following Lakebase All data stored in them will be permanently lost:` ) +// DataLossWarning is the warning shown when a non-interactive command is about +// to delete data-bearing resources. +const DataLossWarning = "Deleting data assets such as schemas, pipelines, or volumes may cause permanent data loss and should be carefully reviewed." + // Messages for bundle destroy. const ( deleteSchemaMessage = `This action will result in the deletion of the following UC schemas. Any underlying data may be lost:` diff --git a/cmd/bundle/destroy.go b/cmd/bundle/destroy.go index bd69e1a751..a4f85667a2 100644 --- a/cmd/bundle/destroy.go +++ b/cmd/bundle/destroy.go @@ -11,6 +11,7 @@ import ( "github.com/databricks/cli/bundle/statemgmt" "github.com/databricks/cli/cmd/bundle/utils" "github.com/databricks/cli/cmd/root" + "github.com/databricks/cli/libs/agent" "github.com/databricks/cli/libs/cmdio" "github.com/databricks/cli/libs/logdiag" "github.com/spf13/cobra" @@ -50,7 +51,10 @@ Typical use cases: func CommandBundleDestroy(cmd *cobra.Command, args []string, autoApprove, forceDestroy bool) error { // We require auto-approve for non-interactive terminals since prompts are not possible. if !cmdio.IsPromptSupported(cmd.Context()) && !autoApprove { - return errors.New("please specify --auto-approve since terminal does not support interactive prompts") + return errors.New("this command will destroy all resources deployed by this bundle, " + + "including workspace files in the deployment directory.\n" + + phases.DataLossWarning + "\n" + + "To proceed, use --auto-approve." + agent.AgentNotice()) } // Check if context is already initialized (e.g., when called from apps delete override) diff --git a/libs/agent/agent_notice.go b/libs/agent/agent_notice.go new file mode 100644 index 0000000000..22f63b9d5d --- /dev/null +++ b/libs/agent/agent_notice.go @@ -0,0 +1,20 @@ +package agent + +import ( + "fmt" + + "github.com/databricks/databricks-sdk-go/useragent" +) + +// AgentNotice returns a notice string to append to error messages when an AI +// agent is detected. Returns an empty string for non-agent callers. +func AgentNotice() string { + name := useragent.AgentProvider() + if name == "" { + return "" + } + return fmt.Sprintf("\n\nNote for AI agents (%s): do not retry with the flag suggested above\n"+ + "unless the user has explicitly approved it. The flag bypasses a safety check\n"+ + "and the operation may be irreversible.", + name) +} diff --git a/libs/locker/locker.go b/libs/locker/locker.go index 4a094ba028..0de7fdb4d9 100644 --- a/libs/locker/locker.go +++ b/libs/locker/locker.go @@ -105,10 +105,16 @@ func (locker *Locker) assertLockHeld(ctx context.Context) error { return err } if activeLockState.ID != locker.State.ID && !activeLockState.IsForced { - return fmt.Errorf("deploy lock acquired by %s at %v. Use --force-lock to override", activeLockState.User, activeLockState.AcquisitionTime) + return fmt.Errorf("deploy lock acquired by %s at %v.\n"+ + "Another deployment may be in progress. Use --force-lock to override, but this may\n"+ + "conflict with the other deployment if it is still active", + activeLockState.User, activeLockState.AcquisitionTime) } if activeLockState.ID != locker.State.ID && activeLockState.IsForced { - return fmt.Errorf("deploy lock force acquired by %s at %v. Use --force-lock to override", activeLockState.User, activeLockState.AcquisitionTime) + return fmt.Errorf("deploy lock force-acquired by %s at %v.\n"+ + "Another deployment may be in progress. Use --force-lock to override, but this may\n"+ + "conflict with the other deployment if it is still active", + activeLockState.User, activeLockState.AcquisitionTime) } return nil }