Skip to content

Commit 29f8611

Browse files
authored
Merge pull request #34 from henrybear327/feat/add_golangci-lint
Add make verify target for running static analysis checks
2 parents 469f031 + 60f0e89 commit 29f8611

File tree

12 files changed

+170
-25
lines changed

12 files changed

+170
-25
lines changed

.github/workflows/static-analysis.yaml

+19
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,22 @@ jobs:
1414
uses: golangci/golangci-lint-action@v4
1515
with:
1616
version: v1.57.1
17+
args: --config tools/.golangci.yaml
18+
- run: |
19+
set -euo pipefail
20+
21+
make verify
22+
- run: |
23+
set -euo pipefail
24+
25+
make fmt
26+
27+
DIFF=$(git status --porcelain)
28+
29+
if [ -n "$DIFF" ]; then
30+
echo "These files were modified:"
31+
echo
32+
echo "$DIFF"
33+
echo
34+
exit 1
35+
fi

Makefile

+13
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,19 @@ GO_VERSION ?= 1.21.8
1919
GOOS ?= linux
2020
GOARCH ?= amd64
2121
TEMP_DIR := $(shell mktemp -d)
22+
GOFILES = $(shell find . -name \*.go)
23+
24+
.PHONY: fmt
25+
fmt:
26+
@echo "Verifying gofmt, failures can be fixed with ./scripts/fix.sh"
27+
@!(gofmt -l -s -d ${GOFILES} | grep '[a-z]')
28+
29+
@echo "Verifying goimports, failures can be fixed with ./scripts/fix.sh"
30+
@!(go run golang.org/x/tools/cmd/goimports@latest -l -d ${GOFILES} | grep '[a-z]')
31+
32+
.PHONY: verify
33+
verify:
34+
golangci-lint run --config tools/.golangci.yaml ./...
2235

2336
# Local development build
2437
build:

cmd/analyze.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ type analyzeOptions struct {
3636
filename string
3737
}
3838

39-
var analyzeOpts *analyzeOptions = &analyzeOptions{}
39+
var analyzeOpts = &analyzeOptions{}
4040

