diff --git a/cmd/grounds/commands/push/push.go b/cmd/grounds/commands/push/push.go index eccd65b..c8491e0 100644 --- a/cmd/grounds/commands/push/push.go +++ b/cmd/grounds/commands/push/push.go @@ -22,9 +22,18 @@ func NewPushCommand() *cobra.Command { func newPush() *cobra.Command { var target string cmd := &cobra.Command{ - Use: "push [--target=dev]", + Use: "push [--target=dev|staging]", Short: "Build via Gradle plugin and deploy to a target", + Long: `Build the current project with the grounds-push Gradle plugin and deploy it. + +Targets: + dev — long-lived, lands in your personal namespace (user-). + staging — ephemeral preview env, fresh namespace per push, auto-deleted after 7 days. + Public URL pattern: -pr.dev.grnds.io.`, RunE: func(cmd *cobra.Command, _ []string) error { + if target != "dev" && target != "staging" { + return fmt.Errorf("invalid --target %q: must be \"dev\" or \"staging\"", target) + } cwd, err := os.Getwd() if err != nil { return err @@ -38,7 +47,7 @@ func newPush() *cobra.Command { return gradle.Run(ctx, wrapper, args, cmd.OutOrStdout(), cmd.ErrOrStderr(), 0) }, } - cmd.Flags().StringVar(&target, "target", "dev", "deploy target: dev") + cmd.Flags().StringVar(&target, "target", "dev", "deploy target: dev (persistent personal ns) or staging (ephemeral preview env, 7d TTL)") return cmd } diff --git a/cmd/grounds/commands/push/push_test.go b/cmd/grounds/commands/push/push_test.go new file mode 100644 index 0000000..a7747ba --- /dev/null +++ b/cmd/grounds/commands/push/push_test.go @@ -0,0 +1,43 @@ +package push + +import ( + "bytes" + "strings" + "testing" +) + +// Validates the --target flag's allow-list before grounds-push gets +// invoked. The Gradle plugin already rejects bogus targets but +// surfacing the error here gives a faster fail-loud signal and a +// cleaner CLI error. +func TestPushRejectsInvalidTarget(t *testing.T) { + cmd := newPush() + cmd.SetArgs([]string{"--target=production"}) + var stderr bytes.Buffer + cmd.SetErr(&stderr) + cmd.SetOut(&stderr) + cmd.SilenceUsage = true + + err := cmd.Execute() + if err == nil { + t.Fatal("expected an error for invalid target, got nil") + } + if !strings.Contains(err.Error(), "invalid --target") { + t.Errorf("expected 'invalid --target' in error, got: %v", err) + } + if !strings.Contains(err.Error(), "dev") || !strings.Contains(err.Error(), "staging") { + t.Errorf("expected error to mention 'dev' and 'staging', got: %v", err) + } +} + +// Default value should match the help text + Gradle plugin default. +func TestPushDefaultTargetIsDev(t *testing.T) { + cmd := newPush() + flag := cmd.Flag("target") + if flag == nil { + t.Fatal("expected --target flag to exist") + } + if flag.DefValue != "dev" { + t.Errorf("expected default --target=dev, got %q", flag.DefValue) + } +}