Skip to content

Commit f45dfa7

Browse files
committed
Make code more lint-proof
1 parent 34e3772 commit f45dfa7

File tree

11 files changed

+228
-151
lines changed

11 files changed

+228
-151
lines changed

.github/dependabot.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
version: 2
22
updates:
3-
- package-ecosystem: gomod
4-
directory: "/"
5-
schedule:
6-
interval: daily
7-
time: "04:00"
8-
open-pull-requests-limit: 10
3+
- package-ecosystem: gomod
4+
directory: "/"
5+
schedule:
6+
interval: daily
7+
time: "04:00"
8+
open-pull-requests-limit: 10

.github/workflows/workflow.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
strategy:
2424
fail-fast: false
2525
matrix:
26-
go-version: ['1.20', '1.21', '1.22', '1.23', '1.24']
26+
go-version: ["1.20", "1.21", "1.22", "1.23", "1.24"]
2727
os: [ubuntu-latest, macos-latest, windows-latest]
2828
env:
2929
OS: ${{ matrix.os }}

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,6 @@ Gopkg.lock
1919

2020
# cover
2121
coverage.txt
22+
23+
# added by lint-install
24+
out/

Makefile

Lines changed: 62 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,75 @@
1-
SOURCE_FILES?=$$(go list ./... | grep -v /vendor/)
2-
TEST_PATTERN?=.
3-
TEST_OPTIONS?=
4-
VERSION?=$$(cat VERSION)
5-
LINTER?=$$(which golangci-lint)
6-
LINTER_VERSION=1.50.0
7-
8-
ifeq ($(OS),Windows_NT)
9-
LINTER_FILE=golangci-lint-$(LINTER_VERSION)-windows-amd64.zip
10-
LINTER_UNPACK= >| app.zip; unzip -j app.zip -d $$GOPATH/bin; rm app.zip
11-
else ifeq ($(OS), Darwin)
12-
LINTER_FILE=golangci-lint-$(LINTER_VERSION)-darwin-amd64.tar.gz
13-
LINTER_UNPACK= | tar xzf - -C $$GOPATH/bin --wildcards --strip 1 "**/golangci-lint"
14-
else
15-
LINTER_FILE=golangci-lint-$(LINTER_VERSION)-linux-amd64.tar.gz
16-
LINTER_UNPACK= | tar xzf - -C $$GOPATH/bin --wildcards --strip 1 "**/golangci-lint"
17-
endif
18-
19-
setup:
20-
go install github.com/pierrre/gotestcover@latest
21-
go install golang.org/x/tools/cmd/cover@latest
22-
go mod download
23-
24-
test: test_and_cover_report lint
25-
26-
test_and_cover_report:
27-
gotestcover $(TEST_OPTIONS) -covermode=atomic -coverprofile=coverage.txt $(SOURCE_FILES) -run $(TEST_PATTERN) -timeout=2m
28-
291
cover: test ## Run all the tests and opens the coverage report
302
go tool cover -html=coverage.txt
313

4+
test:
5+
go test ./...
6+
327
fmt: ## gofmt and goimports all go files
338
find . -name '*.go' -not -wholename './vendor/*' | while read -r file; do gofmt -w -s "$$file"; goimports -w "$$file"; done
349

35-
lint: ## Run all the linters
36-
@if [ "$(LINTER)" = "" ]; then\
37-
curl -L https://github.com/golangci/golangci-lint/releases/download/v$(LINTER_VERSION)/$(LINTER_FILE) $(LINTER_UNPACK) ;\
38-
chmod +x $$GOPATH/bin/golangci-lint;\
39-
fi
40-
41-
golangci-lint run
42-
43-
ci: test_and_cover_report ## Run all the tests but no linters - use https://golangci.com integration instead
44-
4510
build:
4611
go build
4712

48-
release: ## Release new version
49-
git tag | grep -q $(VERSION) && echo This version was released! Increase VERSION! || git tag $(VERSION) && git push origin $(VERSION) && git tag v$(VERSION) && git push origin v$(VERSION)
50-
51-
# Absolutely awesome: http://marmelab.com/blog/2016/02/29/auto-documented-makefile.html
5213
help:
5314
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
5415

