Skip to content

Commit df057a1

Browse files
committed
Add KAL
1 parent 3f159b9 commit df057a1

File tree

3 files changed

+121
-0
lines changed

3 files changed

+121
-0
lines changed

.golangci-kal.yml

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
version: "2"
2+
run:
3+
go: "1.24"
4+
allow-parallel-runners: true
5+
linters:
6+
default: none
7+
enable:
8+
- kubeapilinter # linter for Kube API conventions
9+
settings:
10+
custom:
11+
kubeapilinter:
12+
type: module
13+
description: KAL is the Kube-API-Linter and lints Kube like APIs based on API conventions and best practices.
14+
settings:
15+
linters:
16+
enable:
17+
- "commentstart" # Ensure comments start with the serialized version of the field name.
18+
- "conditions" # Ensure conditions have the correct json tags and markers.
19+
- "duplicatemarkers" # Ensure there are no exact duplicate markers. for types and fields.
20+
- "integers" # Ensure only int32 and int64 are used for integers.
21+
- "jsontags" # Ensure every field has a json tag.
22+
- "maxlength" # Ensure all strings and arrays have maximum lengths/maximum items.
23+
- "nobools" # Bools do not evolve over time, should use enums instead.
24+
- "nofloats" # Ensure floats are not used.
25+
- "nomaps" # Ensure maps are not used.
26+
- "optionalfields" # Ensure that all fields marked as optional adhere to being pointers and
27+
# having the `omitempty` value in their `json` tag where appropriate.
28+
- "optionalorrequired" # Every field should be marked as `+optional` or `+required`.
29+
- "requiredfields" # Required fields should not be pointers, and should not have `omitempty`.
30+
- "ssatags" # Ensure array fields have the appropriate listType markers
31+
- "statusoptional" # Ensure all first children within status should be optional.
32+
- "statussubresource" # All root objects that have a `status` field should have a status subresource.
33+
- "notimestamp" # Prevents usage of 'Timestamp' fields
34+
- "uniquemarkers" # Ensure that types and fields do not contain more than a single definition of a marker that should only be present once.
35+
36+
# Per discussion in July 2024, we are keeping phase fields for now.
37+
# See https://github.com/kubernetes-sigs/cluster-api/pull/10897#discussion_r1685929508
38+
# and https://github.com/kubernetes-sigs/cluster-api/pull/10897#discussion_r1685919394.
39+
# - "nophase" # Phase fields are discouraged by the Kube API conventions, use conditions instead.
40+
41+
# Linters below this line are disabled, pending conversation on how and when to enable them.
42+
disable:
43+
- "*" # We will manually enable new linters after understanding the impact. Disable all by default.
44+
lintersConfig:
45+
conditions:
46+
isFirstField: Warn # Require conditions to be the first field in the status struct.
47+
usePatchStrategy: Forbid # Forbid patchStrategy markers on the Conditions field.
48+
useProtobuf: Forbid # We don't use protobuf, so protobuf tags are not required.
49+
optionalfields:
50+
pointers:
51+
preference: WhenRequired # Always | WhenRequired # Whether to always require pointers, or only when required. Defaults to `Always`.
52+
policy: SuggestFix # SuggestFix | Warn # The policy for pointers in optional fields. Defaults to `SuggestFix`.
53+
omitempty:
54+
policy: SuggestFix # SuggestFix | Warn | Ignore # The policy for omitempty in optional fields. Defaults to `SuggestFix`.
55+
# jsontags:
56+
# jsonTagRegex: "^[a-z][a-z0-9]*(?:[A-Z][a-z0-9]*)*$" # The default regex is appropriate for our use case.
57+
# optionalorrequired:
58+
# preferredOptionalMarker: optional | kubebuilder:validation:Optional # The preferred optional marker to use, fixes will suggest to use this marker. Defaults to `optional`.
59+
# preferredRequiredMarker: required | kubebuilder:validation:Required # The preferred required marker to use, fixes will suggest to use this marker. Defaults to `required`.
60+
# requiredfields:
61+
# pointerPolicy: Warn | SuggestFix # Defaults to `SuggestFix`. We want our required fields to not be pointers.
62+
# ssatags:
63+
# listTypeSetUsage: Warn | Ignore # The policy for listType=set usage on object arrays. Defaults to `Warn`.
64+
65+
exclusions:
66+
generated: strict
67+
paths:
68+
- zz_generated.*\.go$
69+
- vendored_openapi\.go$
70+
# We don't want to invest time to fix new linter findings in old API types.
71+
- ".*_test.go" # Exclude test files.
72+
rules:
73+
## KAL should only run on API folders.
74+
- path-except: "apis/vmware/v1beta1//*"
75+
linters:
76+
- kubeapilinter
77+
78+
## Excludes for current apiVersions that can be removed once v1beta1 is removed.
79+
# .status.deprecated.v1beta1.conditions fields are using v1beta1.Condition types.
80+
- path: "apis/vmware/v1beta1"
81+
text: "Conditions field must be a slice of metav1.Condition"
82+
linters:
83+
- kubeapilinter
84+
- path: "apis/vmware/v1beta1"
85+
text: "ssatags: Conditions should have a listType marker for proper Server-Side Apply behavior"
86+
linters:
87+
- kubeapilinter
88+
89+
## Removal of bool fields of existing types requires further discussion
90+
- path: "apis/vmware/v1beta1"
91+
text: "nobools"
92+
linters:
93+
- kubeapilinter
94+
95+
issues:
96+
max-same-issues: 0
97+
max-issues-per-linter: 0
98+
new-from-merge-base: main
99+
#new-from-rev: 2b8b70e3

