-
Notifications
You must be signed in to change notification settings - Fork 237
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Added
circleci telemetry enable
and `circleci telemetry disab…
…le` commands
- Loading branch information
1 parent
a68d639
commit 91caef4
Showing
4 changed files
with
218 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
package cmd | ||
|
||
import ( | ||
"os" | ||
|
||
"github.com/CircleCI-Public/circleci-cli/api/rest" | ||
"github.com/CircleCI-Public/circleci-cli/settings" | ||
"github.com/pkg/errors" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
func newTelemetryCommand(config *settings.Config) *cobra.Command { | ||
apiClient := telemetryCircleCIAPI{ | ||
cli: rest.NewFromConfig(config.Host, config), | ||
} | ||
|
||
telemetryEnable := &cobra.Command{ | ||
Use: "enable", | ||
Short: "Allow telemetry events to be sent to CircleCI servers", | ||
RunE: func(_ *cobra.Command, _ []string) error { | ||
return setIsTelemetryActive(apiClient, true) | ||
}, | ||
Args: cobra.ExactArgs(0), | ||
} | ||
|
||
telemetryDisable := &cobra.Command{ | ||
Use: "disable", | ||
Short: "Make sure no telemetry events is sent to CircleCI servers", | ||
RunE: func(_ *cobra.Command, _ []string) error { | ||
return setIsTelemetryActive(apiClient, false) | ||
}, | ||
Args: cobra.ExactArgs(0), | ||
} | ||
|
||
telemetryCommand := &cobra.Command{ | ||
Use: "telemetry", | ||
Short: "Configure telemetry preferences", | ||
Long: `Configure telemetry preferences. | ||
Note: If you have not configured your telemetry preferences and call the CLI with a closed stdin, telemetry will be disabled`, | ||
} | ||
|
||
telemetryCommand.AddCommand(telemetryEnable) | ||
telemetryCommand.AddCommand(telemetryDisable) | ||
|
||
return telemetryCommand | ||
} | ||
|
||
func setIsTelemetryActive(apiClient telemetryAPIClient, isActive bool) error { | ||
settings := settings.TelemetrySettings{} | ||
if err := settings.Load(); err != nil && !os.IsNotExist(err) { | ||
return errors.Wrap(err, "Loading telemetry configuration") | ||
} | ||
|
||
settings.HasAnsweredPrompt = true | ||
settings.IsActive = isActive | ||
|
||
if settings.UniqueID == "" { | ||
settings.UniqueID = createUUID() | ||
} | ||
|
||
if settings.UserID == "" { | ||
if myID, err := apiClient.getMyUserId(); err == nil { | ||
settings.UserID = myID | ||
} | ||
} | ||
|
||
if err := settings.Write(); err != nil { | ||
return errors.Wrap(err, "Writing telemetry configuration") | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
package cmd | ||
|
||
import ( | ||
"path/filepath" | ||
"testing" | ||
|
||
"github.com/CircleCI-Public/circleci-cli/settings" | ||
"github.com/spf13/afero" | ||
"gotest.tools/v3/assert" | ||
) | ||
|
||
func TestSetIsTelemetryActive(t *testing.T) { | ||
type args struct { | ||
apiClient telemetryAPIClient | ||
isActive bool | ||
settings *settings.TelemetrySettings | ||
} | ||
type want struct { | ||
settings *settings.TelemetrySettings | ||
} | ||
|
||
type testCase struct { | ||
name string | ||
args args | ||
want want | ||
} | ||
|
||
userId := "user-id" | ||
uniqueId := "unique-id" | ||
|
||
testCases := []testCase{ | ||
{ | ||
name: "Enabling telemetry with settings should just update the is active field", | ||
args: args{ | ||
apiClient: telemetryTestAPIClient{}, | ||
isActive: true, | ||
settings: &settings.TelemetrySettings{ | ||
IsActive: false, | ||
HasAnsweredPrompt: true, | ||
UniqueID: uniqueId, | ||
UserID: userId, | ||
}, | ||
}, | ||
want: want{ | ||
settings: &settings.TelemetrySettings{ | ||
IsActive: true, | ||
HasAnsweredPrompt: true, | ||
UniqueID: uniqueId, | ||
UserID: userId, | ||
}, | ||
}, | ||
}, | ||
{ | ||
name: "Enabling telemetry without settings should fill the settings fields", | ||
args: args{ | ||
apiClient: telemetryTestAPIClient{id: userId, err: nil}, | ||
isActive: true, | ||
settings: nil, | ||
}, | ||
want: want{ | ||
settings: &settings.TelemetrySettings{ | ||
IsActive: true, | ||
HasAnsweredPrompt: true, | ||
UniqueID: uniqueId, | ||
UserID: userId, | ||
}, | ||
}, | ||
}, | ||
{ | ||
name: "Disabling telemetry with settings should just update the is active field", | ||
args: args{ | ||
apiClient: telemetryTestAPIClient{}, | ||
isActive: false, | ||
settings: &settings.TelemetrySettings{ | ||
IsActive: true, | ||
HasAnsweredPrompt: true, | ||
UniqueID: uniqueId, | ||
UserID: userId, | ||
}, | ||
}, | ||
want: want{ | ||
settings: &settings.TelemetrySettings{ | ||
IsActive: false, | ||
HasAnsweredPrompt: true, | ||
UniqueID: uniqueId, | ||
UserID: userId, | ||
}, | ||
}, | ||
}, | ||
{ | ||
name: "Enabling telemetry without settings should fill the settings fields", | ||
args: args{ | ||
apiClient: telemetryTestAPIClient{id: userId, err: nil}, | ||
isActive: false, | ||
settings: nil, | ||
}, | ||
want: want{ | ||
settings: &settings.TelemetrySettings{ | ||
IsActive: false, | ||
HasAnsweredPrompt: true, | ||
UniqueID: uniqueId, | ||
UserID: userId, | ||
}, | ||
}, | ||
}, | ||
} | ||
|
||
// Mock create UUID | ||
oldUUIDCreate := createUUID | ||
createUUID = func() string { return uniqueId } | ||
defer (func() { createUUID = oldUUIDCreate })() | ||
|
||
for _, tt := range testCases { | ||
t.Run(tt.name, func(t *testing.T) { | ||
// Mock FS | ||
oldFS := settings.FS.Fs | ||
settings.FS.Fs = afero.NewMemMapFs() | ||
defer (func() { settings.FS.Fs = oldFS })() | ||
|
||
if tt.args.settings != nil { | ||
err := tt.args.settings.Write() | ||
assert.NilError(t, err) | ||
} | ||
|
||
err := setIsTelemetryActive(tt.args.apiClient, tt.args.isActive) | ||
assert.NilError(t, err) | ||
|
||
exist, err := settings.FS.Exists(filepath.Join(settings.SettingsPath(), "telemetry.yml")) | ||
assert.NilError(t, err) | ||
if tt.want.settings == nil { | ||
assert.Equal(t, exist, false) | ||
} else { | ||
assert.Equal(t, exist, true) | ||
|
||
loadedSettings := &settings.TelemetrySettings{} | ||
err := loadedSettings.Load() | ||
assert.NilError(t, err) | ||
|
||
assert.DeepEqual(t, tt.want.settings, loadedSettings) | ||
} | ||
}) | ||
} | ||
} |