5516
.DEFAULT_GOAL := build
17+
18+
# BEGIN: lint-install .
19+
# http://github.com/codeGROOVE-dev/lint-install
20+
21+
.PHONY: lint
22+
lint: _lint
23+
24+
LINT_ARCH := $(shell uname -m)
25+
LINT_OS := $(shell uname)
26+
LINT_OS_LOWER := $(shell echo $(LINT_OS) | tr '[:upper:]' '[:lower:]')
27+
LINT_ROOT := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
28+
29+
# shellcheck and hadolint lack arm64 native binaries: rely on x86-64 emulation
30+
ifeq ($(LINT_OS),Darwin)
31+
ifeq ($(LINT_ARCH),arm64)
32+
LINT_ARCH=x86_64
33+
endif
34+
endif
35+
36+
LINTERS :=
37+
FIXERS :=
38+
39+
GOLANGCI_LINT_CONFIG := $(LINT_ROOT)/.golangci.yml
40+
GOLANGCI_LINT_VERSION ?= v2.3.0
41+
GOLANGCI_LINT_BIN := $(LINT_ROOT)/out/linters/golangci-lint-$(GOLANGCI_LINT_VERSION)-$(LINT_ARCH)
42+
$(GOLANGCI_LINT_BIN):
43+
mkdir -p $(LINT_ROOT)/out/linters
44+
rm -rf $(LINT_ROOT)/out/linters/golangci-lint-*
45+
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(LINT_ROOT)/out/linters $(GOLANGCI_LINT_VERSION)
46+
mv $(LINT_ROOT)/out/linters/golangci-lint $@
47+
48+
LINTERS += golangci-lint-lint
49+
golangci-lint-lint: $(GOLANGCI_LINT_BIN)
50+
find . -name go.mod -execdir "$(GOLANGCI_LINT_BIN)" run -c "$(GOLANGCI_LINT_CONFIG)" \;
51+
52+
FIXERS += golangci-lint-fix
53+
golangci-lint-fix: $(GOLANGCI_LINT_BIN)
54+
find . -name go.mod -execdir "$(GOLANGCI_LINT_BIN)" run -c "$(GOLANGCI_LINT_CONFIG)" --fix \;
55+
56+
YAMLLINT_VERSION ?= 1.37.1
57+
YAMLLINT_ROOT := $(LINT_ROOT)/out/linters/yamllint-$(YAMLLINT_VERSION)
58+
YAMLLINT_BIN := $(YAMLLINT_ROOT)/dist/bin/yamllint
59+
$(YAMLLINT_BIN):
60+
mkdir -p $(LINT_ROOT)/out/linters
61+
rm -rf $(LINT_ROOT)/out/linters/yamllint-*
62+
curl -sSfL https://github.com/adrienverge/yamllint/archive/refs/tags/v$(YAMLLINT_VERSION).tar.gz | tar -C $(LINT_ROOT)/out/linters -zxf -
63+
cd $(YAMLLINT_ROOT) && pip3 install --target dist . || pip install --target dist .
64+
65+
LINTERS += yamllint-lint
66+
yamllint-lint: $(YAMLLINT_BIN)
67+
PYTHONPATH=$(YAMLLINT_ROOT)/dist $(YAMLLINT_ROOT)/dist/bin/yamllint .
68+
69+
.PHONY: _lint $(LINTERS)
70+
_lint: $(LINTERS)
71+
72+
.PHONY: fix $(FIXERS)
73+
fix: $(FIXERS)
74+
75+
# END: lint-install .

examples/custom_retry_function_test.go

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
package retry_test
22

33
import (
4+
"errors"
45
"fmt"
5-
"io/ioutil"
6+
"io"
67
"net/http"
78
"net/http/httptest"
89
"strconv"
@@ -34,12 +35,12 @@ func TestCustomRetryFunction(t *testing.T) {
3435
// HTTP 429 status code with Retry-After header in seconds
3536
w.Header().Add("Retry-After", "1")
3637
w.WriteHeader(http.StatusTooManyRequests)
37-
w.Write([]byte("Server limit reached"))
38+
_, _ = w.Write([]byte("Server limit reached"))
3839
attempts--
3940
return
4041
}
4142
w.WriteHeader(http.StatusOK)
42-
w.Write([]byte("hello"))
43+
_, _ = w.Write([]byte("hello"))
4344
}))
4445
defer ts.Close()
4546

