Skip to content

🌱 Add KAL linter for linting API conventions #11733

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/pr-golangci-lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,5 @@ jobs:
version: v1.63.4
args: --out-format=colored-line-number
working-directory: ${{matrix.working-directory}}
- name: Lint API
run: GOLANGCI_LINT_EXTRA_ARGS=--out-format=colored-line-number make lint-api
62 changes: 62 additions & 0 deletions .golangci-kal.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
run:
timeout: 10m
go: "1.23"
allow-parallel-runners: true

linters:
disable-all: true
enable:
- kal # linter for Kube API conventions

linters-settings:
custom:
kal:
type: "module"
description: KAL is the Kube-API-Linter and lints Kube like APIs based on API conventions and best practices.
settings:
linters:
enable:
# Per discussion in July 2024, we are keeping phase fields for now.
# See https://github.com/kubernetes-sigs/cluster-api/pull/10897#discussion_r1685929508
# and https://github.com/kubernetes-sigs/cluster-api/pull/10897#discussion_r1685919394.
# - "nophase" # Phase fields are discouraged by the Kube API conventions, use conditions instead.

# Linters below this line are disabled, pending conversation on how and when to enable them.
# - "conditions" # Ensure conditions have the correct json tags and markers.
# - "commentstart" # Ensure comments start with the serialized version of the field name.
# - "integers" # Ensure only int32 and int64 are used for integers.
# - "jsontags" # Ensure every field has a json tag.
# - "maxlength" # Ensure all strings and arrays have maximum lengths/maximum items.
# - "nobools" # Bools do not evolve over time, should use enums instead.
# - "optionalorrequired" # Every field should be marked as `+optional` or `+required`.
# - "requiredfields" # Required fields should not be pointers, and should not have `omitempty`.
# - "statussubresource" # All root objects that have a `status` field should have a status subresource.
disable:
- "*" # We will manually enable new linters after understanding the impact. Disable all by default.
lintersConfig:
conditions:
isFirstField: Warn # Require conditions to be the first field in the status struct.
usePatchStrategy: Forbid # Conditions should not use the patch strategy on CRDs.
useProtobuf: Forbid # We don't use protobuf, so protobuf tags are not required.
# jsonTags:
# jsonTagRegex: "^[a-z][a-z0-9]*(?:[A-Z][a-z0-9]*)*$" # The default regex is appropriate for our use case.
# optionalOrRequired:
# preferredOptionalMarker: optional | kubebuilder:validation:Optional # The preferred optional marker to use, fixes will suggest to use this marker. Defaults to `optional`.
# preferredRequiredMarker: required | kubebuilder:validation:Required # The preferred required marker to use, fixes will suggest to use this marker. Defaults to `required`.
# requiredFields:
# pointerPolicy: Warn | SuggestFix # Defaults to `SuggestFix`. We want our required fields to not be pointers.

issues:
exclude-files:
- "zz_generated.*\\.go$"
- "vendored_openapi\\.go$"
# We don't want to invest time to fix new linter findings in old API types.
- "internal/apis/.*"
- ".*_test.go" # Exclude test files.
max-same-issues: 0
max-issues-per-linter: 0
exclude-rules:
# KAL should only run on API folders.
- path-except: "api/*"
linters:
- kal
1 change: 1 addition & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ linters-settings:
- name: constant-logical-expr
goconst:
ignore-tests: true

