From bc078472d4c00926de51d12124de556da051b0fe Mon Sep 17 00:00:00 2001 From: Pasha Sviderski Date: Fri, 12 Sep 2025 22:52:06 +1000 Subject: [PATCH] feat: add -y|--yes flag for 'us deploy' to auto-confirm deployment plan --- .mise.lock | 41 +++++++++++------------------------------ cmd/uncloud/deploy.go | 34 +++++++++++++++++++++++----------- go.mod | 2 +- internal/cli/prompt.go | 12 +++++++++++- 4 files changed, 46 insertions(+), 43 deletions(-) diff --git a/.mise.lock b/.mise.lock index c8e7adcb..35ef6e1d 100644 --- a/.mise.lock +++ b/.mise.lock @@ -1,47 +1,28 @@ -[tools."aqua:vektra/mockery"] +[[tools."aqua:vektra/mockery"]] version = "3.5.3" backend = "aqua:vektra/mockery" -[tools."aqua:vektra/mockery".checksums] -"mockery_3.5.3_Darwin_arm64.tar.gz" = "sha256:a3a94b14c7414e148f2252199ffc4a0108d311358f3d336cbe05bb73cb203704" -"mockery_3.5.3_Linux_x86_64.tar.gz" = "sha256:ebce416b0175338525246c376885a1579ca6cd4d4015140ba0c70e6b5339a39c" - -[tools.go] -version = "1.23.10" +[[tools.go]] +version = "1.23.12" backend = "core:go" -[tools.go.checksums] -"go1.23.10.darwin-arm64.tar.gz" = "sha256:25c64bfa8a8fd8e7f62fb54afa4354af8409a4bb2358c2699a1003b733e6fce5" -"go1.23.10.linux-amd64.tar.gz" = "sha256:535f9f81802499f2a7dbfa70abb8fda3793725fcc29460f719815f6e10b5fd60" +[tools.go.platforms.macos-arm64] +checksum = "sha256:5bfa117e401ae64e7ffb960243c448b535fe007e682a13ff6c7371f4a6f0ccaa" +size = 71669468 +url = "https://dl.google.com/go/go1.23.12.darwin-arm64.tar.gz" -[tools.golangci-lint] +[[tools.golangci-lint]] version = "2.2.2" backend = "aqua:golangci/golangci-lint" -[tools.golangci-lint.checksums] -"golangci-lint-2.2.2-darwin-arm64.tar.gz" = "sha256:d84d94d042c0d495fd1746f3d18948a75de163b17a14e8de3ef840928dd2df74" -"golangci-lint-2.2.2-linux-amd64.tar.gz" = "sha256:c27fbde948a87d326feacd21df2f61a9c54dbd2e3bfa185c0a1cd6917a6f964f" - -[tools.protoc] +[[tools.protoc]] version = "27.3" backend = "aqua:protocolbuffers/protobuf/protoc" -[tools.protoc.checksums] -"protoc-27.3-linux-x86_64.zip" = "sha256:6dab2adab83f915126cab53540d48957c40e9e9023969c3e84d44bfb936c7741" -"protoc-27.3-osx-aarch_64.zip" = "sha256:b22116bd97cdbd7ea25346abe635a9df268515fe5ef5afa93cd9a68fc2513f84" - -[tools.protoc-gen-go] +[[tools.protoc-gen-go]] version = "1.34.2" backend = "aqua:protocolbuffers/protobuf-go/protoc-gen-go" -[tools.protoc-gen-go.checksums] -"protoc-gen-go.v1.34.2.darwin.arm64.tar.gz" = "sha256:17aca7f948dbb624049030cf841e35895cf34183ba006e721247fdeb95ff2780" -"protoc-gen-go.v1.34.2.linux.amd64.tar.gz" = "sha256:b87bc134dee55576a842141bf0ed27761c635d746780fce5dee038c6dd16554f" - -[tools.protoc-gen-go-grpc] +[[tools.protoc-gen-go-grpc]] version = "1.5.1" backend = "aqua:grpc/grpc-go/protoc-gen-go-grpc" - -[tools.protoc-gen-go-grpc.checksums] -"protoc-gen-go-grpc.v1.5.1.darwin.arm64.tar.gz" = "sha256:d6083feb51dcfe59f26793e99ef01ef5eac68b64294ec2546711f614ac5878f3" -"protoc-gen-go-grpc.v1.5.1.linux.amd64.tar.gz" = "sha256:a6cac4ea731e54aea304ad44d704a69d1cdc82997084b33637e21a89dc9229d6" diff --git a/cmd/uncloud/deploy.go b/cmd/uncloud/deploy.go index 4daf92c0..273e11f2 100644 --- a/cmd/uncloud/deploy.go +++ b/cmd/uncloud/deploy.go @@ -22,6 +22,7 @@ type deployOptions struct { services []string noBuild bool recreate bool + yes bool context string } @@ -43,16 +44,19 @@ func NewDeployCommand() *cobra.Command { }, } - cmd.Flags().StringSliceVarP(&opts.files, "file", "f", nil, - "One or more Compose files to deploy services from. (default compose.yaml)") - cmd.Flags().StringSliceVarP(&opts.profiles, "profile", "p", nil, - "One or more Compose profiles to enable.") cmd.Flags().StringVarP(&opts.context, "context", "c", "", "Name of the cluster context to deploy to (default is the current context)") + cmd.Flags().StringSliceVarP(&opts.files, "file", "f", nil, + "One or more Compose files to deploy services from. (default compose.yaml)") cmd.Flags().BoolVarP(&opts.noBuild, "no-build", "n", false, "Do not build images before deploying services. (default false)") + cmd.Flags().StringSliceVarP(&opts.profiles, "profile", "p", nil, + "One or more Compose profiles to enable.") cmd.Flags().BoolVar(&opts.recreate, "recreate", false, "Recreate containers even if their configuration and image haven't changed.") + cmd.Flags().BoolVarP(&opts.yes, "yes", "y", false, + "Auto-confirm deployment plan. Enabled by default when running non-interactively,\n"+ + "e.g., in CI/CD pipelines.") // TODO: Consider adding a filter flag to specify which machines to deploy to but keep the rest running. // Could be useful to test a new version on a subset of machines before rolling out to all. @@ -136,13 +140,21 @@ func runDeploy(ctx context.Context, uncli *cli.CLI, opts deployOptions) error { } fmt.Println() - confirmed, err := cli.Confirm() - if err != nil { - return fmt.Errorf("confirm deployment: %w", err) - } - if !confirmed { - fmt.Println("Cancelled. No changes were made.") - return nil + // Ask for plan confirmation before proceeding with the deployment unless running in non-interactive mode + // or --yes is specified. + if !opts.yes { + if cli.IsStdinTerminal() { + confirmed, err := cli.Confirm() + if err != nil { + return fmt.Errorf("confirm deployment: %w", err) + } + if !confirmed { + fmt.Println("Cancelled. No changes were made.") + return nil + } + } else { + fmt.Println("Auto-confirming deployment plan in non-interactive mode.") + } } return progress.RunWithTitle(ctx, func(ctx context.Context) error { diff --git a/go.mod b/go.mod index 0b447ede..10548001 100644 --- a/go.mod +++ b/go.mod @@ -52,6 +52,7 @@ require ( golang.org/x/net v0.35.0 golang.org/x/sync v0.11.0 golang.org/x/sys v0.31.0 + golang.org/x/term v0.29.0 golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 @@ -307,7 +308,6 @@ require ( golang.org/x/crypto/x509roots/fallback v0.0.0-20240507223354-67b13616a595 // indirect golang.org/x/exp v0.0.0-20241215155358-4a5509556b9e // indirect golang.org/x/mod v0.23.0 // indirect - golang.org/x/term v0.29.0 // indirect golang.org/x/text v0.22.0 // indirect golang.org/x/time v0.8.0 // indirect golang.org/x/tools v0.30.0 // indirect diff --git a/internal/cli/prompt.go b/internal/cli/prompt.go index 6b29558b..48ce10c9 100644 --- a/internal/cli/prompt.go +++ b/internal/cli/prompt.go @@ -1,6 +1,11 @@ package cli -import "github.com/charmbracelet/huh" +import ( + "os" + + "github.com/charmbracelet/huh" + "golang.org/x/term" +) func Confirm() (bool, error) { var confirmed bool @@ -21,3 +26,8 @@ func Confirm() (bool, error) { return confirmed, nil } + +// IsStdinTerminal checks if the standard input is a terminal (TTY). +func IsStdinTerminal() bool { + return term.IsTerminal(int(os.Stdin.Fd())) +}