Skip to content

Commit

Permalink
Install tools instead of relying on go run (#241)
Browse files Browse the repository at this point in the history
`go run`ning tools is slow as Go recompiles the program with ever invocation. This PR changes to installing tools into `$PWD/out/tools` ready to be used by the rest of the `Makefile` improving the dependent recipe's performance.
  • Loading branch information
mergify[bot] authored Mar 31, 2023
2 parents ace3e08 + afc9083 commit df72ddf
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 43 deletions.
115 changes: 74 additions & 41 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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<target>\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.

Expand All @@ -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)

Expand All @@ -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/[email protected]

mocks: ## Generate mocks for testing.
mocks: $(MOCKGEN)
$(MOCKGEN) \
-destination internal/frontend/ec2/frontend_mock_test.go \
-package ec2 \
Expand All @@ -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)

1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 3 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -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=
Expand Down Expand Up @@ -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=
Expand Down

0 comments on commit df72ddf

Please sign in to comment.