Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: track cli command run events #189

Merged
merged 32 commits into from
Apr 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
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
2 changes: 2 additions & 0 deletions cmd/cliflags/flags.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package cliflags

const (
BaseURIDefault = "https://app.launchdarkly.com"

AccessTokenFlag = "access-token"
BaseURIFlag = "base-uri"
DataFlag = "data"
Expand Down
3 changes: 2 additions & 1 deletion cmd/cmdtest.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ var ValidResponse = `{"valid": true}`
func CallCmd(
t *testing.T,
clients APIClients,
tracker analytics.Tracker,
args []string,
) ([]byte, error) {
rootCmd, err := NewRootCommand(
&analytics.NoopClient{},
tracker,
clients,
"test",
false,
Expand Down
12 changes: 11 additions & 1 deletion cmd/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"github.com/spf13/viper"
"gopkg.in/yaml.v3"

"ldcli/cmd/cliflags"
"ldcli/internal/analytics"
"ldcli/internal/config"
)

Expand All @@ -19,12 +21,20 @@ const (
UnsetFlag = "unset"
)

func NewConfigCmd() *cobra.Command {
func NewConfigCmd(analyticsTracker analytics.Tracker) *cobra.Command {
cmd := &cobra.Command{
Long: "View and modify specific configuration values",
RunE: run(),
Short: "View and modify specific configuration values",
Use: "config",
PreRun: func(cmd *cobra.Command, args []string) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this PreRun while the others are PersistentPreRun?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I considered leaving a comment. PersistentPreRun from my testing only ran on child cmds attached to the parent cmd. The parent cmd is where PersistentPreRun is defined.

On the other hand PreRun will run on the parent command only. In this case config doesn't have any sub commands similar to the others (flags, environments). Hence why its a PreRun and not PersistentPreRun

analyticsTracker.SendEvent(
viper.GetString(cliflags.AccessTokenFlag),
viper.GetString(cliflags.BaseURIFlag),
"CLI Command Run",
analytics.CmdRunEventProperties(cmd, "config"),
)
},
}

cmd.Flags().Bool(ListFlag, false, "List configs")
Expand Down
3 changes: 2 additions & 1 deletion cmd/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package config_test

import (
"ldcli/cmd"
"ldcli/internal/analytics"
"os"
"testing"

Expand All @@ -16,7 +17,7 @@ func TestNoFlag(t *testing.T) {
"config",
}

output, err := cmd.CallCmd(t, cmd.APIClients{}, args)
output, err := cmd.CallCmd(t, cmd.APIClients{}, &analytics.NoopClient{}, args)

require.NoError(t, err)

Expand Down
13 changes: 11 additions & 2 deletions cmd/environments/environments.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package environments

import (
"github.com/spf13/cobra"
"github.com/spf13/viper"

"ldcli/cmd/cliflags"
"ldcli/internal/analytics"
"ldcli/internal/environments"
)
Expand All @@ -15,13 +17,20 @@ func NewEnvironmentsCmd(
Use: "environments",
Short: "Make requests (list, create, etc.) on environments",
Long: "Make requests (list, create, etc.) on environments",
PersistentPreRun: func(cmd *cobra.Command, args []string) {
analyticsTracker.SendEvent(
viper.GetString(cliflags.AccessTokenFlag),
viper.GetString(cliflags.BaseURIFlag),
"CLI Command Run",
analytics.CmdRunEventProperties(cmd, "environments"),
)
},
}

getCmd, err := NewGetCmd(analyticsTracker, client)
getCmd, err := NewGetCmd(client)
if err != nil {
return nil, err
}

cmd.AddCommand(getCmd)

return cmd, nil
Expand Down
14 changes: 1 addition & 13 deletions cmd/environments/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,16 @@ import (

"ldcli/cmd/cliflags"
"ldcli/cmd/validators"
"ldcli/internal/analytics"
"ldcli/internal/environments"
)

func NewGetCmd(
analyticsTracker analytics.Tracker,
client environments.Client,
) (*cobra.Command, error) {
cmd := &cobra.Command{
Args: validators.Validate(),
Long: "Return an environment",
RunE: runGet(analyticsTracker, client),
RunE: runGet(client),
Short: "Return an environment",
Use: "get",
}
Expand Down Expand Up @@ -50,7 +48,6 @@ func NewGetCmd(
}

func runGet(
analyticsTracker analytics.Tracker,
client environments.Client,
) func(*cobra.Command, []string) error {
return func(cmd *cobra.Command, args []string) error {
Expand All @@ -68,15 +65,6 @@ func runGet(
return err
}

analyticsTracker.SendEvent(
viper.GetString(cliflags.AccessTokenFlag),
viper.GetString(cliflags.BaseURIFlag),
"environment_get",
map[string]interface{}{
"key": viper.GetString(cliflags.EnvironmentFlag),
"projectKey": viper.GetString(cliflags.ProjectFlag),
})

fmt.Fprintf(cmd.OutOrStdout(), string(response)+"\n")

return nil
Expand Down
46 changes: 39 additions & 7 deletions cmd/environments/get_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"ldcli/internal/analytics"
"ldcli/internal/environments"
"ldcli/internal/errors"
)
Expand Down Expand Up @@ -36,7 +37,7 @@ func TestGet(t *testing.T) {
"--project", "test-proj",
}

output, err := cmd.CallCmd(t, clients, args)
output, err := cmd.CallCmd(t, clients, &analytics.NoopClient{}, args)

require.NoError(t, err)
assert.JSONEq(t, `{"valid": true}`, string(output))
Expand All @@ -58,7 +59,7 @@ func TestGet(t *testing.T) {
"--project", "test-proj",
}

output, err := cmd.CallCmd(t, clients, args)
output, err := cmd.CallCmd(t, clients, &analytics.NoopClient{}, args)

require.NoError(t, err)
assert.JSONEq(t, `{"valid": true}`, string(output))
Expand All @@ -80,7 +81,7 @@ func TestGet(t *testing.T) {
"--project", "test-proj",
}

_, err := cmd.CallCmd(t, clients, args)
_, err := cmd.CallCmd(t, clients, &analytics.NoopClient{}, args)

require.EqualError(t, err, "An error")
})
Expand All @@ -93,7 +94,7 @@ func TestGet(t *testing.T) {
"environments", "get",
}

_, err := cmd.CallCmd(t, clients, args)
_, err := cmd.CallCmd(t, clients, &analytics.NoopClient{}, args)

assert.EqualError(t, err, `required flag(s) "access-token", "environment", "project" not set`+errorHelp)
})
Expand All @@ -107,7 +108,7 @@ func TestGet(t *testing.T) {
"-e",
}

_, err := cmd.CallCmd(t, clients, args)
_, err := cmd.CallCmd(t, clients, &analytics.NoopClient{}, args)

assert.EqualError(t, err, `flag needs an argument: 'e' in -e`)
})
Expand All @@ -121,7 +122,7 @@ func TestGet(t *testing.T) {
"--environment",
}

