Skip to content
This repository was archived by the owner on Aug 30, 2024. It is now read-only.

Commit 7a48de0

Browse files
committed
More clog additions
1 parent 358a044 commit 7a48de0

File tree

5 files changed

+66
-25
lines changed

5 files changed

+66
-25
lines changed

cmd/coder/main.go

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import (
1212
"cdr.dev/coder-cli/internal/clog"
1313
"cdr.dev/coder-cli/internal/cmd"
1414
"cdr.dev/coder-cli/internal/x/xterminal"
15-
"golang.org/x/xerrors"
1615

1716
"go.coder.com/flog"
1817
)
@@ -44,12 +43,7 @@ func main() {
4443
app.Version = fmt.Sprintf("%s %s %s/%s", version, runtime.Version(), runtime.GOOS, runtime.GOARCH)
4544

4645
if err := app.ExecuteContext(ctx); err != nil {
47-
var cliErr clog.RichCLIMessage
48-
if xerrors.As(err, &cliErr) {
49-
fmt.Println(cliErr.Error())
50-
os.Exit(1)
51-
} else {
52-
flog.Fatal("%v", err)
53-
}
46+
clog.Log(err)
47+
os.Exit(1)
5448
}
5549
}

coder-sdk/error.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ import (
1212
// ErrNotFound describes an error case in which the requested resource could not be found
1313
var ErrNotFound = xerrors.Errorf("resource not found")
1414

15-
// apiError is the expected payload format for our errors.
16-
type apiError struct {
15+
// APIError is the expected payload format for our errors.
16+
type APIError struct {
1717
Err struct {
1818
Msg string `json:"msg"`
1919
} `json:"error"`
@@ -30,15 +30,15 @@ func (e *HTTPError) Error() string {
3030
return fmt.Sprintf("dump response: %+v", err)
3131
}
3232

33-
var msg apiError
33+
var msg APIError
3434
// Try to decode the payload as an error, if it fails or if there is no error message,
3535
// return the response URL with the dump.
3636
if err := json.NewDecoder(e.Response.Body).Decode(&msg); err != nil || msg.Err.Msg == "" {
3737
return fmt.Sprintf("%s\n%s", e.Response.Request.URL, dump)
3838
}
3939

4040
// If the payload was a in the expected error format with a message, include it.
41-
return fmt.Sprintf("%s\n%s%s", e.Response.Request.URL, dump, msg.Err.Msg)
41+
return msg.Err.Msg
4242
}
4343

4444
func bodyError(resp *http.Response) error {

internal/clog/error.go

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package clog
22

33
import (
4+
"errors"
45
"fmt"
56
"strings"
67

78
"github.com/fatih/color"
9+
"golang.org/x/xerrors"
810
)
911

1012
// RichCLIMessage provides a human-readable message for CLI errors and messages.
@@ -13,10 +15,11 @@ type RichCLIMessage struct {
1315
Color color.Attribute
1416
Header string
1517
Lines []string
18+
error
1619
}
1720

1821
// Error formats the CLI message for consumption by a human as an error.
19-
func (r RichCLIMessage) Error() string {
22+
func (r RichCLIMessage) String() string {
2023
var str strings.Builder
2124
str.WriteString(fmt.Sprintf("%s: %s\n",
2225
color.New(r.Color).Sprint(r.Level),
@@ -29,37 +32,75 @@ func (r RichCLIMessage) Error() string {
2932
}
3033

3134
// String gives the same formatting as Error.
32-
func (r RichCLIMessage) String() string {
33-
return r.Error()
35+
func (r RichCLIMessage) Error() string {
36+
return r.error.Error()
37+
}
38+
39+
func Wrap(err error, msg string) error {
40+
var cliError RichCLIMessage
41+
if xerrors.As(err, &cliError) {
42+
return xerrors.Errorf("%s: %w", msg, cliError.error)
43+
}
44+
return xerrors.Errorf("%s: %w", msg, err)
45+
}
46+
47+
func Log(err error) {
48+
var cliErr RichCLIMessage
49+
if !xerrors.As(err, &cliErr) {
50+
cliErr = Fatal(err.Error())
51+
}
52+
fmt.Println(cliErr.String())
53+
}
54+
55+
56+
// Info formats according to a format specifier and prints the resulting CLI message.
57+
func Info(format string, args ...interface{}) {
58+
fmt.Println(RichCLIMessage{
59+
Level: "info",
60+
Color: color.FgBlue,
61+
Header: fmt.Sprintf(format, args...),
62+
}.String())
63+
}
64+
65+
// Success formats according to a format specifier and prints the resulting CLI message.
66+
func Success(format string, args ...interface{}) {
67+
fmt.Println(RichCLIMessage{
68+
Level: "success",
69+
Color: color.FgGreen,
70+
Header: fmt.Sprintf(format, args...),
71+
}.String())
3472
}
3573

3674
// Warn creates an error with the level "warning".
37-
func Warn(header string, lines ...string) error {
75+
func Warn(header string, lines ...string) RichCLIMessage {
3876
return RichCLIMessage{
3977
Color: color.FgYellow,
4078
Level: "warning",
4179
Header: header,
4280
Lines: lines,
81+
error: errors.New(header),
4382
}
4483
}
4584

4685
// Error creates an error with the level "error".
47-
func Error(header string, lines ...string) error {
86+
func Error(header string, lines ...string) RichCLIMessage {
4887
return RichCLIMessage{
4988
Color: color.FgRed,
5089
Level: "error",
5190
Header: header,
5291
Lines: lines,
92+
error: errors.New(header),
5393
}
5494
}
5595

5696
// Fatal creates an error with the level "fatal".
57-
func Fatal(header string, lines ...string) error {
97+
func Fatal(header string, lines ...string) RichCLIMessage {
5898
return RichCLIMessage{
5999
Color: color.FgRed,
60100
Level: "fatal",
61101
Header: header,
62102
Lines: lines,
103+
error: errors.New(header),
63104
}
64105
}
65106

internal/cmd/ceapi.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ func findEnv(ctx context.Context, client *coder.Client, envName, userEmail strin
7878
"failed to find environment",
7979
fmt.Sprintf("environment %q not found in %q", envName, found),
8080
"",
81-
clog.Bold("tip: ")+"view your environments with \"coder envs ls\"",
81+
clog.Bold("tip: ")+"run \"coder envs ls\" to view your environments",
8282
)
8383
}
8484

internal/cmd/envs.go

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@ package cmd
22

33
import (
44
"encoding/json"
5+
"fmt"
56
"os"
7+
"sync/atomic"
68

79
"cdr.dev/coder-cli/coder-sdk"
10+
"cdr.dev/coder-cli/internal/clog"
811
"cdr.dev/coder-cli/internal/x/xtabwriter"
912
"github.com/spf13/cobra"
1013
"golang.org/x/sync/errgroup"
@@ -92,26 +95,29 @@ coder envs --user charlie@coder.com ls -o json \
9295
}
9396

9497
var egroup errgroup.Group
98+
var fails int32
9599
for _, envName := range args {
96100
envName := envName
97101
egroup.Go(func() error {
98102
env, err := findEnv(cmd.Context(), client, envName, *user)
99103
if err != nil {
100-
flog.Error("failed to find environment by name \"%s\": %v", envName, err)
101-
return xerrors.Errorf("find environment by name: %w", err)
104+
atomic.AddInt32(&fails, 1)
105+
clog.Log(err)
106+
return clog.Wrap(err, "find env by name")
102107
}
103108

104109
if err = client.StopEnvironment(cmd.Context(), env.ID); err != nil {
105-
flog.Error("failed to stop environment \"%s\": %v", env.Name, err)
106-
return xerrors.Errorf("stop environment: %w", err)
110+
atomic.AddInt32(&fails, 1)
111+
clog.Log(err)
112+
return clog.Wrap(err, "stop environment")
107113
}
108-
flog.Success("Successfully stopped environment %q", envName)
114+
clog.Success("successfully stopped environment %q", envName)
109115
return nil
110116
})
111117
}
112118

113119
if err = egroup.Wait(); err != nil {
114-
return xerrors.Errorf("some stop operations failed")
120+
return clog.Fatal(fmt.Sprintf("%d failure(s) emitted", fails))
115121
}
116122
return nil
117123
},

0 commit comments

Comments
 (0)