Skip to content

Commit 1b72f1b

Browse files
committed
wip: add kal linter
Signed-off-by: Richard Case <[email protected]>
1 parent 2bf86d4 commit 1b72f1b

File tree

3 files changed

+131
-1
lines changed

3 files changed

+131
-1
lines changed

.golangci-kal.yml

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
run:
2+
timeout: 10m
3+
go: "1.22"
4+
allow-parallel-runners: true
5+
6+
linters:
7+
disable-all: true
8+
enable:
9+
- kal # linter for Kube API conventions
10+
11+
linters-settings:
12+
custom:
13+
kal:
14+
type: "module"
15+
description: KAL is the Kube-API-Linter and lints Kube like APIs based on API conventions and best practices.
16+
settings:
17+
linters:
18+
enable:
19+
#- "commentstart" # Ensure comments start with the serialized version of the field name.
20+
#- "conditions" # Ensure conditions have the correct json tags and markers.
21+
#- "integers" # Ensure only int32 and int64 are used for integers.
22+
#- "jsontags" # Ensure every field has a json tag.
23+
#- "maxlength" # Ensure all strings and arrays have maximum lengths/maximum items.
24+
#- "nobools" # Bools do not evolve over time, should use enums instead.
25+
- "nofloats" # Ensure floats are not used.
26+
#- "optionalorrequired" # Every field should be marked as `+optional` or `+required`.
27+
# - "requiredfields" # Required fields should not be pointers, and should not have `omitempty`.
28+
- "statussubresource" # All root objects that have a `status` field should have a status subresource.
29+
30+
# Linters below this line are disabled, pending conversation on how and when to enable them.
31+
disable:
32+
- "*" # We will manually enable new linters after understanding the impact. Disable all by default.
33+
lintersConfig:
34+
conditions:
35+
isFirstField: Warn # Require conditions to be the first field in the status struct.
36+
usePatchStrategy: Forbid # Conditions should not use the patch strategy on CRDs.
37+
useProtobuf: Forbid # We don't use protobuf, so protobuf tags are not required.
38+
# jsonTags:
39+
# jsonTagRegex: "^[a-z][a-z0-9]*(?:[A-Z][a-z0-9]*)*$" # The default regex is appropriate for our use case.
40+
# optionalOrRequired:
41+
# preferredOptionalMarker: optional | kubebuilder:validation:Optional # The preferred optional marker to use, fixes will suggest to use this marker. Defaults to `optional`.
42+
# preferredRequiredMarker: required | kubebuilder:validation:Required # The preferred required marker to use, fixes will suggest to use this marker. Defaults to `required`.
43+
# requiredFields:
44+
# pointerPolicy: Warn | SuggestFix # Defaults to `SuggestFix`. We want our required fields to not be pointers.
45+
46+
issues:
47+
exclude-files:
48+
- "zz_generated.*\\.go$"
49+
- "vendored_openapi\\.go$"
50+
# We don't want to invest time to fix new linter findings in old API types.
51+
- "internal/apis/.*"
52+
- ".*_test.go" # Exclude test files.
53+
max-same-issues: 0
54+
max-issues-per-linter: 0
55+
exclude-rules:
56+
# KAL should only run on API folders.
57+
- path-except: "api//*"
58+
linters:
59+
- kal
60+
- path: "api/v1beta1/*|api/v1alpha1/*"
61+
text: "Conditions field must be a slice of metav1.Condition"
62+
linters:
63+
- kal
64+
- path: "api/v1beta1/*"
65+
text: "type ClusterIPFamily should not use an int, int8 or int16. Use int32 or int64 depending on bounding requirements"
66+
linters:
67+
- kal
68+
- path: "exp/ipam/api/v1alpha1/*|exp/ipam/api/v1beta1/*"
69+
text: "field Prefix should not use an int, int8 or int16. Use int32 or int64 depending on bounding requirements"
70+
linters:
71+
- kal
72+
# clusterctl and Runtime Hooks can be fixed once we bump their apiVersion.
73+
- path: "cmd/clusterctl/api/v1alpha3|exp/runtime/hooks/api/v1alpha1"
74+
text: "maxlength"
75+
linters:
76+
- kal
77+
# controller-gen does not allow to add MaxItems to Schemaless fields
78+
- path: "api/v1beta1/*"
79+
text: "maxlength: field (AllOf|OneOf|AnyOf) must have a maximum items, add kubebuilder:validation:MaxItems marker"
80+
linters:
81+
- kal
82+
# It does not make sense to add a maxItems marker on the *List structs as they are not used to generate CRD YAMLs.
83+
# This exclude will be removed once https://github.com/JoelSpeed/kal/issues/38 is resolved.
84+
- path: "api/v1beta1/*|api/v1alpha1/*"
85+
text: "maxlength: field Items must have a maximum items, add kubebuilder:validation:MaxItems marker"
86+
linters:
87+
- kal
88+
- path: "api/v1alpha1/*|api/v1beta1/*"
89+
text: "nobools"
90+
linters:
91+
- kal
92+
# We follow the current CustomResourceDefinition field's json tag pattern.
93+
- path: "api/v1beta1/*"
94+
text: "field (XPreserveUnknownFields|XPreserveUnknownFields|XValidations|XMetadata|XIntOrString) json tag does not match pattern"
95+
linters:
96+
- kal
97+
# The following rules are disabled until we migrate to the new API.
98+
- path: "bootstrap/kubeadm/api/v1beta1/kubeadm_types.go"
99+
text: "field Token is marked as required, should not be a pointer"
100+
linters:
101+
- kal
102+
- path: "api/v1beta1/clusterclass_types.go"
103+
text: "field Ref is marked as required, should not be a pointer"
104+
linters:
105+
- kal
106+
- path: "api/v1alpha1/*|api/v1beta1/*|api/v1alpha3/*"
107+
text: "field Items must be marked as optional or required"
108+
linters:
109+
- kal

