Skip to content

Commit 05279cf

Browse files
committed
Merge branch 'master' of github.com:algolia/cli
2 parents a023790 + 537ebe1 commit 05279cf

File tree

8 files changed

+349
-112
lines changed

8 files changed

+349
-112
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
### MacOS
1010

11-
`algolia` is available on on Homebrew and as a downloadable binary from the [releases page](https://github.com/algolia/cli/releases).
11+
`algolia` is available on Homebrew and as a downloadable binary from the [releases page](https://github.com/algolia/cli/releases).
1212

1313
```bash
1414
brew install algolia/algolia-cli/algolia

algolia

12.5 MB
Binary file not shown.

cmd/algolia/main.go

Lines changed: 1 addition & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -1,121 +1,12 @@
11
package main
22

33
import (
4-
"errors"
5-
"fmt"
6-
"io"
7-
"net"
84
"os"
9-
"strings"
105

11-
surveyCore "github.com/AlecAivazis/survey/v2/core"
12-
"github.com/AlecAivazis/survey/v2/terminal"
13-
"github.com/mgutz/ansi"
14-
"github.com/spf13/cobra"
15-
16-
"github.com/algolia/cli/pkg/cmd/factory"
176
"github.com/algolia/cli/pkg/cmd/root"
18-
"github.com/algolia/cli/pkg/cmdutil"
19-
"github.com/algolia/cli/pkg/config"
20-
)
21-
22-
type exitCode int
23-
24-
const (
25-
exitOK exitCode = 0
26-
exitError exitCode = 1
27-
exitCancel exitCode = 2
28-
exitAuth exitCode = 4
297
)
308

319
func main() {
32-
code := mainRun()
10+
code := root.Execute()
3311
os.Exit(int(code))
3412
}
35-
36-
func mainRun() exitCode {
37-
hasDebug := os.Getenv("DEBUG") != ""
38-
39-
cfg := config.Config{}
40-
cfg.InitConfig()
41-
cmdFactory := factory.New(&cfg)
42-
43-
stderr := cmdFactory.IOStreams.ErrOut
44-
45-
if !cmdFactory.IOStreams.ColorEnabled() {
46-
surveyCore.DisableColor = true
47-
} else {
48-
// override survey's poor choice of color
49-
surveyCore.TemplateFuncsWithColor["color"] = func(style string) string {
50-
switch style {
51-
case "white":
52-
if cmdFactory.IOStreams.ColorSupport256() {
53-
return fmt.Sprintf("\x1b[%d;5;%dm", 38, 242)
54-
}
55-
return ansi.ColorCode("default")
56-
default:
57-
return ansi.ColorCode(style)
58-
}
59-
}
60-
}
61-
62-
rootCmd := root.NewRootCmd(cmdFactory)
63-
64-
authError := errors.New("authError")
65-
rootCmd.PersistentPreRunE = func(cmd *cobra.Command, args []string) error {
66-
// require that the user is authenticated before running most commands
67-
if cmdutil.IsAuthCheckEnabled(cmd) {
68-
if err := cmdutil.CheckAuth(cfg); err != nil {
69-
fmt.Fprintf(stderr, "Authentication error: %s\n", err)
70-
fmt.Fprintln(stderr, "Please run `algolia application add` to configure your first application.")
71-
return authError
72-
} else {
73-
return nil
74-
}
75-
}
76-
77-
return nil
78-
}
79-
80-
if cmd, err := rootCmd.ExecuteC(); err != nil {
81-
if err == cmdutil.ErrSilent {
82-
return exitError
83-
} else if cmdutil.IsUserCancellation(err) {
84-
if errors.Is(err, terminal.InterruptErr) {
85-
// ensure the next shell prompt will start on its own line
86-
fmt.Fprint(stderr, "\n")
87-
}
88-
return exitCancel
89-
} else if errors.Is(err, authError) {
90-
return exitAuth
91-
}
92-
93-
printError(stderr, err, cmd, hasDebug)
94-
95-
return exitError
96-
}
97-
98-
return exitOK
99-
}
100-
101-
func printError(out io.Writer, err error, cmd *cobra.Command, debug bool) {
102-
var dnsError *net.DNSError
103-
if errors.As(err, &dnsError) {
104-
fmt.Fprintf(out, "error connecting to %s\n", dnsError.Name)
105-
if debug {
106-
fmt.Fprintln(out, dnsError)
107-
}
108-
fmt.Fprintln(out, "check your internet connection or https://status.algolia.com")
109-
return
110-
}
111-
112-
fmt.Fprintln(out, err)
113-
114-
var flagError *cmdutil.FlagError
115-
if errors.As(err, &flagError) || strings.HasPrefix(err.Error(), "unknown command ") {
116-
if !strings.HasSuffix(err.Error(), "\n") {
117-
fmt.Fprintln(out)
118-
}
119-
fmt.Fprintln(out, cmd.UsageString())
120-
}
121-
}

go.mod

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ require (
77
github.com/BurntSushi/toml v1.0.0
88
github.com/MakeNowJust/heredoc v1.0.0
99
github.com/algolia/algoliasearch-client-go/v3 v3.21.0
10+
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect
1011
github.com/briandowns/spinner v1.13.0
1112
github.com/cli/safeexec v1.0.0
1213
github.com/dustin/go-humanize v1.0.0
@@ -20,12 +21,15 @@ require (
2021
github.com/mitchellh/go-homedir v1.1.0
2122
github.com/muesli/reflow v0.3.0
2223
github.com/muesli/termenv v0.9.0
24+
github.com/segmentio/backo-go v1.0.0 // indirect
2325
github.com/sirupsen/logrus v1.8.1
2426
github.com/spf13/cobra v1.4.0
2527
github.com/spf13/pflag v1.0.5
2628
github.com/spf13/viper v1.9.0
2729
github.com/stretchr/testify v1.7.0
30+
github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c // indirect
2831
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881 // indirect
2932
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211
3033
gopkg.in/yaml.v3 v3.0.1
34+
gopkg.in/segmentio/analytics-go.v3 v3.1.0
3135
)

go.sum

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV
6161
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
6262
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
6363
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
64+
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
65+
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
6466
github.com/briandowns/spinner v1.13.0 h1:q/Y9LtpwtvL0CRzXrAMj0keVXqNhBYUFg6tBOUiY8ek=
6567
github.com/briandowns/spinner v1.13.0/go.mod h1:QOuQk7x+EaDASo80FEXwlwiA+j/PPIcX3FScO+3/ZPQ=
6668
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
@@ -292,6 +294,8 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
292294
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
293295
github.com/sagikazarmark/crypt v0.1.0/go.mod h1:B/mN0msZuINBtQ1zZLEQcegFJJf9vnYIR88KRMEuODE=
294296
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
297+
github.com/segmentio/backo-go v1.0.0 h1:kbOAtGJY2DqOR0jfRkYEorx/b18RgtepGtY3+Cpe6qA=
298+
github.com/segmentio/backo-go v1.0.0/go.mod h1:kJ9mm9YmoWSkk+oQ+5Cj8DEoRCX2JT6As4kEtIIOp1M=
295299
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
296300
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
297301
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
@@ -318,6 +322,8 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc
318322
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
319323
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
320324
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
325+
github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c h1:3lbZUMbMiGUW/LMkfsEABsc5zNT9+b1CvsJx47JzJ8g=
326+
github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c/go.mod h1:UrdRz5enIKZ63MEE3IF9l2/ebyx59GyGgPi+tICQdmM=
321327
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
322328
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
323329
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -709,6 +715,8 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8
709715
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
710716
gopkg.in/ini.v1 v1.63.2 h1:tGK/CyBg7SMzb60vP1M03vNZ3VDu3wGQJwn7Sxi9r3c=
711717
gopkg.in/ini.v1 v1.63.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
718+
gopkg.in/segmentio/analytics-go.v3 v3.1.0 h1:UzxH1uaGZRpMKDhJyBz0pexz6yUoBU3x8bJsRk/HV6U=
719+
gopkg.in/segmentio/analytics-go.v3 v3.1.0/go.mod h1:4QqqlTlSSpVlWA9/9nDcPw+FkM2yv1NQoYjUbL9/JAw=
712720
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
713721
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
714722
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

pkg/cmd/root/root.go

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,21 @@
33
package root
44

55
import (
6+
"context"
7+
"errors"
8+
"fmt"
9+
"io"
10+
"net"
11+
"os"
12+
"strings"
13+
14+
"github.com/AlecAivazis/survey/v2/terminal"
615
"github.com/MakeNowJust/heredoc"
716
"github.com/spf13/cobra"
817

918
"github.com/algolia/cli/pkg/cmd/apikey"
1019
"github.com/algolia/cli/pkg/cmd/application"
20+
"github.com/algolia/cli/pkg/cmd/factory"
1121
"github.com/algolia/cli/pkg/cmd/index"
1222
"github.com/algolia/cli/pkg/cmd/objects"
1323
"github.com/algolia/cli/pkg/cmd/open"
@@ -16,9 +26,20 @@ import (
1626
"github.com/algolia/cli/pkg/cmd/settings"
1727
"github.com/algolia/cli/pkg/cmd/synonyms"
1828
"github.com/algolia/cli/pkg/cmdutil"
29+
"github.com/algolia/cli/pkg/config"
30+
"github.com/algolia/cli/pkg/telemetry"
1931
"github.com/algolia/cli/pkg/version"
2032
)
2133

34+
type exitCode int
35+
36+
const (
37+
exitOK exitCode = 0
38+
exitError exitCode = 1
39+
exitCancel exitCode = 2
40+
exitAuth exitCode = 4
41+
)
42+
2243
func NewRootCmd(f *cmdutil.Factory) *cobra.Command {
2344
cmd := &cobra.Command{
2445
Use: "algolia <command> <subcommand> [flags]",
@@ -73,3 +94,146 @@ func NewRootCmd(f *cmdutil.Factory) *cobra.Command {
7394

7495
return cmd
7596
}
97+
98+
func Execute() exitCode {
99+
hasDebug := os.Getenv("DEBUG") != ""
100+
hasTelemetry := os.Getenv("ALGOLIA_CLI_TELEMETRY") != "0"
101+
fmt.Println("hasDebug:", hasDebug)
102+
fmt.Println("hasTelemetry:", hasTelemetry)
103+
104+
// Set up the command factory.
105+
cfg := config.Config{}
106+
cfg.InitConfig()
107+
cmdFactory := factory.New(&cfg)
108+
stderr := cmdFactory.IOStreams.ErrOut
109+
110+
// Set up the root command.
111+
rootCmd := NewRootCmd(cmdFactory)
112+
113+
// Pre-command auth check and telemetry setup.
114+
authError := errors.New("authError")
115+
rootCmd.PersistentPreRunE = func(cmd *cobra.Command, args []string) error {
116+
if cmdutil.IsAuthCheckEnabled(cmd) {
117+
if err := cmdutil.CheckAuth(cfg); err != nil {
118+
fmt.Fprintf(stderr, "Authentication error: %s\n", err)
119+
fmt.Fprintln(stderr, "Please run `algolia application add` to configure your first application.")
120+
return authError
121+
}
122+
}
123+
124+
// Initialize telemetry context.
125+
appID, err := cfg.Application.GetID()
126+
if err != nil {
127+
appID = ""
128+
}
129+
telemetryMetadata := telemetry.GetEventMetadata(cmd.Context())
130+
telemetryMetadata.SetCobraCommandContext(cmd)
131+
telemetryMetadata.SetAppID(appID)
132+
telemetryMetadata.SetConfiguredApplicationsNb(len(cfg.ConfiguredApplications()))
133+
134+
ctx := cmd.Context()
135+
telemetryClient := telemetry.GetTelemetryClient(ctx)
136+
137+
// Identify the user.
138+
err = telemetryClient.Identify(ctx)
139+
if err != nil && hasDebug {
140+
fmt.Fprintf(stderr, "Failed to identify user: %s\n", err)
141+
return err
142+
}
143+
144+
// Send telemetry.
145+
err = telemetryClient.Track(ctx, "Command Invoked")
146+
if err != nil && hasDebug {
147+
fmt.Fprintf(stderr, "Error tracking telemetry: %s\n", err)
148+
}
149+
150+
return nil
151+
}
152+
153+
// Command context is used to pass information to the telemetry client.
154+
ctx, err := createContext(rootCmd, stderr, hasDebug, hasTelemetry)
155+
if err != nil {
156+
printError(stderr, err, rootCmd, hasDebug)
157+
return exitError
158+
}
159+
160+
// Run the command.
161+
cmd, err := rootCmd.ExecuteContextC(ctx)
162+
163+
// Post-command telemetry
164+
ctx = cmd.Context()
165+
telemetryClient := telemetry.GetTelemetryClient(ctx)
166+
telemetryErr := telemetryClient.Track(ctx, "Command Finished")
167+
if telemetryErr != nil && hasDebug {
168+
fmt.Fprintf(stderr, "Error tracking telemetry: %s\n", err)
169+
}
170+
telemetryErr = telemetryClient.Close() // flush telemetry events
171+
if telemetryErr != nil && hasDebug {
172+
fmt.Fprintf(stderr, "Error closing telemetry client: %s\n", err)
173+
}
174+
175+
// Handle eventual errors.
176+
if err != nil {
177+
if err == cmdutil.ErrSilent {
178+
return exitError
179+
} else if cmdutil.IsUserCancellation(err) {
180+
if errors.Is(err, terminal.InterruptErr) {
181+
// ensure the next shell prompt will start on its own line
182+
fmt.Fprint(stderr, "\n")
183+
}
184+
return exitCancel
185+
} else if errors.Is(err, authError) {
186+
return exitAuth
187+
}
188+
189+
printError(stderr, err, cmd, hasDebug)
190+
return exitError
191+
}
192+
193+
return exitOK
194+
}
195+
196+
// createContext creates a context with telemetry.
197+
func createContext(cmd *cobra.Command, stderr io.Writer, hasTelemetry bool, hasDebug bool) (context.Context, error) {
198+
ctx := context.Background()
199+
telemetryMetadata := telemetry.NewEventMetadata()
200+
updatedCtx := telemetry.WithEventMetadata(ctx, telemetryMetadata)
201+
202+
var telemetryClient telemetry.TelemetryClient
203+
var err error
204+
if hasTelemetry {
205+
telemetryClient, err = telemetry.NewAnalyticsTelemetryClient()
206+
// Fail silently if telemetry is not available unless in debug mode.
207+
if err != nil && hasDebug {
208+
fmt.Fprintf(stderr, "Error creating telemetry client: %s\n", err)
209+
return nil, err
210+
}
211+
} else {
212+
telemetryClient = &telemetry.NoOpTelemetryClient{}
213+
}
214+
contextWithTelemetry := telemetry.WithTelemetryClient(updatedCtx, telemetryClient)
215+
return contextWithTelemetry, nil
216+
}
217+
218+
// printError prints an error to the stderr, with additional information if applicable.
219+
func printError(out io.Writer, err error, cmd *cobra.Command, debug bool) {
220+
var dnsError *net.DNSError
221+
if errors.As(err, &dnsError) {
222+
fmt.Fprintf(out, "error connecting to %s\n", dnsError.Name)
223+
if debug {
224+
fmt.Fprintln(out, dnsError)
225+
}
226+
fmt.Fprintln(out, "check your internet connection or https://status.algolia.com")
227+
return
228+
}
229+
230+
fmt.Fprintln(out, err)
231+
232+
var flagError *cmdutil.FlagError
233+
if errors.As(err, &flagError) || strings.HasPrefix(err.Error(), "unknown command ") {
234+
if !strings.HasSuffix(err.Error(), "\n") {
235+
fmt.Fprintln(out)
236+
}
237+
fmt.Fprintln(out, cmd.UsageString())
238+
}
239+
}

cmd/algolia/main_test.go renamed to pkg/cmd/root/root_help.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package main
1+
package root
22

33
import (
44
"bytes"

0 commit comments

Comments
 (0)