diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 996a13a1..81c7a10d 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -19,17 +19,12 @@ jobs: lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 - - uses: actions/cache@v1 - with: - path: ~/go/pkg/mod - key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-go- - - name: lint - uses: ./ci/image + - uses: actions/checkout@v2 + - name: golangci-lint + uses: golangci/golangci-lint-action@v2 with: - args: ./ci/steps/lint.sh + # Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version. + version: v1.29 test: runs-on: ubuntu-latest steps: diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 00000000..aa56dabb --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,17 @@ +# See https://golangci-lint.run/usage/configuration/ +linters-settings: + goconst: + min-len: 4 + min-occurrences: 3 + gocognit: + min-complexity: 46 + nestif: + min-complexity: 10 + golint: + govet: + settings: + printf: + funcs: # Run `go tool vet help printf` to see available settings for `printf` analyzer. + - (cdr.dev/coder-cli/internal/clog).Tipf + - (cdr.dev/coder-cli/internal/clog).Hintf + - (cdr.dev/coder-cli/internal/clog).Causef \ No newline at end of file diff --git a/ci/image/Dockerfile b/ci/image/Dockerfile index cb06bf81..8eb77371 100644 --- a/ci/image/Dockerfile +++ b/ci/image/Dockerfile @@ -4,5 +4,4 @@ ENV GOFLAGS="-mod=readonly" ENV CI=true RUN go get golang.org/x/tools/cmd/goimports -RUN go get golang.org/x/lint/golint -RUN go get github.com/mattn/goveralls \ No newline at end of file +RUN go get github.com/mattn/goveralls diff --git a/ci/steps/lint.sh b/ci/steps/lint.sh index c3f72614..dcb2acaa 100755 --- a/ci/steps/lint.sh +++ b/ci/steps/lint.sh @@ -4,5 +4,8 @@ set -euo pipefail echo "Linting..." -go vet ./... -golint -set_exit_status ./... +cd "$(dirname "$0")" +cd ../../ + +echo "--- golangci-lint" +golangci-lint run -c .golangci.yml diff --git a/internal/clog/error.go b/internal/clog/error.go index 71183573..66d28ec1 100644 --- a/internal/clog/error.go +++ b/internal/clog/error.go @@ -112,18 +112,18 @@ func Bold(a string) string { return color.New(color.Bold).Sprint(a) } -// Tip formats according to the given format specifier and prepends a bolded "tip: " header. -func Tip(format string, a ...interface{}) string { +// Tipf formats according to the given format specifier and prepends a bolded "tip: " header. +func Tipf(format string, a ...interface{}) string { return fmt.Sprintf("%s %s", Bold("tip:"), fmt.Sprintf(format, a...)) } -// Hint formats according to the given format specifier and prepends a bolded "hint: " header. -func Hint(format string, a ...interface{}) string { +// Hintf formats according to the given format specifier and prepends a bolded "hint: " header. +func Hintf(format string, a ...interface{}) string { return fmt.Sprintf("%s %s", Bold("hint:"), fmt.Sprintf(format, a...)) } -// Cause formats according to the given format specifier and prepends a bolded "cause: " header. -func Cause(format string, a ...interface{}) string { +// Causef formats according to the given format specifier and prepends a bolded "cause: " header. +func Causef(format string, a ...interface{}) string { return fmt.Sprintf("%s %s", Bold("cause:"), fmt.Sprintf(format, a...)) } diff --git a/internal/cmd/auth.go b/internal/cmd/auth.go index ff789ca3..b0105ac4 100644 --- a/internal/cmd/auth.go +++ b/internal/cmd/auth.go @@ -14,7 +14,7 @@ import ( var errNeedLogin = clog.Fatal( "failed to read session credentials", - clog.Hint(`did you run "coder login [https://coder.domain.com]"?`), + clog.Hintf(`did you run "coder login [https://coder.domain.com]"?`), ) func newClient() (*coder.Client, error) { diff --git a/internal/cmd/ceapi.go b/internal/cmd/ceapi.go index f9b4ebe6..5c6297ad 100644 --- a/internal/cmd/ceapi.go +++ b/internal/cmd/ceapi.go @@ -78,15 +78,6 @@ func findEnv(ctx context.Context, client *coder.Client, envName, userEmail strin "failed to find environment", fmt.Sprintf("environment %q not found in %q", envName, found), clog.BlankLine, - clog.Tip("run \"coder envs ls\" to view your environments"), + clog.Tipf("run \"coder envs ls\" to view your environments"), ) } - -type notFoundButDidFind struct { - needle string - haystack []string -} - -func (n notFoundButDidFind) Error() string { - return fmt.Sprintf("\"%s\" not found in %q: %v", n.needle, n.haystack, coder.ErrNotFound) -} diff --git a/internal/cmd/envs.go b/internal/cmd/envs.go index f5c6d84c..6aea5afa 100644 --- a/internal/cmd/envs.go +++ b/internal/cmd/envs.go @@ -117,8 +117,8 @@ coder envs --user charlie@coder.com ls -o json \ if err = client.StopEnvironment(cmd.Context(), env.ID); err != nil { atomic.AddInt32(&fails, 1) err = clog.Fatal(fmt.Sprintf("stop environment %q", env.Name), - clog.Cause(err.Error()), clog.BlankLine, - clog.Hint("current environment status is %q", env.LatestStat.ContainerStatus), + clog.Causef(err.Error()), clog.BlankLine, + clog.Hintf("current environment status is %q", env.LatestStat.ContainerStatus), ) clog.Log(err) return err @@ -186,7 +186,7 @@ coder envs create --cpu 4 --disk 100 --memory 8 --image 5f443b16-30652892427b955 clog.LogSuccess( "creating environment...", clog.BlankLine, - clog.Tip(`run "coder envs watch-build %q" to trail the build logs`, args[0]), + clog.Tipf(`run "coder envs watch-build %q" to trail the build logs`, args[0]), ) if follow { @@ -205,7 +205,7 @@ coder envs create --cpu 4 --disk 100 --memory 8 --image 5f443b16-30652892427b955 cmd.Flags().IntP("gpus", "g", defaultGPUs, "number GPUs an environment should be provisioned with.") cmd.Flags().StringVarP(&img, "image", "i", "", "ID of the image to base the environment off of.") cmd.Flags().BoolVar(&follow, "follow", false, "follow buildlog after initiating rebuild") - cmd.MarkFlagRequired("image") + _ = cmd.MarkFlagRequired("image") return cmd } @@ -296,7 +296,7 @@ coder envs edit back-end-env --disk 20`, clog.LogSuccess( "applied changes to the environment, rebuilding...", clog.BlankLine, - clog.Tip(`run "coder envs watch-build %q" to trail the build logs`, envName), + clog.Tipf(`run "coder envs watch-build %q" to trail the build logs`, envName), ) return nil }, diff --git a/internal/cmd/login.go b/internal/cmd/login.go index fdcbe765..2984822b 100644 --- a/internal/cmd/login.go +++ b/internal/cmd/login.go @@ -40,7 +40,7 @@ func makeLoginCmd() *cobra.Command { // Don't return errors as it would print the usage. if err := login(cmd, u, config.URL, config.Session); err != nil { - return xerrors.Errorf("Login error", err) + return xerrors.Errorf("login error: %w", err) } return nil }, diff --git a/internal/cmd/rebuild.go b/internal/cmd/rebuild.go index 41f3913d..8e6de326 100644 --- a/internal/cmd/rebuild.go +++ b/internal/cmd/rebuild.go @@ -58,7 +58,7 @@ coder envs rebuild backend-env --force`, } else { clog.LogSuccess( "successfully started rebuild", - clog.Tip("run \"coder envs watch-build %s\" to follow the build logs", env.Name), + clog.Tipf("run \"coder envs watch-build %s\" to follow the build logs", env.Name), ) } return nil @@ -75,7 +75,6 @@ coder envs rebuild backend-env --force`, func trailBuildLogs(ctx context.Context, client *coder.Client, envID string) error { const check = "✅" const failure = "❌" - const loading = "⌛" newSpinner := func() *spinner.Spinner { return spinner.New(spinner.CharSets[11], 100*time.Millisecond) } diff --git a/internal/cmd/resourcemanager.go b/internal/cmd/resourcemanager.go index d4ee20bb..515318fc 100644 --- a/internal/cmd/resourcemanager.go +++ b/internal/cmd/resourcemanager.go @@ -214,7 +214,7 @@ func printResourceTop(writer io.Writer, groups []groupable, labeler envLabeler, if len(userResources) == 0 { clog.LogInfo( "no groups for the given filters exist with active environments", - clog.Tip("run \"--show-empty\" to see groups with no resources."), + clog.Tipf("run \"--show-empty\" to see groups with no resources."), ) } return nil @@ -318,6 +318,7 @@ func (a resources) String() string { // ) } +//nolint:unused func (a resources) cpuUtilPercentage() string { if a.cpuAllocation == 0 { return "N/A" @@ -325,6 +326,7 @@ func (a resources) cpuUtilPercentage() string { return fmt.Sprintf("%.1f%%", a.cpuUtilization/a.cpuAllocation*100) } +//nolint:unused func (a resources) memUtilPercentage() string { if a.memAllocation == 0 { return "N/A" diff --git a/internal/cmd/shell.go b/internal/cmd/shell.go index 9903058a..18197570 100644 --- a/internal/cmd/shell.go +++ b/internal/cmd/shell.go @@ -201,7 +201,7 @@ func networkErr(client *coder.Client, env *coder.Environment) error { fmt.Sprintf("environment %q is not running", env.Name), fmt.Sprintf("its current status is %q", env.LatestStat.ContainerStatus), clog.BlankLine, - clog.Tip("run \"coder envs rebuild %s --follow\" to start the environment", env.Name), + clog.Tipf("run \"coder envs rebuild %s --follow\" to start the environment", env.Name), ) } return xerrors.Errorf("network error, is %q online?", env.Name)