From afc9083744407cb12ad987e5098de391f490b139 Mon Sep 17 00:00:00 2001 From: Chris Doherty Date: Thu, 16 Mar 2023 21:32:40 -0500 Subject: [PATCH] Stop using go run to run tooling go run has proven sluggish when invoking Make recipes. This change trends us toward an install and use approach skipping the compilation invoked with go run. Signed-off-by: Chris Doherty --- Makefile | 115 +++++++++++++++++++++++++++++++++++-------------------- go.mod | 1 + go.sum | 5 ++- 3 files changed, 78 insertions(+), 43 deletions(-) diff --git a/Makefile b/Makefile index d8275923..d37ef957 100644 --- a/Makefile +++ b/Makefile @@ -13,10 +13,72 @@ GOPROXY ?= $(shell go env GOPROXY) # Specify additional `docker build` arguments. (Recipes: image) IMAGE_ARGS ?= -t hegel +# Root output directory. +OUT_DIR ?= $(shell pwd)/out + +# Project binary output directory. +BIN_DIR ?= $(OUT_DIR)/bin + +# Linter installation directory. +TOOLS_DIR ?= $(OUT_DIR)/tools + +# Platform variables +PLATFORM_OS ?= $(shell uname) +PLATFORM_ARCH ?= $(shell uname -m) + .PHONY: help help: @awk 'BEGIN {FS = ":.*##"; printf "Usage:\n make \033[36m\033[0m\n"} /^[%\/0-9A-Za-z_-]+:.*?##/ { printf " \033[36m%-20s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) +# -- Tooling + +GOLANGCI_LINT_VERSION ?= v1.51.2 +GOLANGCI_LINT := $(TOOLS_DIR)/golangci-lint +$(GOLANGCI_LINT): + curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | \ + sh -s -- -b $(TOOLS_DIR) $(GOLANGCI_LINT_VERSION) + +# The command to run mockgen. +MOCKGEN_VERSION ?= v1.6.0 +MOCKGEN := $(TOOLS_DIR)/mockgen +$(MOCKGEN): PLATFORM_ARCH := $(if $(filter x86_64,$(PLATFORM_ARCH)),amd64,$(PLATFORM_ARCH)) +$(MOCKGEN): PLATFORM_OS := $(shell echo $(PLATFORM_OS) | tr '[:upper:]' '[:lower:]') +$(MOCKGEN): + curl -sSfL https://github.com/golang/mock/releases/download/$(MOCKGEN_VERSION)/mock_$(MOCKGEN_VERSION:v%=%)_$(PLATFORM_OS)_$(PLATFORM_ARCH).tar.gz | \ + tar -C $(TOOLS_DIR) --strip-components=1 -xzf - + @rm $(TOOLS_DIR)/README.md $(TOOLS_DIR)/LICENSE + +SETUP_ENVTEST_VERSION := latest +SETUP_ENVTEST := $(TOOLS_DIR)/setup-envtest +$(SETUP_ENVTEST): + GOBIN=$(TOOLS_DIR) go install sigs.k8s.io/controller-runtime/tools/setup-envtest@$(SETUP_ENVTEST_VERSION) + +HADOLINT_VERSION ?= v2.12.0 +HADOLINT := $(TOOLS_DIR)/hadolint +$(HADOLINT): + curl -sSfL https://github.com/hadolint/hadolint/releases/download/$(HADOLINT_VERSION)/hadolint-$(PLATFORM_OS)-$(PLATFORM_ARCH) > $(HADOLINT);\ + chmod u+x $(HADOLINT) + +YAMLLINT_VERSION ?= v1.28.0 +YAMLTOOLS_DIR := $(TOOLS_DIR)/yamllint +YAMLLINT_BIN := $(YAMLTOOLS_DIR)/bin/yamllint +# We install yamllint into a target directory to avoid installing something to the users system. +# This makes it necessary to set the PYTHONPATH so yamllint can import its modules. +YAMLLINT := PYTHONPATH=$(YAMLTOOLS_DIR) $(YAMLLINT_BIN) +# For simplicity, depend on pip. Its common enough to be present on most systems. +$(YAMLLINT_BIN): $(shell mkdir -p $(YAMLTOOLS_DIR)) + python3 -m pip install -t $(YAMLTOOLS_DIR) -qq yamllint==$(YAMLLINT_VERSION) + +.PHONY: tools +tools: $(GOLANGCI_LINT) $(MOCKGEN) $(SETUP_ENVTEST) $(HADOLINT) $(YAMLLINT_BIN) ## Install tools required for development. + +.PHONY: clean-tools +clean-tools: ## Remove tools installed for development. + chmod -R +w $(TOOLS_DIR)/envtest + rm -rf $(TOOLS_DIR) + +# -- Everything else + # The image recipe calls build hence build doesn't feature here. all: test image ## Run tests and build the Hegel a Linux Hegel image for the host architecture. @@ -39,15 +101,15 @@ test-e2e: ## Run E2E tests. go test $(GO_TEST_ARGS) -tags=e2e -coverprofile=coverage.out ./internal/e2e # Version should match with whatever we consume in sources (check the go.mod). -SETUP_ENVTEST := go run sigs.k8s.io/controller-runtime/tools/setup-envtest@latest -ENVTEST_BIN_DIR := $(shell pwd)/bin +ENVTEST_BIN_DIR := $(TOOLS_DIR)/envtest # The kubernetes version to use with envtest. Overridable when invoking make. # E.g. make ENVTEST_KUBE_VERSION=1.24 test-integration -ENVTEST_KUBE_VERSION ?= 1.25 +ENVTEST_KUBE_VERSION ?= 1.25 .PHONY: setup-envtest -setup-envtest: +setup-envtest: ## Download and setup binaries for envtest testing. +setup-envtest: $(SETUP_ENVTEST) @echo Installing Kubernetes $(ENVTEST_KUBE_VERSION) binaries into $(ENVTEST_BIN_DIR); \ $(SETUP_ENVTEST) use --bin-dir $(ENVTEST_BIN_DIR) $(ENVTEST_KUBE_VERSION) @@ -56,23 +118,23 @@ setup-envtest: # For packages containing both unit and integration tests its recommended to populate # "//go:build !integration" in all unit test sources so as to avoid compiling them in this recipe. .PHONY: test-integration +test-integration: ## Run integration tests. test-integration: setup-envtest test-integration: TEST_DIRS := $(shell grep -R --include="*.go" -l -E "//go:build.*\sintegration" . | xargs dirname | uniq) -test-integration: ## Run integration tests. +test-integration: source <($(SETUP_ENVTEST) use -p env --bin-dir $(ENVTEST_BIN_DIR) $(ENVTEST_KUBE_VERSION)); \ go test $(GO_TEST_ARGS) -tags=integration -coverprofile=coverage.out $(TEST_DIRS) # When we build the image its Linux based. This means we need a Linux binary hence we need to export # GOOS so we have compatible binary. .PHONY: image +image: ## Build a Linux based Hegel image for the the host architecture. image: export GOOS=linux -image: build ## Build a Linux based Hegel image for the the host architecture. +image: build DOCKER_BUILDKIT=1 docker build $(IMAGE_ARGS) . -# The command to run mockgen. -MOCKGEN = go run github.com/golang/mock/mockgen@v1.6 - mocks: ## Generate mocks for testing. +mocks: $(MOCKGEN) $(MOCKGEN) \ -destination internal/frontend/ec2/frontend_mock_test.go \ -package ec2 \ @@ -86,42 +148,13 @@ mocks: ## Generate mocks for testing. -package healthcheck \ -source internal/healthcheck/health_check.go -OUT_DIR ?= $(shell pwd)/out -BIN_DIR ?= $(OUT_DIR)/bin -LINT_DIR ?= $(OUT_DIR)/linters - -GOLANGCI_LINT_VERSION ?= v1.50.1 -GOLANGCI_LINT := go run github.com/golangci/golangci-lint/cmd/golangci-lint@$(GOLANGCI_LINT_VERSION) - -HADOLINT_VERSION ?= v2.12.0 -HADOLINT_TARGET := install/hadolint-$(HADOLINT_VERSION) -HADOLINT := $(LINT_DIR)/hadolint-$(HADOLINT_VERSION) - -YAMLLINT_VERSION ?= v1.28.0 -YAMLLINT_TARGET := install/yamllint-$(YAMLLINT_VERSION) -YAMLLINT_INSTALL := $(LINT_DIR)/yamllint-$(YAMLLINT_VERSION) -# We install yamllint into a target directory to avoid installing something to the users system. -# This makes it necessary to set the PYTHONPATH so yamllint can import its modules. -YAMLLINT := PYTHONPATH=$(YAMLLINT_INSTALL) $(YAMLLINT_INSTALL)/bin/yamllint - -LINT_OS := $(shell uname) -LINT_ARCH := $(shell uname -m) - .PHONY: lint -lint: SHELL := bash -lint: $(shell mkdir -p $(LINT_DIR)) -lint: $(HADOLINT_TARGET) $(YAMLLINT_TARGET) ## Run linters. +lint: ## Run linters. +lint: $(shell mkdir -p $(TOOLS_DIR)) +lint: $(GOLANGCI_LINT) $(HADOLINT) $(YAMLLINT_BIN) $(GOLANGCI_LINT) run $(HADOLINT) --no-fail $(shell find . -name "*Dockerfile") $(YAMLLINT) . -.PHONY: $(HADOLINT_TARGET) -$(HADOLINT_TARGET): - curl -sfL https://github.com/hadolint/hadolint/releases/download/$(HADOLINT_VERSION)/hadolint-$(LINT_OS)-$(LINT_ARCH) > $(HADOLINT);\ - chmod u+x $(HADOLINT) -# For simplicity, depend on pip. Its common enough to be present on most systems. -.PHONY: $(YAMLLINT_TARGET) -$(YAMLLINT_TARGET): $(shell mkdir -p $(YAMLLINT_INSTALL)) - python3 -m pip install -t $(YAMLLINT_INSTALL) -qq yamllint==$(YAMLLINT_VERSION) diff --git a/go.mod b/go.mod index 98644ca4..d162ae1d 100644 --- a/go.mod +++ b/go.mod @@ -99,6 +99,7 @@ require ( golang.org/x/term v0.5.0 // indirect golang.org/x/text v0.7.0 // indirect golang.org/x/time v0.3.0 // indirect + golang.org/x/tools v0.6.0 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef // indirect diff --git a/go.sum b/go.sum index 8a74dcb2..6f5bfc99 100644 --- a/go.sum +++ b/go.sum @@ -780,7 +780,7 @@ golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449/go.mod h1:s0Qsj1ACt9ePp/hM golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I= +golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1039,7 +1039,8 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= -golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE= +golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=