issues:
exclude-files:
- "zz_generated.*\\.go$"
Expand Down
18 changes: 17 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,10 @@ GOLANGCI_LINT_VER := $(shell cat .github/workflows/pr-golangci-lint.yaml | grep
GOLANGCI_LINT := $(abspath $(TOOLS_BIN_DIR)/$(GOLANGCI_LINT_BIN)-$(GOLANGCI_LINT_VER))
GOLANGCI_LINT_PKG := github.com/golangci/golangci-lint/cmd/golangci-lint

GOLANGCI_LINT_KAL_BIN := golangci-lint-kal
GOLANGCI_LINT_KAL_VER := $(shell cat ./hack/tools/.custom-gcl.yaml | grep name: | sed 's/name: golangci-lint-kal-//')
GOLANGCI_LINT_KAL := $(abspath $(TOOLS_BIN_DIR)/$(GOLANGCI_LINT_KAL_BIN)-$(GOLANGCI_LINT_KAL_VER))

GOVULNCHECK_BIN := govulncheck
GOVULNCHECK_VER := v1.1.4
GOVULNCHECK := $(abspath $(TOOLS_BIN_DIR)/$(GOVULNCHECK_BIN)-$(GOVULNCHECK_VER))
Expand Down Expand Up @@ -653,11 +657,12 @@ generate-test-infra-prowjobs: $(PROWJOB_GEN) ## Generates the prowjob configurat
##@ lint and verify:

.PHONY: lint
lint: $(GOLANGCI_LINT) ## Lint the codebase
lint: $(GOLANGCI_LINT) $(GOLANGCI_LINT_KAL) ## Lint the codebase
$(GOLANGCI_LINT) run -v $(GOLANGCI_LINT_EXTRA_ARGS)
cd $(TEST_DIR); $(GOLANGCI_LINT) run --path-prefix $(TEST_DIR) --config $(ROOT_DIR)/.golangci.yml -v $(GOLANGCI_LINT_EXTRA_ARGS)
cd $(TOOLS_DIR); $(GOLANGCI_LINT) run --path-prefix $(TOOLS_DIR) --config $(ROOT_DIR)/.golangci.yml -v $(GOLANGCI_LINT_EXTRA_ARGS)
./scripts/lint-dockerfiles.sh $(HADOLINT_VER) $(HADOLINT_FAILURE_THRESHOLD)
$(GOLANGCI_LINT_KAL) run -v --config $(ROOT_DIR)/.golangci-kal.yml $(GOLANGCI_LINT_EXTRA_ARGS)

.PHONY: lint-dockerfiles
lint-dockerfiles:
Expand All @@ -667,6 +672,14 @@ lint-dockerfiles:
lint-fix: $(GOLANGCI_LINT) ## Lint the codebase and run auto-fixers if supported by the linter
GOLANGCI_LINT_EXTRA_ARGS=--fix $(MAKE) lint

.PHONY: lint-api
lint-api: $(GOLANGCI_LINT_KAL)
$(GOLANGCI_LINT_KAL) run -v --config $(ROOT_DIR)/.golangci-kal.yml $(GOLANGCI_LINT_EXTRA_ARGS)

.PHONY: lint-api-fix
lint-api-fix: $(GOLANGCI_LINT_KAL)
GOLANGCI_LINT_EXTRA_ARGS=--fix $(MAKE) lint-api

.PHONY: tiltfile-fix
tiltfile-fix: ## Format the Tiltfile
TRACE=$(TRACE) ./hack/verify-starlark.sh fix
Expand Down Expand Up @@ -1492,6 +1505,9 @@ $(GINKGO): # Build ginkgo from tools folder.
$(GOLANGCI_LINT): # Build golangci-lint from tools folder.
GOBIN=$(TOOLS_BIN_DIR) $(GO_INSTALL) $(GOLANGCI_LINT_PKG) $(GOLANGCI_LINT_BIN) $(GOLANGCI_LINT_VER)

$(GOLANGCI_LINT_KAL): $(GOLANGCI_LINT) # Build golangci-lint-kal from custom configuration.
cd $(TOOLS_DIR); $(GOLANGCI_LINT) custom

$(GOVULNCHECK): # Build govulncheck.
GOBIN=$(TOOLS_BIN_DIR) $(GO_INSTALL) $(GOVULNCHECK_PKG) $(GOVULNCHECK_BIN) $(GOVULNCHECK_VER)

Expand Down
6 changes: 6 additions & 0 deletions hack/tools/.custom-gcl.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
version: v1.63.4
name: golangci-lint-kal-v1.63.4
destination: ./bin
plugins:
- module: 'github.com/JoelSpeed/kal'
version: v0.0.0-20250208110507-b94e5ede1177