Skip to content

Commit

Permalink
Add support for controller-gen and setup-envtest
Browse files Browse the repository at this point in the history
Also add a new prepare section to facilitate all the dependency
installing
  • Loading branch information
Nuckal777 authored and SuperSandro2000 committed Feb 12, 2024
1 parent d1a39b4 commit c19dbbc
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 33 deletions.
8 changes: 7 additions & 1 deletion internal/core/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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 {
Expand All @@ -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{
Expand All @@ -68,6 +73,7 @@ func Scan() ScanResult {
GoDirectDependencies: goDeps,
HasBinInfo: hasBinInfo,
UsesPostgres: usesPostgres,
KubernetesController: kubernetesController,
}
}

Expand Down
116 changes: 84 additions & 32 deletions internal/makefile/makefile.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ var scanOverrides []byte
func newMakefile(cfg *core.Configuration, sr core.ScanResult) *makefile {
hasBinaries := len(cfg.Binaries) > 0

isSAPCC := strings.HasPrefix(sr.ModulePath, "github.com/sapcc") || strings.HasPrefix(sr.ModulePath, "github.wdf.sap.corp") || strings.HasPrefix(sr.ModulePath, "github.tools.sap")

///////////////////////////////////////////////////////////////////////////
// General
general := category{name: "general"}
Expand Down Expand Up @@ -71,6 +73,51 @@ endif
})
}

///////////////////////////////////////////////////////////////////////////
// Prepare
prepare := category{name: "prepare"}

//add target for installing dependencies for `make check`
prepareStaticRecipe := []string{
`@if ! hash golangci-lint 2>/dev/null; then` +
` printf "\e[1;36m>> Installing golangci-lint (this may take a while)...\e[0m\n";` +
` go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest; fi`,
}
prepareStaticPrerequisites := []string{}
if isSAPCC {
prepareStaticRecipe = append(prepareStaticRecipe, []string{
`@if ! hash go-licence-detector 2>/dev/null; then` +
` printf "\e[1;36m>> Installing go-licence-detector...\e[0m\n";` +
` go install go.elastic.co/go-licence-detector@latest; fi`,
`@if ! hash addlicense 2>/dev/null; then ` +
` printf "\e[1;36m>> Installing addlicense...\e[0m\n"; ` +
` go install github.com/google/addlicense@latest; fi`,
}...)
}
if sr.KubernetesController {
prepareStaticRecipe = append(prepareStaticRecipe, []string{
`@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`,
}...)
prepareStaticPrerequisites = append(prepareStaticPrerequisites, "install-controller-gen")
}
prepare.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,
target: "prepare-static-check",
recipe: prepareStaticRecipe,
prerequisites: prepareStaticPrerequisites,
})

if sr.KubernetesController {
prepare.addRule(rule{
description: "Install controller-gen required by static-check and build-all. This is used in CI before dropping privileges, you should probably install all the tools using your package manager",
phony: true,
target: "install-controller-gen",
})
}

///////////////////////////////////////////////////////////////////////////
// Build
build := category{name: "build"}
Expand All @@ -97,6 +144,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")
Expand Down Expand Up @@ -141,8 +191,6 @@ endif
test.addDefinition(`space := $(null) $(null)`)
test.addDefinition(`comma := ,`)

isSAPCC := strings.HasPrefix(sr.ModulePath, "github.com/sapcc") || strings.HasPrefix(sr.ModulePath, "github.wdf.sap.corp") || strings.HasPrefix(sr.ModulePath, "github.tools.sap")

//add main testing target
checkPrerequisites := []string{"static-check", "build/cover.html"}
if hasBinaries {
Expand All @@ -156,28 +204,19 @@ endif
recipe: []string{`@printf "\e[1;32m>> All checks successful.\e[0m\n"`},
})

//add target for installing dependencies for `make check`
prepareStaticRecipe := []string{
`@if ! hash golangci-lint 2>/dev/null; then` +
` printf "\e[1;36m>> Installing golangci-lint (this may take a while)...\e[0m\n";` +
` go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest; fi`,
}
if isSAPCC {
prepareStaticRecipe = append(prepareStaticRecipe, []string{
`@if ! hash go-licence-detector 2>/dev/null; then` +
` printf "\e[1;36m>> Installing go-licence-detector...\e[0m\n";` +
` go install go.elastic.co/go-licence-detector@latest; fi`,
`@if ! hash addlicense 2>/dev/null; then ` +
` printf "\e[1;36m>> Installing addlicense...\e[0m\n"; ` +
` go install github.com/google/addlicense@latest; fi`,
}...)
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=./...`,
},
})
}
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,
target: "prepare-static-check",
recipe: prepareStaticRecipe,
})

// add target to run golangci-lint
test.addRule(rule{
Expand All @@ -192,20 +231,26 @@ 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",
// We use order only prerequisite because this target is used in CI.
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.",
Expand Down Expand Up @@ -261,7 +306,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 ./...))`
Expand Down Expand Up @@ -350,11 +395,14 @@ endif

func buildTargets(binaries []core.BinaryConfiguration, sr core.ScanResult) []rule {
result := make([]rule, 0, len(binaries)+1)
bAllRule := rule{
buildAllRule := rule{
description: "Build all binaries.",
target: "build-all",
}
result = append(result, bAllRule)
if sr.KubernetesController {
buildAllRule.prerequisites = []string{"install-controller-gen"}
}
result = append(result, buildAllRule)

allPrerequisites := make([]string, 0, len(binaries))
for _, bin := range binaries {
Expand All @@ -369,6 +417,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)
}
Expand Down

0 comments on commit c19dbbc

Please sign in to comment.