Makefile

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ GOLANGCI_LINT_BIN := golangci-lint
6464
GOLANGCI_LINT_VER := $(shell cat .github/workflows/pr-golangci-lint.yaml | grep [[:space:]]version: | sed 's/.*version: //')
6565
GOLANGCI_LINT := $(abspath $(TOOLS_BIN_DIR)/$(GOLANGCI_LINT_BIN)-$(GOLANGCI_LINT_VER))
6666
GOLANGCI_LINT_PKG := github.com/golangci/golangci-lint/cmd/golangci-lint
67+
GOLANGCI_LINT_KAL_BIN := golangci-lint-kal
68+
GOLANGCI_LINT_KAL_VER := $(shell cat ./hack/tools/.custom-gcl.yaml | grep name: | sed 's/name: golangci-lint-kal-//')
69+
GOLANGCI_LINT_KAL := $(abspath $(TOOLS_BIN_DIR)/$(GOLANGCI_LINT_KAL_BIN)-$(GOLANGCI_LINT_KAL_VER))
6770
KIND := $(TOOLS_BIN_DIR)/kind
6871
KUSTOMIZE := $(TOOLS_BIN_DIR)/kustomize
6972
MOCKGEN := $(TOOLS_BIN_DIR)/mockgen
@@ -295,14 +298,26 @@ generate-go-apis: ## Alias for .build/generate-go-apis
295298
$(GOLANGCI_LINT): # Build golangci-lint from tools folder.
296299
GOBIN=$(abspath $(TOOLS_BIN_DIR)) $(GO_INSTALL) $(GOLANGCI_LINT_PKG) $(GOLANGCI_LINT_BIN) $(GOLANGCI_LINT_VER)
297300

301+
$(GOLANGCI_LINT_KAL): $(GOLANGCI_LINT) # Build golangci-lint-kal from custom configuration.
302+
cd $(TOOLS_DIR); $(GOLANGCI_LINT) custom
303+
298304
.PHONY: lint
299-
lint: $(GOLANGCI_LINT) ## Lint codebase
305+
lint: $(GOLANGCI_LINT) $(GOLANGCI_LINT_KAL) ## Lint codebase
300306
$(GOLANGCI_LINT) run -v --fast=false $(GOLANGCI_LINT_EXTRA_ARGS)
307+
$(GOLANGCI_LINT_KAL) run -v --config $(REPO_ROOT)/.golangci-kal.yml $(GOLANGCI_LINT_EXTRA_ARGS)
301308

302309
.PHONY: lint-fix
303310
lint-fix: $(GOLANGCI_LINT) ## Lint the codebase and run auto-fixers if supported by the linter
304311
GOLANGCI_LINT_EXTRA_ARGS=--fix $(MAKE) lint
305312

313+
.PHONY: lint-api
314+
lint-api: $(GOLANGCI_LINT_KAL)
315+
$(GOLANGCI_LINT_KAL) run -v --config $(REPO_ROOT)/.golangci-kal.yml $(GOLANGCI_LINT_EXTRA_ARGS)
316+
317+
.PHONY: lint-api-fix
318+
lint-api-fix: $(GOLANGCI_LINT_KAL)
319+
GOLANGCI_LINT_EXTRA_ARGS=--fix $(MAKE) lint-api
320+
306321
modules: ## Runs go mod to ensure proper vendoring.
307322
go mod tidy
308323
cd $(TOOLS_DIR); go mod tidy

hack/tools/.custom-gcl.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
version: v1.63.4
2+
name: golangci-lint-kal-v1.63.4
3+
destination: ./bin
4+
plugins:
5+
- module: "github.com/JoelSpeed/kal"
6+
version: v0.0.0-20250305092907-abd233a9fed8

0 commit comments

Comments
 (0)