hack/tools/golangci-lint/sorted/README.md
This linter checks if feature gates in Kubernetes code are sorted alphabetically in const and var blocks, as well as in maps.
In Kubernetes, feature gates should be listed in alphabetical, case-sensitive (upper before any lower case character) order to reduce the risk of code conflicts and improve readability. This linter enforces this convention by checking if feature gates are properly sorted in:
const and var blocksThe linter analyzes Go AST to find:
const and var blocks containing feature gate declarationsmap[featuregate.Feature]...)It extracts feature names, preserves associated comments, and checks alphabetical ordering. If not sorted, it reports an error with a detailed diff showing the current order versus the expected order.
const (
FeatureA featuregate.Feature = "FeatureA"
FeatureB featuregate.Feature = "FeatureB"
)
var (
MyFeature featuregate.Feature = "MyFeature"
OtherFeature featuregate.Feature = "OtherFeature"
)
var DefaultFeatureGate = map[featuregate.Feature]featuregate.VersionedSpecs{
FeatureA: {...},
FeatureB: {...},
genericfeatures.APIServerIdentity: {...}, // selector expressions supported
}
Note: The linter only works for grouped declarations (const (...) or var (...)). Individual declarations are not checked:
// These are NOT checked
const FeatureA featuregate.Feature = "FeatureA"
const FeatureB featuregate.Feature = "FeatureB"
cd hack/tools/golangci-lint/sorted
go build -buildmode=plugin -o sorted.so ./plugin/
.golangci.yml configuration:linters:
settings:
custom:
sorted:
path: /path/to/sorted.so
description: Checks if feature gates are sorted alphabetically
original-url: k8s.io/kubernetes/hack/tools/golangci-lint/sorted
settings:
debug: false
files:
- path/to/additional/file.go
cd hack/tools/golangci-lint/sorted
go run main.go path/to/file.go
| Option | Type | Default | Description |
|---|---|---|---|
| debug | bool | false | Enable debug logging |
| files | []string | (see below) | Files to check for feature gate sorting. If specified, only these files will be checked |
# Enable debug mode
linters:
settings:
custom:
sorted:
settings:
debug: true
# Check specific files only
linters:
settings:
custom:
sorted:
settings:
files:
- pkg/features/kube_features.go
- staging/src/k8s.io/apiserver/pkg/features/kube_features.go
When no files configuration is provided, the linter checks these Kubernetes files:
cmd/kubeadm/app/features/features.gopkg/features/kube_features.gostaging/src/k8s.io/apiserver/pkg/features/kube_features.gostaging/src/k8s.io/client-go/features/known_features.gostaging/src/k8s.io/controller-manager/pkg/features/kube_features.gostaging/src/k8s.io/apiextensions-apiserver/pkg/features/kube_features.gotest/e2e/feature/feature.gotest/e2e/environment/environment.go# Run all linters including sorted
golangci-lint run
# Run only sorted
golangci-lint run --enable=sorted --disable-all
# Enable if disabled by default
golangci-lint run -Esorted
Custom linters follow standard golangci-lint rules:
linters.disable-all: true is setlinters.enable: [sorted]golangci-lint run -Esortedconst (
// Comments are preserved
FeatureA featuregate.Feature = "FeatureA"
FeatureB featuregate.Feature = "FeatureB"
FeatureC featuregate.Feature = "FeatureC"
)
var DefaultSpecs = map[featuregate.Feature]featuregate.VersionedSpecs{
FeatureA: {...},
FeatureB: {...},
genericfeatures.APIServerIdentity: {...},
}
const (
FeatureC featuregate.Feature = "FeatureC" // Wrong order
FeatureA featuregate.Feature = "FeatureA"
FeatureB featuregate.Feature = "FeatureB"
)
var DefaultSpecs = map[featuregate.Feature]featuregate.VersionedSpecs{
FeatureB: {...}, // Wrong order
FeatureA: {...},
}
When sorting issues are detected, the linter provides a unified diff:
not sorted alphabetically:
@@ -1,4 +1,4 @@
const (
- FeatureC = value
- FeatureA = value
FeatureB = value
+ FeatureA = value
+ FeatureC = value
)
By default, this linter checks the following files in the Kubernetes codebase:
pkg/features/kube_features.gostaging/src/k8s.io/apiserver/pkg/features/kube_features.gostaging/src/k8s.io/client-go/features/known_features.gostaging/src/k8s.io/controller-manager/pkg/features/kube_features.gostaging/src/k8s.io/apiextensions-apiserver/pkg/features/kube_features.gotest/e2e/feature/feature.gotest/e2e/environment/environment.goThis linter is integrated into the Kubernetes CI pipeline to ensure consistent feature gate ordering across the codebase. Run it locally before submitting pull requests that modify feature gates.
debug: true in your configuration to see processing detailsgo build -buildmode=plugingo run main.go path/to/file.go to test specific filesgo/ast package for parsingpackage.FeatureName)github.com/pmezard/go-difflibFor more information on custom linters in golangci-lint, refer to the official documentation.