GO_PACKAGE ?= git.kle.li/tools/go-import-redirector BINARY_BASE_NAME ?= $(shell echo ${GO_PACKAGE} | rev | cut -d'/' -f1 | rev) DIST := dist DIST_BIN_DIR := $(DIST)/binaries DIST_RELEASE_DIR := $(DIST)/release DIST_DOCKER_DIR := $(DIST)/docker DIST_DIRS := $(DIST_BIN_DIR) $(DIST_RELEASE_DIR) $(DIST_DOCKER_DIR) # Tool packages GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@latest XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@latest GXZ_PAGAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.11 # Allow overriding the go binary GO ?= go SHASUM ?= shasum -a 256 # Construct the version strings # VERSION default to dev or in CI next for default branch, and branch name for everything else... ifneq ($(CI),) # in CI ifeq ($(CI_REPO_DEFAULT_BRANCH),$(CI_COMMIT_BRANCH)) VERSION ?= next else VERSION ?= $(CI_COMMIT_BRANCH) endif else # not in CI VERSION ?= dev endif # VERSION_NUMBER semver compliant without the v prefix VERSION_NUMBER ?= 0.0.0 # Use CI_COMMIT_TAG from CI if set as version and version number ifneq ($(CI_COMMIT_TAG),) ISTAG := "true" VERSION := $(CI_COMMIT_TAG:v%=%) VERSION_NUMBER := ${VERSION} else ISTAG := "false" endif # Use CI provided SHA, else use git ifneq ($(CI_COMMIT_SHA),) SOURCE_SHA := $(CI_COMMIT_SHA) endif SOURCE_SHA ?= $(shell git rev-parse HEAD) SOURCE_SHA_SHORT := $(shell echo ${SOURCE_SHA} | head -c 8) COMMITTIME = $(shell git log -1 --format=%ct | xargs -I{} date -u +%Y%m%d%H%M%S -d "@{}") # VERSIONED_BINARY is the base output name for xgo VERSIONED_BINARY := $(BINARY_BASE_NAME)-$(VERSION) # https://docs.gitlab.com/ee/ci/variables/predefined_variables.html # https://woodpecker-ci.org/docs/next/usage/environment # gl GITLAB_CI CI CI_COMMIT_TAG CI_DEFAULT_BRANCH CI_COMMIT_SHA CI_COMMIT_SHORT_SHA CI_MERGE_REQUEST_IID CI_PIPELINE_SOURCE # WP CI=woodpecker CI_COMMIT_TAG CI_REPO_DEFAULT_BRANCH CI_COMMIT_SHA CI_COMMIT_PULL_REQUEST # Default LDFlags, stripping, dwarfing, statically linking and adding the version and commit to pkg/meta, extendable via LDFLAGS LDFLAGS := $(LDFLAGS) -s -w LDFLAGS := $(LDFLAGS) -X ${GO_PACKAGE}/pkg/meta.version=${VERSION} LDFLAGS := $(LDFLAGS) -X ${GO_PACKAGE}/pkg/meta.commit=${SOURCE_SHA} LDFLAGS := $(LDFLAGS) -X ${GO_PACKAGE}/pkg/meta.commitTime=${COMMITTIME} LDFLAGS := $(LDFLAGS) -X ${GO_PACKAGE}/pkg/meta.isTag=${ISTAG} LDFLAGS := $(LDFLAGS) -X ${GO_PACKAGE}/pkg/meta.branch=${CI_COMMIT_BRANCH} LDFLAGS := $(LDFLAGS) -X ${GO_PACKAGE}/pkg/meta.defaultBranch=${CI_REPO_DEFAULT_BRANCH} # Disable cgo, but overridable CGO_ENABLED ?= 0 HAS_GO = $(shell hash go > /dev/null 2>&1 && echo "GO" || echo "NOGO" ) ifeq ($(HAS_GO),GO) GOPATH ?= $(shell $(GO) env GOPATH) export PATH := $(GOPATH)/bin:$(PATH) CGO_CFLAGS ?= $(shell $(GO) env CGO_CFLAGS) $(CGO_EXTRA_CFLAGS) endif GOFLAGS := -v -trimpath EXECUTABLE ?= $(BINARY_BASE_NAME) # Release packagin stuffs... STORED_VERSION_FILE := VERSION TAR_EXCLUDES := .git $(EXECUTABLE) $(DIST) # just print the help instead of running any builds... all: help ##@ Prerequisites .PHONY: go-check go-check: ## Check Go version >= go.mod version $(eval MIN_GO_VERSION_STR := $(shell grep -Eo '^go\s+[0-9]+\.[0-9]+' go.mod | cut -d' ' -f2)) $(eval MIN_GO_VERSION := $(shell printf "%03d%03d" $(shell echo '$(MIN_GO_VERSION_STR)' | tr '.' ' '))) $(eval GO_VERSION := $(shell printf "%03d%03d" $(shell $(GO) version | grep -Eo '[0-9]+\.[0-9]+' | tr '.' ' ');)) @if [ "$(GO_VERSION)" -lt "$(MIN_GO_VERSION)" ]; then \ echo "This project requires Go $(MIN_GO_VERSION_STR) or greater to build. You can get it at https://go.dev/dl/"; \ exit 1; \ fi ##@ Convention Checking .PHONY: checks ## Run all checks checks: tidy-check security-check .PHONY: tidy-check tidy-check: tidy ## Check that mods have been cleaned up before checking in @diff=$$(git diff --color=always go.mod go.sum); \ if [ -n "$$diff" ]; then \ echo "Please run 'make tidy' and commit the result:"; \ echo "$${diff}"; \ exit 1; \ fi .PHONY: security-check security-check: go run $(GOVULNCHECK_PACKAGE) ./... ##@ Linting .PHONY: lint lint: ## Lint code @echo "Running golangci-lint" go run $(GOLANGCI_LINT_PACKAGE) run --timeout 10m ##@ Others # Help prints all targets (identified by ##) and categories (identified by ##@) .PHONY: help help: ## Display this help. @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) .PHONY: clean clean: ## Cleanup $(GO) clean -i ./... rm -rf $(EXECUTABLE) $(DIST) vendor .PHONY: tidy tidy: ## Tidy mods $(eval MIN_GO_VERSION := $(shell grep -Eo '^go\s+[0-9]+\.[0-9.]+' go.mod | cut -d' ' -f2)) $(GO) mod tidy -compat=$(MIN_GO_VERSION) vendor: go.mod go.sum ## Download mods to vendor $(GO) mod vendor @touch vendor .PHONY: build build: go-check build-linux ## Build the binary matching the local system $(DIST_DIRS): mkdir -p $(DIST_DIRS) .PHONY: build-linux build-linux: | $(DIST_DIRS) CGO_ENABLED="$(CGO_ENABLED)" CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) build $(GOFLAGS) -tags 'netgo osusergo tzdata $(TAGS)' -ldflags '$(LDFLAGS)' -o $(DIST_BIN_DIR)/$(VERSIONED_BINARY) .PHONY: release-copy release-copy: | $(DIST_DIRS) cd $(DIST); for file in `find . -type f -name "*"`; do cp $${file} ./release/; done; .PHONY: release-check release-check: | $(DIST_DIRS) cd $(DIST)/release/; for file in `find . -type f -name "*"`; do echo "checksumming $${file}" && $(SHASUM) `echo $${file} | sed 's/^..//'` > $${file}.sha256; done; .PHONY: release-compress release-compress: | $(DIST_DIRS) cd $(DIST)/release/; for file in `find . -type f -name "*"`; do echo "compressing $${file}" && $(GO) run $(GXZ_PAGAGE) -k -9 $${file}; done; .PHONY: release-sources release-sources: | $(DIST_DIRS) echo $(VERSION) > $(STORED_VERSION_FILE) # bsdtar needs a ^ to prevent matching subdirectories $(eval EXCL := --exclude=$(shell tar --help | grep -q bsdtar && echo "^")./) # use transform to a add a release-folder prefix; in bsdtar the transform parameter equivalent is -s $(eval TRANSFORM := $(shell tar --help | grep -q bsdtar && echo "-s '/^./$(BINARY_BASE_NAME)-src-$(VERSION)/'" || echo "--transform 's|^./|$(BINARY_BASE_NAME)-src-$(VERSION)/|'")) tar $(addprefix $(EXCL),$(TAR_EXCLUDES)) $(TRANSFORM) -czf $(DIST)/release/$(BINARY_BASE_NAME)-src-$(VERSION).tar.gz . rm -f $(STORED_VERSION_FILE) .PHONY: release ## Prepare a full release release: build-linux # release-copy release-compress vendor release-sources release-check .PHONY: dockerize dockerize: | $(DIST_DIRS) cp -R docker/fscopy/* $(DIST_DOCKER_DIR)/ cp $(DIST_BIN_DIR)/$(VERSIONED_BINARY) $(DIST_DOCKER_DIR)/bin/$(BINARY_BASE_NAME) docker/make_dockerfile.sh > $(DIST_DOCKER_DIR)/Dockerfile