Skip to content
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
99 changes: 99 additions & 0 deletions .golangci-kal.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
version: "2"
run:
go: "1.24"
allow-parallel-runners: true
linters:
default: none
enable:
- kubeapilinter # linter for Kube API conventions
settings:
custom:
kubeapilinter:
type: module
description: KAL is the Kube-API-Linter and lints Kube like APIs based on API conventions and best practices.
settings:
linters:
enable:
- "commentstart" # Ensure comments start with the serialized version of the field name.
- "conditions" # Ensure conditions have the correct json tags and markers.
- "duplicatemarkers" # Ensure there are no exact duplicate markers. for types and fields.
- "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.
- "nofloats" # Ensure floats are not used.
- "nomaps" # Ensure maps are not used.
- "optionalfields" # Ensure that all fields marked as optional adhere to being pointers and
# having the `omitempty` value in their `json` tag where appropriate.
- "optionalorrequired" # Every field should be marked as `+optional` or `+required`.
- "requiredfields" # Required fields should not be pointers, and should not have `omitempty`.
- "ssatags" # Ensure array fields have the appropriate listType markers
- "statusoptional" # Ensure all first children within status should be optional.
- "statussubresource" # All root objects that have a `status` field should have a status subresource.
- "notimestamp" # Prevents usage of 'Timestamp' fields
- "uniquemarkers" # Ensure that types and fields do not contain more than a single definition of a marker that should only be present once.

# 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.
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 # Forbid patchStrategy markers on the Conditions field.
useProtobuf: Forbid # We don't use protobuf, so protobuf tags are not required.
optionalfields:
pointers:
preference: WhenRequired # Always | WhenRequired # Whether to always require pointers, or only when required. Defaults to `Always`.
policy: SuggestFix # SuggestFix | Warn # The policy for pointers in optional fields. Defaults to `SuggestFix`.
omitempty:
policy: SuggestFix # SuggestFix | Warn | Ignore # The policy for omitempty in optional fields. Defaults to `SuggestFix`.
# 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.
# ssatags:
# listTypeSetUsage: Warn | Ignore # The policy for listType=set usage on object arrays. Defaults to `Warn`.

exclusions:
generated: strict
paths:
- zz_generated.*\.go$
- vendored_openapi\.go$
# We don't want to invest time to fix new linter findings in old API types.
- ".*_test.go" # Exclude test files.
rules:
## KAL should only run on API folders.
- path-except: "apis/vmware/v1beta1//*"
linters:
- kubeapilinter

## Excludes for current apiVersions that can be removed once v1beta1 is removed.
# .status.deprecated.v1beta1.conditions fields are using v1beta1.Condition types.
- path: "apis/vmware/v1beta1"
text: "Conditions field must be a slice of metav1.Condition"
linters:
- kubeapilinter
- path: "apis/vmware/v1beta1"
text: "ssatags: Conditions should have a listType marker for proper Server-Side Apply behavior"
linters:
- kubeapilinter

## Removal of bool fields of existing types requires further discussion
- path: "apis/vmware/v1beta1"
text: "nobools"
linters:
- kubeapilinter

issues:
max-same-issues: 0
max-issues-per-linter: 0
new-from-merge-base: main
#new-from-rev: 2b8b70e3
15 changes: 15 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,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/v2/cmd/golangci-lint

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

GOVULNCHECK_BIN := govulncheck
GOVULNCHECK_VER := v1.1.4
GOVULNCHECK := $(abspath $(TOOLS_BIN_DIR)/$(GOVULNCHECK_BIN)-$(GOVULNCHECK_VER))
Expand Down Expand Up @@ -475,6 +479,14 @@ lint: $(GOLANGCI_LINT) ## Lint the codebase
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

APIDIFF_OLD_COMMIT ?= $(shell git rev-parse origin/main)

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

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

.PHONY: $(GOVULNCHECK_BIN)
$(GOVULNCHECK_BIN): $(GOVULNCHECK) ## Build a local copy of govulncheck.

Expand Down
7 changes: 7 additions & 0 deletions hack/tools/.custom-gcl.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
version: v2.1.0
name: golangci-lint-kube-api-linter
destination: ./bin
plugins:
- module: 'sigs.k8s.io/kube-api-linter'
path: ../../../kube-api-linter
# using JoelSpeed/required-fields-v2 branch for now