From 88b9412112b6f2a1e0a117f5c5b185d893ffd999 Mon Sep 17 00:00:00 2001 From: Lindsey B Date: Wed, 18 Mar 2026 16:03:01 -0700 Subject: [PATCH] Add signup command --- cmd/root.go | 3 +++ cmd/signup/signup.go | 52 +++++++++++++++++++++++++++++++++++++++ cmd/signup/signup_test.go | 26 ++++++++++++++++++++ cmd/templates.go | 1 + 4 files changed, 82 insertions(+) create mode 100644 cmd/signup/signup.go create mode 100644 cmd/signup/signup_test.go diff --git a/cmd/root.go b/cmd/root.go index 5d06d1ff..fc83baa9 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -22,6 +22,7 @@ import ( logincmd "github.com/launchdarkly/ldcli/cmd/login" memberscmd "github.com/launchdarkly/ldcli/cmd/members" resourcecmd "github.com/launchdarkly/ldcli/cmd/resources" + signupcmd "github.com/launchdarkly/ldcli/cmd/signup" sourcemapscmd "github.com/launchdarkly/ldcli/cmd/sourcemaps" "github.com/launchdarkly/ldcli/internal/analytics" "github.com/launchdarkly/ldcli/internal/config" @@ -100,6 +101,7 @@ func NewRootCommand( "config", "help", "login", + "signup", } { if cmd.HasParent() && cmd.Parent().Name() == name { cmd.DisableFlagParsing = true @@ -209,6 +211,7 @@ func NewRootCommand( cmd.AddCommand(configCmd.Cmd()) cmd.AddCommand(NewQuickStartCmd(analyticsTrackerFn, clients.EnvironmentsClient, clients.FlagsClient)) cmd.AddCommand(logincmd.NewLoginCmd(clients.ResourcesClient)) + cmd.AddCommand(signupcmd.NewSignupCmd(analyticsTrackerFn)) cmd.AddCommand(resourcecmd.NewResourcesCmd()) cmd.AddCommand(devcmd.NewDevServerCmd(clients.ResourcesClient, analyticsTrackerFn, clients.DevClient)) cmd.AddCommand(sourcemapscmd.NewSourcemapsCmd(clients.ResourcesClient, analyticsTrackerFn)) diff --git a/cmd/signup/signup.go b/cmd/signup/signup.go new file mode 100644 index 00000000..ead10fc7 --- /dev/null +++ b/cmd/signup/signup.go @@ -0,0 +1,52 @@ +package signup + +import ( + "fmt" + "net/url" + + "github.com/pkg/browser" + "github.com/spf13/cobra" + "github.com/spf13/viper" + + cmdAnalytics "github.com/launchdarkly/ldcli/cmd/analytics" + "github.com/launchdarkly/ldcli/cmd/cliflags" + "github.com/launchdarkly/ldcli/internal/analytics" +) + +func NewSignupCmd(analyticsTrackerFn analytics.TrackerFn) *cobra.Command { + cmd := &cobra.Command{ + Long: "Open your browser to create a new LaunchDarkly account", + PreRun: func(cmd *cobra.Command, args []string) { + analyticsTrackerFn( + viper.GetString(cliflags.AccessTokenFlag), + viper.GetString(cliflags.BaseURIFlag), + viper.GetBool(cliflags.AnalyticsOptOut), + ).SendCommandRunEvent(cmdAnalytics.CmdRunEventProperties(cmd, "signup", nil)) + }, + RunE: run, + Short: "Create a new LaunchDarkly account", + Use: "signup", + } + + return cmd +} + +func run(cmd *cobra.Command, args []string) error { + signupURL, err := url.JoinPath( + viper.GetString(cliflags.BaseURIFlag), + "/signup", + ) + if err != nil { + return fmt.Errorf("failed to construct signup URL: %w", err) + } + + fmt.Fprintf(cmd.OutOrStdout(), "Opening your browser to %s to create a new LaunchDarkly account.\n", signupURL) + fmt.Fprintln(cmd.OutOrStdout(), "If your browser does not open automatically, you can paste the above URL into your browser.") + + err = browser.OpenURL(signupURL) + if err != nil { + fmt.Fprintf(cmd.ErrOrStderr(), "Warning: failed to open browser automatically: %v\n", err) + } + + return nil +} diff --git a/cmd/signup/signup_test.go b/cmd/signup/signup_test.go new file mode 100644 index 00000000..b79ca09d --- /dev/null +++ b/cmd/signup/signup_test.go @@ -0,0 +1,26 @@ +package signup + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/launchdarkly/ldcli/internal/analytics" +) + +func TestSignupCmd(t *testing.T) { + t.Run("creates signup command with correct attributes", func(t *testing.T) { + mockTracker := &analytics.MockTracker{} + analyticsTrackerFn := func(accessToken string, baseURI string, optOut bool) analytics.Tracker { + return mockTracker + } + + cmd := NewSignupCmd(analyticsTrackerFn) + + assert.Equal(t, "signup", cmd.Use) + assert.Equal(t, "Create a new LaunchDarkly account", cmd.Short) + assert.Equal(t, "Open your browser to create a new LaunchDarkly account", cmd.Long) + assert.NotNil(t, cmd.RunE) + assert.NotNil(t, cmd.PreRun) + }) +} diff --git a/cmd/templates.go b/cmd/templates.go index 221061f9..3a96b533 100644 --- a/cmd/templates.go +++ b/cmd/templates.go @@ -15,6 +15,7 @@ Commands: {{rpad "config" 29}} View and modify specific configuration values {{rpad "completion" 29}} Enable command autocompletion within supported shells {{rpad "login" 29}} Log in to your LaunchDarkly account + {{rpad "signup" 29}} Create a new LaunchDarkly account {{rpad "dev-server" 29}} Run a development server to serve flags locally Common resource commands: