diff --git a/.circleci/config.yml b/.circleci/config.yml index f791c23..435372d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,8 +1,8 @@ version: 2 jobs: - build-go1.19: + build-go1.20: docker: - - image: golang:1.19 + - image: golang:1.20 working_directory: /go/src/github.com/kolide/kit steps: &steps - checkout @@ -13,4 +13,4 @@ workflows: version: 2 build: jobs: - - build-go1.19 + - build-go1.20 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..cd2af3a --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +# set line endings for go files. Mostly needed for golang-ci +*.go text eol=lf + diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml new file mode 100644 index 0000000..6b083ef --- /dev/null +++ b/.github/workflows/golangci-lint.yml @@ -0,0 +1,33 @@ +name: golangci-lint + +on: + push: + branches: [main, master] + pull_request: + branches: '**' + +jobs: + golangci: + strategy: + fail-fast: false + matrix: + os: [macos-latest, windows-latest, ubuntu-latest] + name: lint + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v2 + + - name: Set up Go + uses: actions/setup-go@v2 + with: + go-version: '1.20.4' + + - name: golangci-lint + uses: golangci/golangci-lint-action@v3 + with: + skip-pkg-cache: true + + # Run again as a workaround for https://github.com/golangci/golangci-lint-action/issues/362 + - name: golangci-lint + if: ${{ always() }} + run: golangci-lint run diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..8ac8a07 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,39 @@ +run: + skip-dirs: + - test-cmds + timeout: 5m + +linters: + enable: + - bodyclose + - unused + - gofmt + - govet + - misspell + - nakedret + - unconvert + - paralleltest + disable: + - errcheck + - gosec + - gosimple + - ineffassign + - interfacer + - maligned + - noctx + - staticcheck + - structcheck + - varcheck + +linters-settings: + errcheck: + ignore: github.com/go-kit/kit/log:Log + gofmt: + simplify: false + +issues: + exclude-rules: + # False positive: https://github.com/kunwardeep/paralleltest/issues/8. + - linters: + - paralleltest + text: "does not use range value in test Run" diff --git a/entrypoint/entrypoint.go b/entrypoint/entrypoint.go index de2d978..3ba7352 100644 --- a/entrypoint/entrypoint.go +++ b/entrypoint/entrypoint.go @@ -1,8 +1,10 @@ /* - Package entrypoint replaces the shell version of - exec $@ - which is often use when creating docker entrypoint scripts to wrap a - binary with some initial setup. +Package entrypoint replaces the shell version of + + exec $@ + +which is often use when creating docker entrypoint scripts to wrap a +binary with some initial setup. */ package entrypoint diff --git a/env/env_test.go b/env/env_test.go index 0711925..07c3984 100644 --- a/env/env_test.go +++ b/env/env_test.go @@ -7,7 +7,7 @@ import ( "time" ) -func TestDuration(t *testing.T) { +func TestDuration(t *testing.T) { //nolint:paralleltest var tests = []struct { value time.Duration }{ @@ -16,7 +16,7 @@ func TestDuration(t *testing.T) { {value: 1 * time.Hour}, } - for _, tt := range tests { + for _, tt := range tests { //nolint:paralleltest t.Run(tt.value.String(), func(t *testing.T) { key := strings.ToUpper(tt.value.String()) if err := os.Setenv(key, tt.value.String()); err != nil { @@ -37,7 +37,7 @@ func TestDuration(t *testing.T) { } } -func TestString(t *testing.T) { +func TestString(t *testing.T) { //nolint:paralleltest var tests = []struct { value string }{ @@ -46,7 +46,7 @@ func TestString(t *testing.T) { {value: "baz"}, } - for _, tt := range tests { + for _, tt := range tests { //nolint:paralleltest t.Run(tt.value, func(t *testing.T) { key := strings.ToUpper(tt.value) if err := os.Setenv(key, tt.value); err != nil { @@ -67,7 +67,7 @@ func TestString(t *testing.T) { } } -func TestBool(t *testing.T) { +func TestBool(t *testing.T) { //nolint:paralleltest var tests = []struct { env string value bool @@ -81,7 +81,7 @@ func TestBool(t *testing.T) { {env: "0", value: false}, } - for _, tt := range tests { + for _, tt := range tests { //nolint:paralleltest t.Run(tt.env, func(t *testing.T) { key := "TEST_BOOL" if err := os.Setenv(key, tt.env); err != nil { @@ -106,7 +106,7 @@ func TestBool(t *testing.T) { } } -func TestInt(t *testing.T) { +func TestInt(t *testing.T) { //nolint:paralleltest var tests = []struct { env string value int @@ -117,7 +117,7 @@ func TestInt(t *testing.T) { {env: "0", value: 0}, } - for _, tt := range tests { + for _, tt := range tests { //nolint:paralleltest t.Run(tt.env, func(t *testing.T) { key := "TEST_INT" if err := os.Setenv(key, tt.env); err != nil { diff --git a/fsutil/filesystem_test.go b/fsutil/filesystem_test.go index 2d47673..f420523 100644 --- a/fsutil/filesystem_test.go +++ b/fsutil/filesystem_test.go @@ -7,6 +7,8 @@ import ( ) func TestSanitizeExtractPath(t *testing.T) { + t.Parallel() + var tests = []struct { filepath string destination string diff --git a/health/health_test.go b/health/health_test.go index 490a12a..369c9f6 100644 --- a/health/health_test.go +++ b/health/health_test.go @@ -12,6 +12,8 @@ import ( ) func TestCheckHealth(t *testing.T) { + t.Parallel() + checkers := map[string]Checker{ "fail": fail{}, "pass": Nop(), @@ -34,6 +36,8 @@ func (c fail) HealthCheck() error { } func TestHealthzHandler(t *testing.T) { + t.Parallel() + logger := log.NewNopLogger() failing := Handler(logger, map[string]Checker{ "mock": healthcheckFunc(func() error { @@ -53,7 +57,10 @@ func TestHealthzHandler(t *testing.T) { {500, failing}, } for _, tt := range httpTests { + tt := tt t.Run("", func(t *testing.T) { + t.Parallel() + rr := httptest.NewRecorder() req := httptest.NewRequest("GET", "/healthz", nil) tt.handler.ServeHTTP(rr, req) diff --git a/httputil/middleware_example_test.go b/httputil/middleware_example_test.go index 9434d70..e903919 100644 --- a/httputil/middleware_example_test.go +++ b/httputil/middleware_example_test.go @@ -16,9 +16,11 @@ func ExampleChain() { srv := httptest.NewServer(h) defer srv.Close() - if _, err := http.Get(srv.URL); err != nil { + resp, err := http.Get(srv.URL) + if err != nil { panic(err) } + defer resp.Body.Close() // Output: // annotate: one diff --git a/logutil/swap_signal.go b/logutil/swap_signal.go index 29e889f..9719084 100644 --- a/logutil/swap_signal.go +++ b/logutil/swap_signal.go @@ -1,3 +1,4 @@ +//go:build !windows // +build !windows package logutil diff --git a/logutil/swap_signal_windows.go b/logutil/swap_signal_windows.go index b5e7195..8a599be 100644 --- a/logutil/swap_signal_windows.go +++ b/logutil/swap_signal_windows.go @@ -1,3 +1,4 @@ +//go:build windows // +build windows package logutil diff --git a/munemo/munemo_test.go b/munemo/munemo_test.go index 3ca4fc4..2342f49 100644 --- a/munemo/munemo_test.go +++ b/munemo/munemo_test.go @@ -67,16 +67,21 @@ func TestMunemoOriginal(t *testing.T) { func testMunemo(t *testing.T, mg *munemoGenerator, tests []testCase) { for _, tt := range tests { + tt := tt if tt.e == "" { // If we lack an error, this is a legit conversion. Try both ways if !tt.skipInt { t.Run(fmt.Sprintf("string/%d", tt.i), func(t *testing.T) { + t.Parallel() + ret := mg.String(tt.i) require.Equal(t, tt.s, ret) }) } t.Run(fmt.Sprintf("int/%s", tt.s), func(t *testing.T) { + t.Parallel() + ret, err := mg.Int(tt.s) assert.Equal(t, tt.i, ret) assert.NoError(t, err) @@ -84,6 +89,8 @@ func testMunemo(t *testing.T, mg *munemoGenerator, tests []testCase) { } else { // Having an error, means we're looking for an error t.Run(fmt.Sprintf("interr/%s", tt.s), func(t *testing.T) { + t.Parallel() + ret, err := mg.Int(tt.s) require.Equal(t, tt.i, ret) require.EqualError(t, err, tt.e) @@ -98,16 +105,21 @@ func TestLegacyInterfaces(t *testing.T) { t.Parallel() for _, tt := range originalTests { + tt := tt if tt.e == "" { // If we lack an error, this is a legit conversion. Try both ways if !tt.skipInt { t.Run(fmt.Sprintf("Munemo/%d", tt.i), func(t *testing.T) { + t.Parallel() + ret := Munemo(tt.i) require.Equal(t, tt.s, ret) }) } t.Run(fmt.Sprintf("UnMunemo/%s", tt.s), func(t *testing.T) { + t.Parallel() + ret, err := UnMunemo(tt.s) assert.Equal(t, tt.i, ret) assert.NoError(t, err) @@ -115,6 +127,8 @@ func TestLegacyInterfaces(t *testing.T) { } else { // Having an error, means we're looking for an error t.Run(fmt.Sprintf("UnMunemo/%s", tt.s), func(t *testing.T) { + t.Parallel() + ret, err := UnMunemo(tt.s) require.Equal(t, tt.i, ret) require.EqualError(t, err, tt.e) diff --git a/pgutil/pgutil_test.go b/pgutil/pgutil_test.go index 7258911..f457e56 100644 --- a/pgutil/pgutil_test.go +++ b/pgutil/pgutil_test.go @@ -36,7 +36,10 @@ func TestConversion(t *testing.T) { } for _, tt := range tests { + tt := tt t.Run("", func(t *testing.T) { + t.Parallel() + c, err := NewFromURL(tt.in, tt.opts...) if tt.err { require.Error(t, err) diff --git a/testutil/testutil_test.go b/testutil/testutil_test.go index 53b0fdd..2cd2633 100644 --- a/testutil/testutil_test.go +++ b/testutil/testutil_test.go @@ -7,6 +7,8 @@ import ( ) func TestErrorAfterSuccess(t *testing.T) { + t.Parallel() + var wg sync.WaitGroup wg.Add(1) go func() { @@ -18,6 +20,8 @@ func TestErrorAfterSuccess(t *testing.T) { } func TestErrorAfterError(t *testing.T) { + t.Parallel() + var wg sync.WaitGroup wg.Add(1) go func() { @@ -30,6 +34,8 @@ func TestErrorAfterError(t *testing.T) { } func TestErrorAfterFuncSuccess(t *testing.T) { + t.Parallel() + err := ErrorAfterFunc(100*time.Millisecond, func() { time.Sleep(1 * time.Millisecond) }) @@ -39,6 +45,8 @@ func TestErrorAfterFuncSuccess(t *testing.T) { } func TestErrorAfterFuncError(t *testing.T) { + t.Parallel() + err := ErrorAfterFunc(1*time.Millisecond, func() { time.Sleep(100 * time.Millisecond) }) @@ -69,6 +77,8 @@ func (m *mockFatal) Fatalf(string, ...interface{}) { } func TestFatalAfterFuncSuccess(t *testing.T) { + t.Parallel() + var m mockFatal // Should not fatal @@ -84,6 +94,8 @@ func TestFatalAfterFuncSuccess(t *testing.T) { } func TestFatalAfterFuncFatal(t *testing.T) { + t.Parallel() + var m mockFatal // Should fatal @@ -115,6 +127,8 @@ func ExampleFatalAfterFunc_fatal() { } func TestFatalAfterSuccess(t *testing.T) { + t.Parallel() + var wg sync.WaitGroup wg.Add(1) go func() { @@ -132,6 +146,8 @@ func TestFatalAfterSuccess(t *testing.T) { } func TestFatalAfterFatal(t *testing.T) { + t.Parallel() + var wg sync.WaitGroup wg.Add(1) go func() { diff --git a/tlsutil/tlsutil_test.go b/tlsutil/tlsutil_test.go index 57cdd5f..203cd5f 100644 --- a/tlsutil/tlsutil_test.go +++ b/tlsutil/tlsutil_test.go @@ -6,6 +6,8 @@ import ( ) func TestNewConfig(t *testing.T) { + t.Parallel() + // default, should have Modern compatibility. cfg := NewConfig() if have, want := cfg.MinVersion, uint16(tls.VersionTLS12); have != want { diff --git a/version/version.go b/version/version.go index 21699c5..ba403ea 100644 --- a/version/version.go +++ b/version/version.go @@ -1,22 +1,22 @@ /* - Package version provides utilities for displaying version information about a Go application. +Package version provides utilities for displaying version information about a Go application. - To use this package, a program would set the package variables at build time, using the - -ldflags go build flag. +To use this package, a program would set the package variables at build time, using the +-ldflags go build flag. - Example: - go build -ldflags "-X github.com/kolide/kit/version.version=1.0.0" +Example: - Available values and defaults to use with ldflags: + go build -ldflags "-X github.com/kolide/kit/version.version=1.0.0" - version = "unknown" - branch = "unknown" - revision = "unknown" - goVersion = "unknown" - buildDate = "unknown" - buildUser = "unknown" - appName = "unknown" +Available values and defaults to use with ldflags: + version = "unknown" + branch = "unknown" + revision = "unknown" + goVersion = "unknown" + buildDate = "unknown" + buildUser = "unknown" + appName = "unknown" */ package version diff --git a/version/version_test.go b/version/version_test.go index 0c008b8..048c65b 100644 --- a/version/version_test.go +++ b/version/version_test.go @@ -6,6 +6,8 @@ import ( ) func TestVersion(t *testing.T) { + t.Parallel() + now := time.Now().String() version = "test" buildDate = now