Makefile

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,10 @@ GOLANGCI_LINT_VER := $(shell cat .github/workflows/pr-golangci-lint.yaml | grep
170170
GOLANGCI_LINT := $(abspath $(TOOLS_BIN_DIR)/$(GOLANGCI_LINT_BIN)-$(GOLANGCI_LINT_VER))
171171
GOLANGCI_LINT_PKG := github.com/golangci/golangci-lint/v2/cmd/golangci-lint
172172

173+
GOLANGCI_LINT_KAL_BIN := golangci-lint-kube-api-linter
174+
GOLANGCI_LINT_KAL_VER := $(shell cat ./hack/tools/.custom-gcl.yaml | grep version: | sed 's/version: //')
175+
GOLANGCI_LINT_KAL := $(abspath $(TOOLS_BIN_DIR)/$(GOLANGCI_LINT_KAL_BIN))
176+
173177
GOVULNCHECK_BIN := govulncheck
174178
GOVULNCHECK_VER := v1.1.4
175179
GOVULNCHECK := $(abspath $(TOOLS_BIN_DIR)/$(GOVULNCHECK_BIN)-$(GOVULNCHECK_VER))
@@ -475,6 +479,14 @@ lint: $(GOLANGCI_LINT) ## Lint the codebase
475479
lint-fix: $(GOLANGCI_LINT) ## Lint the codebase and run auto-fixers if supported by the linter
476480
GOLANGCI_LINT_EXTRA_ARGS=--fix $(MAKE) lint
477481

482+
.PHONY: lint-api
483+
lint-api: $(GOLANGCI_LINT_KAL)
484+
$(GOLANGCI_LINT_KAL) run -v --config $(ROOT_DIR)/.golangci-kal.yml $(GOLANGCI_LINT_EXTRA_ARGS)
485+
486+
.PHONY: lint-api-fix
487+
lint-api-fix: $(GOLANGCI_LINT_KAL)
488+
GOLANGCI_LINT_EXTRA_ARGS=--fix $(MAKE) lint-api
489+
478490
APIDIFF_OLD_COMMIT ?= $(shell git rev-parse origin/main)
479491

480492
.PHONY: apidiff
@@ -1059,6 +1071,9 @@ $(GINKGO_BIN): $(GINKGO) ## Build a local copy of ginkgo.
10591071
.PHONY: $(GOLANGCI_LINT_BIN)
10601072
$(GOLANGCI_LINT_BIN): $(GOLANGCI_LINT) ## Build a local copy of golangci-lint.
10611073

1074+
$(GOLANGCI_LINT_KAL): $(GOLANGCI_LINT) # Build golangci-lint-kal from custom configuration.
1075+
cd $(TOOLS_DIR); $(GOLANGCI_LINT) custom
1076+
10621077
.PHONY: $(GOVULNCHECK_BIN)
10631078
$(GOVULNCHECK_BIN): $(GOVULNCHECK) ## Build a local copy of govulncheck.
10641079

hack/tools/.custom-gcl.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
version: v2.1.0
2+
name: golangci-lint-kube-api-linter
3+
destination: ./bin
4+
plugins:
5+
- module: 'sigs.k8s.io/kube-api-linter'
6+
path: ../../../kube-api-linter
7+
# using JoelSpeed/required-fields-v2 branch for now

0 commit comments

Comments
 (0)