From 292463614ad738f855b25dfdea02cf66326ff349 Mon Sep 17 00:00:00 2001 From: Nuckal777 Date: Fri, 9 Feb 2024 17:10:55 +0100 Subject: [PATCH] Add support for controller-gen and setup-envtest --- internal/core/scan.go | 8 +++++- internal/makefile/makefile.go | 50 ++++++++++++++++++++++++++++++----- 2 files changed, 50 insertions(+), 8 deletions(-) diff --git a/internal/core/scan.go b/internal/core/scan.go index 0a45cfe..7dfee81 100644 --- a/internal/core/scan.go +++ b/internal/core/scan.go @@ -35,7 +35,8 @@ type ScanResult struct { GoVersion string // from "go" directive in go.mod, e.g. "1.21" GoDirectDependencies []module.Version // from "require" directive(s) in go.mod without the "// indirect" comment HasBinInfo bool // whether we can produce linker instructions for "github.com/sapcc/go-api-declarations/bininfo" - UsesPostgres bool // wether postgres is used + UsesPostgres bool // whether postgres is used + KubernetesController bool // whether the repository contains a Kubernetes controller } const ModFilename = "go.mod" @@ -47,6 +48,7 @@ func Scan() ScanResult { var goDeps []module.Version hasBinInfo := false usesPostgres := false + kubernetesController := false for _, v := range modFile.Require { if !v.Indirect { @@ -60,6 +62,9 @@ func Scan() ScanResult { if v.Mod.Path == "github.com/lib/pq" { usesPostgres = true } + if v.Mod.Path == "sigs.k8s.io/controller-runtime" { + kubernetesController = true + } } return ScanResult{ @@ -68,6 +73,7 @@ func Scan() ScanResult { GoDirectDependencies: goDeps, HasBinInfo: hasBinInfo, UsesPostgres: usesPostgres, + KubernetesController: kubernetesController, } } diff --git a/internal/makefile/makefile.go b/internal/makefile/makefile.go index 34fa5c6..6f0854c 100644 --- a/internal/makefile/makefile.go +++ b/internal/makefile/makefile.go @@ -97,6 +97,9 @@ endif build.addDefinition("GO_BUILDFLAGS =%s", cfg.Variable("GO_BUILDFLAGS", defaultBuildFlags)) build.addDefinition("GO_LDFLAGS =%s", cfg.Variable("GO_LDFLAGS", strings.TrimSpace(defaultLdFlags))) build.addDefinition("GO_TESTENV =%s", cfg.Variable("GO_TESTENV", "")) + if sr.KubernetesController { + build.addDefinition("TESTBIN=$(shell pwd)/testbin") + } if sr.HasBinInfo { build.addDefinition("") build.addDefinition("# These definitions are overridable, e.g. to provide fixed version/commit values when") @@ -172,6 +175,16 @@ endif ` go install github.com/google/addlicense@latest; fi`, }...) } + if sr.KubernetesController { + prepareStaticRecipe = append(prepareStaticRecipe, []string{ + `@if ! hash controller-gen 2>/dev/null; then` + + ` printf "\e[1;36m>> Installing controller-gen...\e[0m\n";` + + ` go install sigs.k8s.io/controller-tools/cmd/controller-gen@latest; fi`, + `@if ! hash setup-envtest 2>/dev/null; then` + + ` printf "\e[1;36m>> Installing setup-envtest...\e[0m\n";` + + ` go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest; fi`, + }...) + } test.addRule(rule{ description: "Install any tools required by static-check. This is used in CI before dropping privileges, you should probably install all the tools using your package manager", phony: true, @@ -179,6 +192,20 @@ endif recipe: prepareStaticRecipe, }) + if sr.KubernetesController { + components := strings.Split(sr.ModulePath, "/") + roleName := components[len(components)-1] + test.addRule(rule{ + description: "Generate code for Kubernetes CRDs and deepcopy.", + target: "generate", + recipe: []string{ + `@printf "\e[1;36m>> controller-gen\e[0m\n"`, + fmt.Sprintf(`@controller-gen crd rbac:roleName=%s paths="./..." output:crd:artifacts:config=crd`, roleName), + `@controller-gen object paths=./...`, + }, + }) + } + // add target to run golangci-lint test.addRule(rule{ description: "Install and run golangci-lint. Installing is used in CI, but you should probably install golangci-lint using your package manager.", @@ -192,7 +219,7 @@ endif }) //add targets for `go test` incl. coverage report - test.addRule(rule{ + testRule := rule{ description: "Run tests and generate coverage report.", phony: true, target: "build/cover.out", @@ -200,12 +227,17 @@ endif orderOnlyPrerequisites: []string{"build"}, recipe: []string{ `@printf "\e[1;36m>> go test\e[0m\n"`, - fmt.Sprintf( - `@env $(GO_TESTENV) go test $(GO_BUILDFLAGS) -ldflags '%s $(GO_LDFLAGS)' -shuffle=on -p 1 -coverprofile=$@ -covermode=count -coverpkg=$(subst $(space),$(comma),$(GO_COVERPKGS)) $(GO_TESTPKGS)`, - makeDefaultLinkerFlags(path.Base(sr.MustModulePath()), sr), - ), }, - }) + } + goTest := fmt.Sprintf(`go test $(GO_BUILDFLAGS) -ldflags '%s $(GO_LDFLAGS)' -shuffle=on -p 1 -coverprofile=$@ -covermode=count -coverpkg=$(subst $(space),$(comma),$(GO_COVERPKGS)) $(GO_TESTPKGS)`, makeDefaultLinkerFlags(path.Base(sr.MustModulePath()), sr)) + if sr.KubernetesController { + testRule.prerequisites = append(testRule.prerequisites, "generate") + testRule.recipe = append(testRule.recipe, `KUBEBUILDER_ASSETS="$(shell setup-envtest use 1.29.1 --bin-dir $(TESTBIN) -p path)" `+goTest) + } else { + testRule.recipe = append(testRule.recipe, `@env $(GO_TESTENV) `+goTest) + } + + test.addRule(testRule) test.addRule(rule{ description: "Generate an HTML file with source code annotations from the coverage report.", @@ -261,7 +293,7 @@ endif }) } - if isSAPCC { + if isSAPCC && cfg.GitHubWorkflow != nil { // `go list .` does not work to get the package name because it requires a go file in the current directory // but some packages like concourse-swift-resource or gatekeeper-addons only have subpackages allGoFilesExpr := `$(patsubst $(shell awk '$$1 == "module" {print $$2}' go.mod)%,.%/*.go,$(shell go list ./...))` @@ -369,6 +401,10 @@ func buildTargets(binaries []core.BinaryConfiguration, sr core.ScanResult) []rul )}, } + if sr.KubernetesController { + r.prerequisites = append(r.prerequisites, "generate") + } + result = append(result, r) allPrerequisites = append(allPrerequisites, r.target) }