From c38eeeb073c60d5821698ba6c0a4e9d7a3dcddfc Mon Sep 17 00:00:00 2001 From: Zachary Scott Date: Wed, 6 Jun 2018 20:48:32 +0900 Subject: [PATCH] Add docs to fix linting errors Also adds the following make tasks: * doc: easily run godoc to view package docs * dev: install godoc and gometalinter development dependencies As a side-effect, debug now prints to stderr --- Makefile | 10 ++++++++++ README.md | 19 +++++++++++++++++-- client/client.go | 7 +++++++ cmd/root.go | 5 ++++- logger/logger.go | 25 +++++++++++++++++++++++-- 5 files changed, 61 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index f3b289b0e..792e6a805 100644 --- a/Makefile +++ b/Makefile @@ -32,3 +32,13 @@ cover: .PHONY: lint lint: gometalinter --deadline 60s --vendor ./... + +.PHONY: doc +doc: + godoc -http=:6060 + +.PHONY: dev +dev: + go get golang.org/x/tools/cmd/godoc + go get -u github.com/alecthomas/gometalinter + gometalinter --install diff --git a/README.md b/README.md index 1dcb82fe0..43475461a 100644 --- a/README.md +++ b/README.md @@ -75,15 +75,30 @@ To make sure dependencies are installed: $ dep ensure ``` +## Linting + +We use [`gometalinter`](github.com/alecthomas/gometalinter) for linting. + +You can install it via `$ make dev` or manually with: + +``` +$ go get -u github.com/alecthomas/gometalinter +$ gometalinter --install +``` + +Then you can run it with `$ make lint`. + ## Known Issues * ... ## Doc -You can view `godoc` of cli in your browser. +You can view `godoc` of the cli in your browser. + +After installing it either via `go get golang.org/x/tools/cmd/godoc` or running `make dev`. -1. Run `godoc -http=:6060` +1. Run `make doc` or `godoc -http=:6060` 2. Access http://localhost:6060/pkg/github.com/circleci/circleci-cli/ ## Editor support diff --git a/client/client.go b/client/client.go index 448500f93..79adb65b3 100644 --- a/client/client.go +++ b/client/client.go @@ -7,6 +7,7 @@ import ( "github.com/machinebox/graphql" ) +// Client wraps a graphql.Client and other fields for making API calls. type Client struct { endpoint string token string @@ -14,6 +15,9 @@ type Client struct { logger *logger.Logger } +// NewClient returns a reference to a Client. +// We also call graphql.NewClient to initialize a new GraphQL Client. +// Then we pass the Logger originally constructed as cmd.Logger. func NewClient(endpoint string, token string, logger *logger.Logger) *Client { return &Client{ endpoint, @@ -23,6 +27,9 @@ func NewClient(endpoint string, token string, logger *logger.Logger) *Client { } } +// Run will construct a request using graphql.NewRequest. +// Then it will execute the given query using graphql.Client.Run. +// This function will return the unmarshalled response as JSON. func (c *Client) Run(query string) (map[string]interface{}, error) { req := graphql.NewRequest(query) req.Header.Set("Authorization", c.token) diff --git a/cmd/root.go b/cmd/root.go index 253791281..de9a624cc 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -31,9 +31,12 @@ var ( cfgFile string cfgName = "cli" cfgPathDefault = fmt.Sprintf("%s/.circleci/%s.yml", os.Getenv("HOME"), cfgName) - Logger *logger.Logger ) +// Logger is exposed here so we can access it from subcommands. +// This allows us to print to the log at anytime from within the `cmd` package. +var Logger *logger.Logger + func addCommands() { rootCmd.AddCommand(diagnosticCmd) rootCmd.AddCommand(queryCmd) diff --git a/logger/logger.go b/logger/logger.go index 039736263..6304960ef 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -5,6 +5,8 @@ import ( "os" ) +// Logger wraps a few log.Logger instances in private fields. +// They are accessible via their respective methods. type Logger struct { debug *log.Logger info *log.Logger @@ -12,33 +14,52 @@ type Logger struct { verbose bool } +// NewLogger returns a reference to a Logger. +// We usually call this when initializing cmd.Logger. +// Later we pass this to client.NewClient so it can also log. +// By default debug and error go to os.Stderr, and info goes to os.Stdout func NewLogger(verbose bool) *Logger { return &Logger{ - log.New(os.Stdout, "", 0), + log.New(os.Stderr, "", 0), log.New(os.Stdout, "", 0), log.New(os.Stderr, "", 0), verbose, } } +// Debug prints a formatted message to stderr only if verbose is set. +// Consider these messages useful for developers of the CLI. +// This method wraps log.Logger.Printf func (l *Logger) Debug(format string, args ...interface{}) { if l.verbose { l.debug.Printf(format, args...) } } +// Info prints all args to os.Stdout +// It's commonly used for messages we want to show the user. +// This method wraps log.Logger.Print func (l *Logger) Info(args ...interface{}) { l.info.Print(args...) } +// Infof prints a formatted message to stdout +// This method wraps log.Logger.Printf func (l *Logger) Infof(format string, args ...interface{}) { l.info.Printf(format, args...) } +// Error prints a message and the given error's message to os.Stderr +// This method wraps log.Logger.Print func (l *Logger) Error(msg string, err error) { - l.error.Print(msg, err.Error()) + if err != nil { + l.error.Print(msg, err.Error()) + } } +// FatalOnError prints a message and error's message to os.Stderr then QUITS! +// Please be aware this method will exit the program via os.Exit(1). +// This method wraps log.Logger.Fatalln func (l *Logger) FatalOnError(msg string, err error) { if err != nil { l.error.Fatalln(msg, err.Error())