_, err := cmd.CallCmd(t, clients, args)
_, err := cmd.CallCmd(t, clients, &analytics.NoopClient{}, args)

assert.EqualError(t, err, `flag needs an argument: --environment`)
})
Expand All @@ -138,8 +139,39 @@ func TestGet(t *testing.T) {
"--project", "test-proj",
}

_, err := cmd.CallCmd(t, clients, args)
_, err := cmd.CallCmd(t, clients, &analytics.NoopClient{}, args)

assert.EqualError(t, err, "base-uri is invalid"+errorHelp)
})

t.Run("will track analytics for CLI Command Run event", func(t *testing.T) {
tracker := analytics.MockedTracker(
"environments",
"get",
[]string{
"access-token",
"base-uri",
"environment",
"project",
})

client := environments.MockClient{}
client.
On("Get", mockArgs...).
Return([]byte(cmd.ValidResponse), nil)
clients := cmd.APIClients{
EnvironmentsClient: &client,
}

args := []string{
"environments", "get",
"--access-token", "testAccessToken",
"--base-uri", "http://test.com",
"--environment", "test-env",
"--project", "test-proj",
}

_, err := cmd.CallCmd(t, clients, tracker, args)
require.NoError(t, err)
})
}
46 changes: 39 additions & 7 deletions cmd/flags/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/stretchr/testify/require"