4141
func init() {
4242
RootCmd.AddCommand(analyzeCmd)
@@ -52,7 +52,7 @@ func analyzeValidateAndRun() error {
5252
objectCounts := map[string]uint{}
5353
for _, s := range summaries {
5454
if s.TypeMeta != nil {
55-
objectCounts[fmt.Sprintf("%s/%s", s.TypeMeta.APIVersion, s.TypeMeta.Kind)] += 1
55+
objectCounts[fmt.Sprintf("%s/%s", s.TypeMeta.APIVersion, s.TypeMeta.Kind)]++
5656
}
5757
}
5858

cmd/checksum.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ type checksumOptions struct {
3636
revision int64
3737
}
3838

39-
var checksumOpts *checksumOptions = &checksumOptions{}
39+
var checksumOpts = &checksumOptions{}
4040

4141
func init() {
4242
RootCmd.AddCommand(checksumCmd)

cmd/decode.go

+3-4
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ type decodeOptions struct {
7373
batchProcess bool // special flag to handle incoming etcd-dump-logs output
7474
}
7575

76-
var options *decodeOptions = &decodeOptions{}
76+
var options = &decodeOptions{}
7777

7878
func init() {
7979
RootCmd.AddCommand(decodeCmd)
@@ -124,7 +124,7 @@ func runInBatchMode(metaOnly bool, outMediaType string, out io.Writer) (err erro
124124
return nil
125125
}
126126
if err != nil {
127-
return fmt.Errorf("error reading --batch-process input: %v\n", err)
127+
return fmt.Errorf("error reading --batch-process input: %v", err)
128128
}
129129

130130
input = stripNewline(input)
@@ -210,7 +210,6 @@ func readInput(inputFilename string) ([]byte, error) {
210210
func stripNewline(d []byte) []byte {
211211
if len(d) > 0 && d[len(d)-1] == '\n' {
212212
return d[:len(d)-1]
213-
} else {
214-
return d
215213
}
214+
return d
216215
}

cmd/encode.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ type encodeOptions struct {
5151
inputFilename string
5252
}
5353

54-
var encodeOpts *encodeOptions = &encodeOptions{}
54+
var encodeOpts = &encodeOptions{}
5555

5656
func init() {
5757
RootCmd.AddCommand(encodeCmd)

cmd/extract.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ type extractOptions struct {
9090
filter string
9191
}
9292

93-
var opts *extractOptions = &extractOptions{}
93+
var opts = &extractOptions{}
9494

9595
func init() {
9696
RootCmd.AddCommand(extractCmd)
@@ -250,7 +250,7 @@ func printLeafItemValue(kv *mvccpb.KeyValue, outMediaType string, out io.Writer)
250250
// printKeySummaries prints all keys in the db file with the given key prefix.
251251
func printKeySummaries(filename string, keyPrefix string, revision int64, fields []string, out io.Writer) error {
252252
if len(fields) == 0 {
253-
return fmt.Errorf("no fields provided, nothing to output.")
253+
return fmt.Errorf("no fields provided, nothing to output")
254254
}
255255

256256
var hasKey bool
@@ -288,7 +288,7 @@ func printTemplateSummaries(filename string, keyPrefix string, revision int64, t
288288
}
289289

290290
if len(templatestr) == 0 {
291-
return fmt.Errorf("no template provided, nothing to output.")
291+
return fmt.Errorf("no template provided, nothing to output")
292292
}
293293

294294
filters := []data.Filter{}

pkg/data/data.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ var (
3737
keyBucket = []byte("key")
3838
metaBucket = []byte("meta")
3939

40-
finishedCompactKeyName = []byte("finishedCompactRev")
40+
finishedCompactKeyName = []byte("finishedCompactRev")
4141
)
4242

4343
// KeySummary represents a kubernetes object stored in etcd.
@@ -272,7 +272,7 @@ func ListKeySummaries(filename string, filters []Filter, proj *KeySummaryProject
272272
ks.Version = kv.ModRevision
273273
ks.Stats.ValueSize = len(kv.Value)
274274
}
275-
ks.Stats.VersionCount += 1
275+
ks.Stats.VersionCount++
276276
ks.Stats.AllVersionsKeySize += len(kv.Key)
277277
ks.Stats.AllVersionsValueSize += len(kv.Value)
278278
}

pkg/data/data_test.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -114,22 +114,22 @@ func TestParseFilters(t *testing.T) {
114114
{
115115
name: "namespace-equals",
116116
rawFilter: ".Value.metadata.namespace=default",
117-
expected: []*FieldConstraint{&FieldConstraint{lhs: ".Value.metadata.namespace", op: Equals, rhs: "default"}},
117+
expected: []*FieldConstraint{{lhs: ".Value.metadata.namespace", op: Equals, rhs: "default"}},
118118
},
119119
{
120120
name: "2-filters",
121121
rawFilter: ".Value.metadata.namespace=default,.Value.metadata.name=example",
122122
expected: []*FieldConstraint{
123-
&FieldConstraint{lhs: ".Value.metadata.namespace", op: Equals, rhs: "default"},
124-
&FieldConstraint{lhs: ".Value.metadata.name", op: Equals, rhs: "example"},
123+
{lhs: ".Value.metadata.namespace", op: Equals, rhs: "default"},
124+
{lhs: ".Value.metadata.name", op: Equals, rhs: "example"},
125125
},
126126
},
127127
{
128128
name: "whitespace",
129129
rawFilter: " .Value.metadata.namespace=default\t, .Value.metadata.name=example\n",
130130
expected: []*FieldConstraint{
131-
&FieldConstraint{lhs: ".Value.metadata.namespace", op: Equals, rhs: "default"},
132-
&FieldConstraint{lhs: ".Value.metadata.name", op: Equals, rhs: "example"},
131+
{lhs: ".Value.metadata.namespace", op: Equals, rhs: "default"},
132+
{lhs: ".Value.metadata.name", op: Equals, rhs: "example"},
133133
},
134134
},
135135
}

pkg/encoding/scheme.go

+8-7
Original file line numberDiff line numberDiff line change
@@ -87,17 +87,18 @@ func init() {
8787
// AddToScheme adds all types of this clientset into the given scheme. This allows composition
8888
// of clientsets, like in:
8989
//
90-
// import (
91-
// "k8s.io/client-go/kubernetes"
92-
// clientsetscheme "k8s.io/client-go/kuberentes/scheme"
93-
// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
94-
// )
90+
// import (
91+
// "k8s.io/client-go/kubernetes"
92+
// clientsetscheme "k8s.io/client-go/kuberentes/scheme"
93+
// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
94+
// )
9595
//
96-
// kclientset, _ := kubernetes.NewForConfig(c)
97-
// aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
96+
// kclientset, _ := kubernetes.NewForConfig(c)
97+
// aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
9898
//
9999
// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
100100
// correctly.
101+
//
101102
//nolint:errcheck
102103
func AddToScheme(scheme *runtime.Scheme) {
103104
admissionv1beta1.AddToScheme(scheme)

scripts/fix.sh

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
GO_CMD="go"
2+
3+
GOFILES=$(${GO_CMD} list --f "{{with \$d:=.}}{{range .GoFiles}}{{\$d.Dir}}/{{.}}{{\"\n\"}}{{end}}{{end}}" ./...)
4+
TESTGOFILES=$(${GO_CMD} list --f "{{with \$d:=.}}{{range .TestGoFiles}}{{\$d.Dir}}/{{.}}{{\"\n\"}}{{end}}{{end}}" ./...)
5+
XTESTGOFILES=$(${GO_CMD} list --f "{{with \$d:=.}}{{range .XTestGoFiles}}{{\$d.Dir}}/{{.}}{{\"\n\"}}{{end}}{{end}}" ./...)
6+
7+
echo "${GOFILES}" "${TESTGOFILES}" "${XTESTGOFILES}"| xargs -n 100 go run golang.org/x/tools/cmd/goimports@latest -w -local go.etcd.io
8+
9+
go fmt ./...
10+
go mod tidy

tools/.golangci.yaml

+103
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
---
2+
run:
3+
timeout: 30m
4+
issues.exclude-files: [^zz_generated.*]
5+
issues:
6+
max-same-issues: 0
7+
# Excluding configuration per-path, per-linter, per-text and per-source
8+
exclude-rules:
9+
# exclude ineffassing linter for generated files for conversion
10+
- path: conversion\.go
11+
linters: [ineffassign]
12+
linters:
13+
disable-all: true
14+
enable: # please keep this alphabetized
15+
# Don't use soon to deprecated[1] linters that lead to false
16+
# https://github.com/golangci/golangci-lint/issues/1841
17+
# - deadcode
18+
# - structcheck
19+
# - varcheck
20+
- goimports
21+
- ineffassign
22+
- nakedret
23+
- revive
24+
- staticcheck
25+
- stylecheck
26+
- unconvert # Remove unnecessary type conversions
27+
- unparam
28+
- unused
29+
linters-settings: # please keep this alphabetized
30+
goimports:
31+
local-prefixes: go.etcd.io # Put imports beginning with prefix after 3rd-party packages.
32+
nakedret:
33+
# Align with https://github.com/alexkohler/nakedret/blob/v1.0.2/cmd/nakedret/main.go#L10
34+
max-func-lines: 5
35+
revive:
36+
ignore-generated-header: false
37+
severity: error
38+
confidence: 0.8
39+
enable-all-rules: false
40+
rules:
41+
- name: blank-imports
42+
severity: error
43+
disabled: false
44+
- name: context-as-argument
45+
severity: error
46+
disabled: false
47+
- name: dot-imports
48+
severity: error
49+
disabled: false
50+
- name: error-return
51+
severity: error
52+
disabled: false
53+
- name: error-naming
54+
severity: error
55+
disabled: false
56+
- name: if-return
57+
severity: error
58+
disabled: false
59+
- name: increment-decrement
60+
severity: error
61+
disabled: false
62+
- name: var-declaration
63+
severity: error
64+
disabled: false
65+
- name: package-comments
66+
severity: error
67+
disabled: false
68+
- name: range
69+
severity: error
70+
disabled: false
71+
- name: receiver-naming
72+
severity: error
73+
disabled: false
74+
- name: time-naming
75+
severity: error
76+
disabled: false
77+
- name: indent-error-flow
78+
severity: error
79+
disabled: false
80+
- name: errorf
81+
severity: error
82+
disabled: false
83+
- name: context-keys-type
84+
severity: error
85+
disabled: false
86+
- name: error-strings
87+
severity: error
88+
disabled: false
89+
# TODO: enable the following rules
90+
- name: var-naming
91+
disabled: true
92+
- name: exported
93+
disabled: true
94+
- name: unexported-return
95+
disabled: true
96+
staticcheck:
97+
checks:
98+
- all
99+
- -SA1019 # TODO(fix) Using a deprecated function, variable, constant or field
100+
- -SA2002 # TODO(fix) Called testing.T.FailNow or SkipNow in a goroutine, which isn’t allowed
101+
stylecheck:
102+
checks:
103+
- ST1019 # Importing the same package multiple times.

0 commit comments

Comments
 (0)