@@ -55,8 +56,8 @@ func TestCustomRetryFunction(t *testing.T) {
5556
panic(err)
5657
}
5758
}()
58-
body, err = ioutil.ReadAll(resp.Body)
59-
if resp.StatusCode != 200 {
59+
body, err = io.ReadAll(resp.Body)
60+
if resp.StatusCode != http.StatusOK {
6061
err = fmt.Errorf("HTTP %d: %s", resp.StatusCode, string(body))
6162
if resp.StatusCode == http.StatusTooManyRequests {
6263
// check Retry-After header if it contains seconds to wait for the next retry
@@ -79,17 +80,18 @@ func TestCustomRetryFunction(t *testing.T) {
7980
return err
8081
},
8182
retry.DelayType(func(n uint, err error, config *retry.Config) time.Duration {
82-
fmt.Println("Server fails with: " + err.Error())
83-
if retriable, ok := err.(*RetriableError); ok {
84-
fmt.Printf("Client follows server recommendation to retry after %v\n", retriable.RetryAfter)
83+
// Server fails with: <error message>
84+
var retriable *RetriableError
85+
if errors.As(err, &retriable) {
86+
// Client follows server recommendation to retry after retriable.RetryAfter
8587
return retriable.RetryAfter
8688
}
8789
// apply a default exponential back off strategy
8890
return retry.BackOffDelay(n, err, config)
8991
}),
9092
)
9193

92-
fmt.Println("Server responds with: " + string(body))
94+
// Server responds with: <body content>
9395
if err != nil {
9496
t.Fatalf("unexpected error: %v", err)
9597
}

examples/delay_based_on_error_test.go

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
package retry_test
44

55
import (
6+
"errors"
67
"fmt"
7-
"io/ioutil"
8+
"io"
89
"net/http"
910
"net/http/httptest"
1011
"testing"
@@ -37,7 +38,7 @@ func (err SomeOtherError) Error() string {
3738

3839
func TestCustomRetryFunctionBasedOnKindOfError(t *testing.T) {
3940
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
40-
fmt.Fprintln(w, "hello")
41+
_, _ = fmt.Fprintln(w, "hello")
4142
}))
4243
defer ts.Close()
4344

@@ -53,19 +54,21 @@ func TestCustomRetryFunctionBasedOnKindOfError(t *testing.T) {
5354
panic(err)
5455
}
5556
}()
56-
body, err = ioutil.ReadAll(resp.Body)
57+
body, err = io.ReadAll(resp.Body)
5758
}
5859

5960
return err
6061
},
6162
retry.DelayType(func(n uint, err error, config *retry.Config) time.Duration {
62-
switch e := err.(type) {
63-
case RetryAfterError:
64-
if t, err := parseRetryAfter(e.response.Header.Get("Retry-After")); err == nil {
63+
var retryAfterErr RetryAfterError
64+
if errors.As(err, &retryAfterErr) {
65+
if t, err := parseRetryAfter(retryAfterErr.response.Header.Get("Retry-After")); err == nil {
6566
return time.Until(t)
6667
}
67-
case SomeOtherError:
68-
return e.retryAfter
68+
}
69+
var someOtherErr SomeOtherError
70+
if errors.As(err, &someOtherErr) {
71+
return someOtherErr.retryAfter
6972
}
7073

7174
// default is backoffdelay
@@ -82,5 +85,5 @@ func TestCustomRetryFunctionBasedOnKindOfError(t *testing.T) {
8285

8386
// use https://github.com/aereal/go-httpretryafter instead
8487
func parseRetryAfter(_ string) (time.Time, error) {
85-
return time.Now().Add(1 * time.Second), nil
88+
return time.Now().Add(1 * time.Second), nil //nolint:unparam // error is always nil for test simplicity
8689
}

examples/errors_history_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ func TestErrorHistory(t *testing.T) {
2929
if err != nil {
3030
return err
3131
}
32-
defer resp.Body.Close()
33-
if resp.StatusCode != 200 {
32+
defer func() { _ = resp.Body.Close() }()
33+
if resp.StatusCode != http.StatusOK {
3434
return fmt.Errorf("failed HTTP - %d", resp.StatusCode)
3535
}
3636
return nil

examples/http_get_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package retry_test
22

33
import (
44
"fmt"
5-
"io/ioutil"
5+
"io"
66
"net/http"
77
"net/http/httptest"
88
"testing"
@@ -12,7 +12,7 @@ import (
1212

1313
func TestGet(t *testing.T) {
1414
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
15-
fmt.Fprintln(w, "hello")
15+
_, _ = fmt.Fprintln(w, "hello")
1616
}))
1717
defer ts.Close()
1818

@@ -28,7 +28,7 @@ func TestGet(t *testing.T) {
2828
panic(err)
2929
}
3030
}()
31-
body, err = ioutil.ReadAll(resp.Body)
31+
body, err = io.ReadAll(resp.Body)
3232
}
3333

3434
return err

0 commit comments

Comments
 (0)