# @see https://tech.davis-hansson.com/p/make/ # define the default shell SHELL := bash # Add the -T options to "docker compose exec" to avoid the # "panic: the handle is invalid" # error on Windows and Linux # @see https://stackoverflow.com/a/70856332/413531 DOCKER_COMPOSE_EXEC_OPTIONS=-T # OS is a defined variable for WIN systems, so "uname" will not be executed OS?=$(shell uname) # Values of OS: # Windows => Windows_NT # Mac => Darwin # Linux => Linux ifeq ($(OS),Windows_NT) # Windows requires the .exe extension, otherwise the entry is ignored # @see https://stackoverflow.com/a/60318554/413531 SHELL := bash.exe else ifeq ($(OS),Darwin) # On Mac, the -T must be omitted to avoid cluttered output # @see https://github.com/moby/moby/issues/37366#issuecomment-401157643 DOCKER_COMPOSE_EXEC_OPTIONS= endif # @see https://tech.davis-hansson.com/p/make/ for some make best practices # use bash strict mode @see http://redsymbol.net/articles/unofficial-bash-strict-mode/ # -e - instructs bash to immediately exit if any command has a non-zero exit status # -u - a reference to any variable you haven't previously defined - with the exceptions of $* and $@ - is an error # -o pipefail - if any command in a pipeline fails, that return code will be used as the return code # of the whole pipeline. By default, the pipeline's return code is that of the last command - even if it succeeds. # https://unix.stackexchange.com/a/179305 # -c - Read and execute commands from string after processing the options. Otherwise, arguments are treated as filed. Example: # bash -c "echo foo" # will excecute "echo foo" # bash "echo foo" # will try to open the file named "echo foo" and execute it .SHELLFLAGS := -euo pipefail -c # display a warning if variables are used but not defined MAKEFLAGS += --warn-undefined-variables # remove some "magic make behavior" MAKEFLAGS += --no-builtin-rules # include the default variables include .make/variables.env # include the local variables -include .make/local.env # include the current environment settings -include .make/.env # set default values for ENV and TAG to suppress "warning: undefined variable" when .make/.env does not exist yet ENV?= TAG?= # Common variable to pass arbitrary options to targets ARGS?= # bash colors RED:=\033[0;31m GREEN:=\033[0;32m YELLOW:=\033[0;33m NO_COLOR:=\033[0m # @see https://www.thapaliya.com/en/writings/well-documented-makefiles/ .DEFAULT_GOAL:=help include .make/*.mk # Note: # We are NOT using $(MAKEFILE_LIST) but defined the required make files manually via "Makefile .make/*.mk" # because $(MAKEFILE_LIST) also contains the .env files AND we cannot force the order of the files help: @printf '%-43s \033[1mDefault values: \033[0m \n' @printf '%-43s ===================================\n' @printf '%-43s ENV: \033[31m "$(ENV)" \033[0m \n' @printf '%-43s TAG: \033[31m "$(TAG)" \033[0m \n' @printf '%-43s ===================================\n' @printf '%-43s \033[3mRun the following command to set them:\033[0m\n' @printf '%-43s \033[1mmake make-init ENVS="ENV=prod TAG=latest"\033[0m\n' @awk 'BEGIN {FS = ":.*##"; printf "\n\033[1mUsage:\033[0m\n make \033[36m\033[0m\n"} /^[a-zA-Z0-9_-]+:.*?##/ { printf " \033[36m%-40s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' Makefile .make/*.mk ##@ [Make] ENVS?=ENV=local TAG=2.2 .PHONY: make-init make-init: ## Initializes the local .makefile/.env file with ENV variables for make. Use via ENVS="KEY_1=value1 KEY_2=value2" @$(if $(ENVS),,$(error ENVS is undefined)) @rm -f .make/.env @for variable in $(ENVS); do \ echo $$variable | tee -a .make/.env > /dev/null 2>&1; \ done @echo "Created a local .make/.env file"