Skip to content

Commit 11b2c46

Browse files
Add custom Linter to check 'setupLog.Error(nil, ...)'
New custom linter under hack/ci project was created to allow us to define custom linters for the project
1 parent 3f56eba commit 11b2c46

File tree

7 files changed

+85
-2
lines changed

7 files changed

+85
-2
lines changed

.golangci.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,12 @@ linters-settings:
6767
- pkg: github.com/blang/semver/v4
6868
alias: bsemver
6969

70+
custom:
71+
setuplognilerrorcheck:
72+
path: ./bin/custom-linter
73+
description: Runs the custom linter that checks for 'setupLog.Error(nil, ...)'
74+
required: true
75+
7076
output:
7177
formats:
7278
- format: tab

Makefile

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ help-extended: #HELP Display extended help.
9595
#SECTION Development
9696

9797
.PHONY: lint
98-
lint: $(GOLANGCI_LINT) #HELP Run golangci linter.
98+
lint: custom-linter $(GOLANGCI_LINT) #HELP Run golangci linter.
9999
$(GOLANGCI_LINT) run --build-tags $(GO_BUILD_TAGS) $(GOLANGCI_LINT_ARGS)
100100

101101
.PHONY: tidy
@@ -285,6 +285,11 @@ BINARIES=operator-controller
285285
$(BINARIES):
286286
go build $(GO_BUILD_FLAGS) -tags '$(GO_BUILD_TAGS)' -ldflags '$(GO_BUILD_LDFLAGS)' -gcflags '$(GO_BUILD_GCFLAGS)' -asmflags '$(GO_BUILD_ASMFLAGS)' -o $(BUILDBIN)/$@ ./cmd/$@
287287

288+
.PHONY: custom-linter
289+
custom-linter:
290+
cd ./hack/ci/custom-linters/cmd/ && go build -o ../../../../bin/custom-linter
291+
292+
288293
.PHONY: build-deps
289294
build-deps: manifests generate fmt vet
290295

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ require (
2424
github.com/spf13/pflag v1.0.5
2525
github.com/stretchr/testify v1.10.0
2626
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56
27+
golang.org/x/tools v0.28.0
2728
gopkg.in/yaml.v2 v2.4.0
2829
helm.sh/helm/v3 v3.16.4
2930
k8s.io/api v0.31.4
@@ -230,7 +231,6 @@ require (
230231
golang.org/x/term v0.28.0 // indirect
231232
golang.org/x/text v0.21.0 // indirect
232233
golang.org/x/time v0.5.0 // indirect
233-
golang.org/x/tools v0.28.0 // indirect
234234
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
235235
google.golang.org/genproto v0.0.0-20240311173647-c811ad7063a7 // indirect
236236
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect

hack/ci/custom-linters/cmd/main.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package main
2+
3+
import (
4+
"github.com/github.com/operator-framework/operator-controller/custom-linters/setuplognilerrorcheck"
5+
"golang.org/x/tools/go/analysis"
6+
"golang.org/x/tools/go/analysis/unitchecker"
7+
)
8+
9+
// Define the custom Linters implemented in the project
10+
var customLinters = []*analysis.Analyzer{
11+
setuplognilerrorcheck.SetupLogNilErrorCheck,
12+
}
13+
14+
func main() {
15+
unitchecker.Main(customLinters...)
16+
}

hack/ci/custom-linters/go.mod

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module github.com/github.com/operator-framework/operator-controller/custom-linters
2+
3+
go 1.23.4
4+
5+
require golang.org/x/tools v0.29.0

hack/ci/custom-linters/go.sum

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
2+
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
3+
golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
4+
golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
5+
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
6+
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
7+
golang.org/x/tools v0.29.0 h1:Xx0h3TtM9rzQpQuR4dKLrdglAmCEN5Oi+P74JdhdzXE=
8+
golang.org/x/tools v0.29.0/go.mod h1:KMQVMRsVxU6nHCFXrBPhDB8XncLNLM0lIy/F14RP588=
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package setuplognilerrorcheck
2+
3+
import (
4+
"go/ast"
5+
"golang.org/x/tools/go/analysis"
6+
)
7+
8+
var SetupLogNilErrorCheck = &analysis.Analyzer{
9+
Name: "setuplognilerrorcheck",
10+
Doc: "check for setupLog.Error(nil, ...) calls with nil as the first argument",
11+
Run: runSetupLogNilErrorCheck,
12+
}
13+
14+
func runSetupLogNilErrorCheck(pass *analysis.Pass) (interface{}, error) {
15+
for _, f := range pass.Files {
16+
ast.Inspect(f, func(n ast.Node) bool {
17+
expr, ok := n.(*ast.CallExpr)
18+
if !ok {
19+
return true
20+
}
21+
22+
selectorExpr, ok := expr.Fun.(*ast.SelectorExpr)
23+
if !ok || selectorExpr.Sel.Name != "Error" {
24+
return true
25+
}
26+
27+
i, ok := selectorExpr.X.(*ast.Ident)
28+
if !ok || i.Name != "setupLog" {
29+
return true
30+
}
31+
32+
if len(expr.Args) > 0 {
33+
if arg, ok := expr.Args[0].(*ast.Ident); ok && arg.Name == "nil" {
34+
pass.Reportf(expr.Pos(), "Avoid using 'setupLog.Error(nil, ...)'. Instead, use 'errors.New()' "+
35+
"or 'fmt.Errorf()' to ensure logs are created. Using 'nil' for errors can result in silent "+
36+
"failures, making bugs harder to detect.")
37+
}
38+
}
39+
return true
40+
})
41+
}
42+
return nil, nil
43+
}

0 commit comments

Comments
 (0)