Skip to content

:WIP sparkles: Add KAL and fix missing parts from tutorials #4888

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

Closed
Closed
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
6 changes: 6 additions & 0 deletions .github/workflows/lint-sample.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ jobs:
- name: Prepare ${{ matrix.folder }}
working-directory: ${{ matrix.folder }}
run: go mod tidy
- name: Build kubeapilinter
working-directory: ${{ matrix.folder }}
run: make kube-api-linter
env:
CGO_ENABLED: 1
- name: Check linter configuration
working-directory: ${{ matrix.folder }}
run: make lint-config
Expand All @@ -41,6 +46,7 @@ jobs:
with:
version: v2.2.2
working-directory: ${{ matrix.folder }}
install-mode: goinstall
- name: Run linter via makefile target
working-directory: ${{ matrix.folder }}
run: make lint
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ jobs:
uses: golangci/golangci-lint-action@v8
with:
version: v2.2.2
install-mode: goinstall
12 changes: 12 additions & 0 deletions docs/book/src/cronjob-tutorial/testdata/project/.golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,20 @@ linters:
- unconvert
- unparam
- unused
- kubeapilinter
settings:
revive:
rules:
- name: comment-spacings
- name: import-shadowing
custom:
kubeapilinter:
path: "./bin/kube-api-linter.so"
description: "Kube API Linter plugin"
original-url: "sigs.k8s.io/kube-api-linter"
settings:
linters: { }
lintersConfig: { }
exclusions:
generated: lax
rules:
Expand All @@ -36,6 +45,9 @@ linters:
- dupl
- lll
path: internal/*
- path-except: "^api/"
linters:
- kubeapilinter
paths:
- third_party$
- builtin$
Expand Down
19 changes: 18 additions & 1 deletion docs/book/src/cronjob-tutorial/testdata/project/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ cleanup-test-e2e: ## Tear down the Kind cluster used for e2e tests
@$(KIND) delete cluster --name $(KIND_CLUSTER)

.PHONY: lint
lint: golangci-lint ## Run golangci-lint linter
lint: golangci-lint kube-api-linter ## Run golangci-lint linter
$(GOLANGCI_LINT) run

.PHONY: lint-fix
Expand Down Expand Up @@ -225,6 +225,23 @@ golangci-lint: $(GOLANGCI_LINT) ## Download golangci-lint locally if necessary.
$(GOLANGCI_LINT): $(LOCALBIN)
$(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/v2/cmd/golangci-lint,$(GOLANGCI_LINT_VERSION))

# To lint Kubernetes API definitions.
# More info: https://github.com/kubernetes-sigs/kube-api-linter
KUBE_API_LINTER_PLUGIN := $(LOCALBIN)/kube-api-linter.so
KUBE_API_LINTER_BUILD_DIR := ./hack/kube-api-linter

.PHONY: kube-api-linter
kube-api-linter: $(KUBE_API_LINTER_PLUGIN) ## Build the kube-api-linter plugin
$(KUBE_API_LINTER_PLUGIN): $(KUBE_API_LINTER_BUILD_DIR)/go.mod
cd $(KUBE_API_LINTER_BUILD_DIR) && \
go build -buildmode=plugin -o "$(abspath $(KUBE_API_LINTER_PLUGIN))" sigs.k8s.io/kube-api-linter/pkg/plugin
$(KUBE_API_LINTER_BUILD_DIR)/go.mod:
@echo "Setting up local module for kube-api-linter plugin..."
mkdir -p $(KUBE_API_LINTER_BUILD_DIR)
cd $(KUBE_API_LINTER_BUILD_DIR) && \
go mod init local-kube-api-linter && \
go get sigs.k8s.io/kube-api-linter@latest
Copy link
Member Author

@camilamacedo86 camilamacedo86 Jun 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@everettraven @JoelSpeed
Do you see a better way to install with Golang CI 2x?

Would it be possible to do a release of the linter like any initial version, such as v0.1.0, and provide its binary so that we can download it here instead to simplify the install?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're currently trying to build this as a plugin, which means you also need to build the golangci-lint binary within the same Go module so that they share dependencies.

I would recommend using the module version of KAL where you compile a complete custom version of golangci-lint with KAL installed. In the future I hope to have a complete CLI released that is a custom version of golangci-lint, I'll see if I can do something about that next week as that might make this easier


# go-install-tool will 'go install' any package with custom target and name of binary, if it doesn't exist
# $1 - target path with name of binary
# $2 - package url which can be installed
Expand Down
18 changes: 17 additions & 1 deletion docs/book/src/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ we will allow configuring the number of instances with the following:
```go
type MemcachedSpec struct {
...
// +kubebuilder:validation:Minimum=0
// +required
Size int32 `json:"size,omitempty"`
}
```
Expand All @@ -97,7 +99,21 @@ similar to how we do with any resource from the Kubernetes API.
```go
// MemcachedStatus defines the observed state of Memcached
type MemcachedStatus struct {
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,1,rep,name=conditions"`
// For Kubernetes API conventions, see:
// https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties

// conditions represent the current state of the {{ .Resource.Kind }} resource.
// Each condition has a unique type and reflects the status of a specific aspect of the resource.
//
// Standard condition types include:
// - "Available": the resource is fully functional.
// - "Progressing": the resource is being created or updated.
// - "Degraded": the resource failed to reach or maintain its desired state.
//
// The status of each condition is one of True, False, or Unknown.
// +listType=map
// +listMapKey=type
Conditions []metav1.Condition `json:"conditions,omitempty"`
}
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ jobs:
uses: golangci/golangci-lint-action@v8
with:
version: v2.2.2
install-mode: goinstall

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this do?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It allow we run the linter as a go Module
Otherwise, the GA will not be able to run it as it is installed

12 changes: 12 additions & 0 deletions docs/book/src/getting-started/testdata/project/.golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,20 @@ linters:
- unconvert
- unparam
- unused
- kubeapilinter
settings:
revive:
rules:
- name: comment-spacings
- name: import-shadowing
custom:
kubeapilinter:
path: "./bin/kube-api-linter.so"
description: "Kube API Linter plugin"
original-url: "sigs.k8s.io/kube-api-linter"
settings:
linters: { }
lintersConfig: { }
Comment on lines +36 to +37

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should discuss sensible defaults to these options for CRDs

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you suggesting that we should not enable all by default?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some linters that are disabled by default because they only make sense for CRDs.

There are some linters where the default config makes sense only for built-ins, and they need specific configuration for CRDs.

This is an ideal place to document what the correct configuration should be for CRDs in general

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are calling only in the api dir, but that is a good call.
People might have more than CRDs, we need to make it very clear.

exclusions:
generated: lax
rules:
Expand All @@ -36,6 +45,9 @@ linters:
- dupl
- lll
path: internal/*
- path-except: "^api/"
linters:
- kubeapilinter
paths:
- third_party$
- builtin$
Expand Down
19 changes: 18 additions & 1 deletion docs/book/src/getting-started/testdata/project/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ cleanup-test-e2e: ## Tear down the Kind cluster used for e2e tests
@$(KIND) delete cluster --name $(KIND_CLUSTER)

.PHONY: lint
lint: golangci-lint ## Run golangci-lint linter
lint: golangci-lint kube-api-linter ## Run golangci-lint linter
$(GOLANGCI_LINT) run

.PHONY: lint-fix
Expand Down Expand Up @@ -221,6 +221,23 @@ golangci-lint: $(GOLANGCI_LINT) ## Download golangci-lint locally if necessary.
$(GOLANGCI_LINT): $(LOCALBIN)
$(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/v2/cmd/golangci-lint,$(GOLANGCI_LINT_VERSION))

# To lint Kubernetes API definitions.
# More info: https://github.com/kubernetes-sigs/kube-api-linter
KUBE_API_LINTER_PLUGIN := $(LOCALBIN)/kube-api-linter.so
KUBE_API_LINTER_BUILD_DIR := ./hack/kube-api-linter

.PHONY: kube-api-linter
kube-api-linter: $(KUBE_API_LINTER_PLUGIN) ## Build the kube-api-linter plugin
$(KUBE_API_LINTER_PLUGIN): $(KUBE_API_LINTER_BUILD_DIR)/go.mod
cd $(KUBE_API_LINTER_BUILD_DIR) && \
go build -buildmode=plugin -o "$(abspath $(KUBE_API_LINTER_PLUGIN))" sigs.k8s.io/kube-api-linter/pkg/plugin
$(KUBE_API_LINTER_BUILD_DIR)/go.mod:
@echo "Setting up local module for kube-api-linter plugin..."
mkdir -p $(KUBE_API_LINTER_BUILD_DIR)
cd $(KUBE_API_LINTER_BUILD_DIR) && \
go mod init local-kube-api-linter && \
go get sigs.k8s.io/kube-api-linter@latest

# go-install-tool will 'go install' any package with custom target and name of binary, if it doesn't exist
# $1 - target path with name of binary
# $2 - package url which can be installed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ jobs:
uses: golangci/golangci-lint-action@v8
with:
version: v2.2.2
install-mode: goinstall
12 changes: 12 additions & 0 deletions docs/book/src/multiversion-tutorial/testdata/project/.golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,20 @@ linters:
- unconvert
- unparam
- unused
- kubeapilinter
settings:
revive:
rules:
- name: comment-spacings
- name: import-shadowing
custom:
kubeapilinter:
path: "./bin/kube-api-linter.so"
description: "Kube API Linter plugin"
original-url: "sigs.k8s.io/kube-api-linter"
settings:
linters: { }
lintersConfig: { }
exclusions:
generated: lax
rules:
Expand All @@ -36,6 +45,9 @@ linters:
- dupl
- lll
path: internal/*
- path-except: "^api/"
linters:
- kubeapilinter
paths:
- third_party$
- builtin$
Expand Down
19 changes: 18 additions & 1 deletion docs/book/src/multiversion-tutorial/testdata/project/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ cleanup-test-e2e: ## Tear down the Kind cluster used for e2e tests
@$(KIND) delete cluster --name $(KIND_CLUSTER)

.PHONY: lint
lint: golangci-lint ## Run golangci-lint linter
lint: golangci-lint kube-api-linter ## Run golangci-lint linter
$(GOLANGCI_LINT) run

.PHONY: lint-fix
Expand Down Expand Up @@ -225,6 +225,23 @@ golangci-lint: $(GOLANGCI_LINT) ## Download golangci-lint locally if necessary.
$(GOLANGCI_LINT): $(LOCALBIN)
$(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/v2/cmd/golangci-lint,$(GOLANGCI_LINT_VERSION))

# To lint Kubernetes API definitions.
# More info: https://github.com/kubernetes-sigs/kube-api-linter
KUBE_API_LINTER_PLUGIN := $(LOCALBIN)/kube-api-linter.so
KUBE_API_LINTER_BUILD_DIR := ./hack/kube-api-linter

.PHONY: kube-api-linter
kube-api-linter: $(KUBE_API_LINTER_PLUGIN) ## Build the kube-api-linter plugin
$(KUBE_API_LINTER_PLUGIN): $(KUBE_API_LINTER_BUILD_DIR)/go.mod
cd $(KUBE_API_LINTER_BUILD_DIR) && \
go build -buildmode=plugin -o "$(abspath $(KUBE_API_LINTER_PLUGIN))" sigs.k8s.io/kube-api-linter/pkg/plugin
$(KUBE_API_LINTER_BUILD_DIR)/go.mod:
@echo "Setting up local module for kube-api-linter plugin..."
mkdir -p $(KUBE_API_LINTER_BUILD_DIR)
cd $(KUBE_API_LINTER_BUILD_DIR) && \
go mod init local-kube-api-linter && \
go get sigs.k8s.io/kube-api-linter@latest
Comment on lines +239 to +243

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this achieve? Why was it needed?

Copy link
Member Author

@camilamacedo86 camilamacedo86 Jun 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added it to allow us to build the linter locally.
I created the module inside the hack dir to not add any dep to the project itself.
But if we have a release, an easier way by like downloading it then we can remove it.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The approach taken for K/K and other repos has generally to have a separate go.mod for tools (new Go tools directives), and then this doesn't add deps to the main go.mod, but does allow all of the tools to built using the same environment.

I need it to have the linter and be able to build it locally in the hack dir, and without adding any dependencies to the project itself.

But you're building it with the first command, so I'm not sure why there's then a second get of the linter after you've already built the plugin?

Could we start to do releases? Would it be possible to provide it so that it can be downloaded instead of building it?

This is on the todo, but has been lower priority, as so far everyone who has used it has largely been ok with the plugin or module way of building things


# go-install-tool will 'go install' any package with custom target and name of binary, if it doesn't exist
# $1 - target path with name of binary
# $2 - package url which can be installed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,5 @@ jobs:
uses: golangci/golangci-lint-action@v8
with:
version: {{ .GolangciLintVersion }}
install-mode: goinstall
`
12 changes: 12 additions & 0 deletions pkg/plugins/golang/v4/scaffolds/internal/templates/golangci.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,20 @@ linters:
- unconvert
- unparam
- unused
- kubeapilinter
settings:
revive:
rules:
- name: comment-spacings
- name: import-shadowing
custom:
kubeapilinter:
path: "./bin/kube-api-linter.so"
description: "Kube API Linter plugin"
original-url: "sigs.k8s.io/kube-api-linter"
settings:
linters: { }
lintersConfig: { }
exclusions:
generated: lax
rules:
Expand All @@ -79,6 +88,9 @@ linters:
- dupl
- lll
path: internal/*
- path-except: "^api/"
linters:
- kubeapilinter
paths:
- third_party$
- builtin$
Expand Down
19 changes: 18 additions & 1 deletion pkg/plugins/golang/v4/scaffolds/internal/templates/makefile.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ cleanup-test-e2e: ## Tear down the Kind cluster used for e2e tests
@$(KIND) delete cluster --name $(KIND_CLUSTER)

.PHONY: lint
lint: golangci-lint ## Run golangci-lint linter
lint: golangci-lint kube-api-linter ## Run golangci-lint linter
$(GOLANGCI_LINT) run

.PHONY: lint-fix
Expand Down Expand Up @@ -300,6 +300,23 @@ golangci-lint: $(GOLANGCI_LINT) ## Download golangci-lint locally if necessary.
$(GOLANGCI_LINT): $(LOCALBIN)
$(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/v2/cmd/golangci-lint,$(GOLANGCI_LINT_VERSION))

# To lint Kubernetes API definitions.
# More info: https://github.com/kubernetes-sigs/kube-api-linter
KUBE_API_LINTER_PLUGIN := $(LOCALBIN)/kube-api-linter.so
KUBE_API_LINTER_BUILD_DIR := ./hack/kube-api-linter

.PHONY: kube-api-linter
kube-api-linter: $(KUBE_API_LINTER_PLUGIN) ## Build the kube-api-linter plugin
$(KUBE_API_LINTER_PLUGIN): $(KUBE_API_LINTER_BUILD_DIR)/go.mod
cd $(KUBE_API_LINTER_BUILD_DIR) && \
go build -buildmode=plugin -o "$(abspath $(KUBE_API_LINTER_PLUGIN))" sigs.k8s.io/kube-api-linter/pkg/plugin
$(KUBE_API_LINTER_BUILD_DIR)/go.mod:
@echo "Setting up local module for kube-api-linter plugin..."
mkdir -p $(KUBE_API_LINTER_BUILD_DIR)
cd $(KUBE_API_LINTER_BUILD_DIR) && \
go mod init local-kube-api-linter && \
go get sigs.k8s.io/kube-api-linter@latest

# go-install-tool will 'go install' any package with custom target and name of binary, if it doesn't exist
# $1 - target path with name of binary
# $2 - package url which can be installed
Expand Down
1 change: 1 addition & 0 deletions testdata/project-v4-multigroup/.github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ jobs:
uses: golangci/golangci-lint-action@v8
with:
version: v2.2.2
install-mode: goinstall
12 changes: 12 additions & 0 deletions testdata/project-v4-multigroup/.golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,20 @@ linters:
- unconvert
- unparam
- unused
- kubeapilinter
settings:
revive:
rules:
- name: comment-spacings
- name: import-shadowing
custom:
kubeapilinter:
path: "./bin/kube-api-linter.so"
description: "Kube API Linter plugin"
original-url: "sigs.k8s.io/kube-api-linter"
settings:
linters: { }
lintersConfig: { }
exclusions:
generated: lax
rules:
Expand All @@ -36,6 +45,9 @@ linters:
- dupl
- lll
path: internal/*
- path-except: "^api/"
linters:
- kubeapilinter
paths:
- third_party$
- builtin$
Expand Down
19 changes: 18 additions & 1 deletion testdata/project-v4-multigroup/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ cleanup-test-e2e: ## Tear down the Kind cluster used for e2e tests
@$(KIND) delete cluster --name $(KIND_CLUSTER)

.PHONY: lint
lint: golangci-lint ## Run golangci-lint linter
lint: golangci-lint kube-api-linter ## Run golangci-lint linter
$(GOLANGCI_LINT) run

.PHONY: lint-fix
Expand Down Expand Up @@ -221,6 +221,23 @@ golangci-lint: $(GOLANGCI_LINT) ## Download golangci-lint locally if necessary.
$(GOLANGCI_LINT): $(LOCALBIN)
$(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/v2/cmd/golangci-lint,$(GOLANGCI_LINT_VERSION))

# To lint Kubernetes API definitions.
# More info: https://github.com/kubernetes-sigs/kube-api-linter
KUBE_API_LINTER_PLUGIN := $(LOCALBIN)/kube-api-linter.so
KUBE_API_LINTER_BUILD_DIR := ./hack/kube-api-linter

.PHONY: kube-api-linter
kube-api-linter: $(KUBE_API_LINTER_PLUGIN) ## Build the kube-api-linter plugin
$(KUBE_API_LINTER_PLUGIN): $(KUBE_API_LINTER_BUILD_DIR)/go.mod
cd $(KUBE_API_LINTER_BUILD_DIR) && \
go build -buildmode=plugin -o "$(abspath $(KUBE_API_LINTER_PLUGIN))" sigs.k8s.io/kube-api-linter/pkg/plugin
$(KUBE_API_LINTER_BUILD_DIR)/go.mod:
@echo "Setting up local module for kube-api-linter plugin..."
mkdir -p $(KUBE_API_LINTER_BUILD_DIR)
cd $(KUBE_API_LINTER_BUILD_DIR) && \
go mod init local-kube-api-linter && \
go get sigs.k8s.io/kube-api-linter@latest

# go-install-tool will 'go install' any package with custom target and name of binary, if it doesn't exist
# $1 - target path with name of binary
# $2 - package url which can be installed
Expand Down
Loading
Loading