"ldcli/cmd"
"ldcli/internal/analytics"
"ldcli/internal/errors"
"ldcli/internal/flags"
)
Expand Down Expand Up @@ -37,7 +38,7 @@ func TestCreate(t *testing.T) {
"--project", "test-proj-key",
}

output, err := cmd.CallCmd(t, clients, args)
output, err := cmd.CallCmd(t, clients, &analytics.NoopClient{}, args)

require.NoError(t, err)
assert.JSONEq(t, `{"valid": true}`, string(output))
Expand All @@ -59,7 +60,7 @@ func TestCreate(t *testing.T) {
"--project", "test-proj-key",
}

output, err := cmd.CallCmd(t, clients, args)
output, err := cmd.CallCmd(t, clients, &analytics.NoopClient{}, args)

require.NoError(t, err)
assert.JSONEq(t, `{"valid": true}`, string(output))
Expand All @@ -81,7 +82,7 @@ func TestCreate(t *testing.T) {
"--project", "test-proj-key",
}

_, err := cmd.CallCmd(t, clients, args)
_, err := cmd.CallCmd(t, clients, &analytics.NoopClient{}, args)

require.EqualError(t, err, "An error")
})
Expand All @@ -94,7 +95,7 @@ func TestCreate(t *testing.T) {
"flags", "create",
}

_, err := cmd.CallCmd(t, clients, args)
_, err := cmd.CallCmd(t, clients, &analytics.NoopClient{}, args)

assert.EqualError(t, err, `required flag(s) "access-token", "data", "project" not set`+errorHelp)
})
Expand All @@ -108,7 +109,7 @@ func TestCreate(t *testing.T) {
"-d",
}

_, err := cmd.CallCmd(t, clients, args)
_, err := cmd.CallCmd(t, clients, &analytics.NoopClient{}, args)

assert.EqualError(t, err, `flag needs an argument: 'd' in -d`)
})
Expand All @@ -122,7 +123,7 @@ func TestCreate(t *testing.T) {
"--data",
}

_, err := cmd.CallCmd(t, clients, args)
_, err := cmd.CallCmd(t, clients, &analytics.NoopClient{}, args)

assert.EqualError(t, err, `flag needs an argument: --data`)
})
Expand All @@ -139,8 +140,39 @@ func TestCreate(t *testing.T) {
"--project", "test-proj-key",
}

_, err := cmd.CallCmd(t, clients, args)
_, err := cmd.CallCmd(t, clients, &analytics.NoopClient{}, args)

assert.EqualError(t, err, "base-uri is invalid"+errorHelp)
})

t.Run("will track analytics for CLI Command Run event", func(t *testing.T) {
tracker := analytics.MockedTracker(
"flags",
"create",
[]string{
"access-token",
"base-uri",
"data",
"project",
})

client := flags.MockClient{}
client.
On("Create", mockArgs...).
Return([]byte(cmd.ValidResponse), nil)
clients := cmd.APIClients{
FlagsClient: &client,
}

args := []string{
"flags", "create",
"--access-token", "testAccessToken",
"--base-uri", "http://test.com",
"-d", `{"key": "test-key", "name": "test-name"}`,
"--project", "test-proj-key",
}

_, err := cmd.CallCmd(t, clients, tracker, args)
require.NoError(t, err)
})
}
13 changes: 12 additions & 1 deletion cmd/flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,26 @@ package flags

import (
"github.com/spf13/cobra"
"github.com/spf13/viper"

"ldcli/cmd/cliflags"
"ldcli/internal/analytics"
"ldcli/internal/flags"
)

func NewFlagsCmd(client flags.Client) (*cobra.Command, error) {
func NewFlagsCmd(analyticsTracker analytics.Tracker, client flags.Client) (*cobra.Command, error) {
cmd := &cobra.Command{
Use: "flags",
Short: "Make requests (list, create, etc.) on flags",
Long: "Make requests (list, create, etc.) on flags",
PersistentPreRun: func(cmd *cobra.Command, args []string) {
analyticsTracker.SendEvent(
viper.GetString(cliflags.AccessTokenFlag),
viper.GetString(cliflags.BaseURIFlag),
"CLI Command Run",
analytics.CmdRunEventProperties(cmd, "flags"),
)
},
}

createCmd, err := NewCreateCmd(client)
Expand Down
Loading
Loading