
.NOTPARALLEL:

MK.nobindir=1

MK_ALL_TARGETS=build publish

#----------------------------------------------------------------------------------------------

ifeq ($(STEM),)
$(error STEM is undefined. Aborting.)
endif

ifeq ($(VERSION),)
VERSION:=$(patsubst v%,%,$(shell git describe --tags `git rev-list --tags --max-count=1`))
endif
ifeq ($(VERSION),)
$(error Cannot determine version. Aborting.)
endif

ifeq ($(VAR),)
_VAR=
else
_VAR=-$(VAR)
endif

BUILD_OPT=--rm --pull
# --squash

DOCKERFILE_STEM ?= $(ROOT)/Dockerfile

#----------------------------------------------------------------------------------------------

REDIS_VER ?= 6.0.1

PACK ?= 0
TEST ?= 0

ifeq ($(ARTIFACTS),1)
PACK:=1
endif

#----------------------------------------------------------------------------------------------

OSNICK ?= debian

ifeq ($(OS.custom),)

OS.centos7=centos:7.6.1810
OS.fedora=fedora:32
OS.focal=ubuntu:focal
OS.bionic=ubuntu:bionic
OS.xenial=ubuntu:xenial
OS.buster=debian:buster
OS.stretch=debian:stretch

endif # OS

OS=$(OS.$(OSNICK))
ifeq ($(OS),)
$(error Invalid OSNICK. Aborting.)
endif

#----------------------------------------------------------------------------------------------

define HELP
make build      # build Docker images
  REDIS_VER=ver   # use Redis version `ver`
  TEST=1          # test aftar build
  PACK=1          # create packages
  ARTIFACTS=1     # copy artifacts from docker image

make publish   # push Docker image to Dockerhub
  LATEST=1       # tag selected version as latest and push it
  PUSH=0         # only push multi-arch manifest
  MULTI=1        # build and push multi-arch Docker manifest

make show      # display registry information from Docker repo

Common arguments:
  OSNICK=nick    # nick=buster|stretch|bionic|centos7
  VERSION=ver    # build and publish version x.y.z
  X64=1          # build and publish x64 arch
  ARM7=1         # build and publish arm32v7 arch
  ARM8=1         # build and publish arm64v8 arch
endef

#----------------------------------------------------------------------------------------------

define D_NAME # (1=arch)
$(STEM):$(VERSION)$(_VAR)-$(1)-$(OSNICK)
endef

define D_LATEST_NAME # (1=arch)
$(STEM):latest$(_VAR)-$(1)-$(OSNICK)
endef

DOCKER_BUILD_ARGS += \
	VERSION=$(VERSION) \
	OSNICK=$(OSNICK) \
	OS=$(OS) \
	REDIS_VER=$(REDIS_VER) \
	TEST=$(TEST) \
	PACK=$(PACK)

define targets # (1=OP, 2=op)
$(1)_TARGETS :=
$(1)_TARGETS += $(if $(findstring $(X64),1),$(2)_x64)
$(1)_TARGETS += $(if $(findstring $(ARM7),1),$(2)_arm32v7)
$(1)_TARGETS += $(if $(findstring $(ARM8),1),$(2)_arm64v8)

$(1)_TARGETS += $$(if $$(strip $$($(1)_TARGETS)),,$(2)_x64 $(2)_arm32v7 $(2)_arm64v8)
endef

$(eval $(call targets,BUILD,build))
$(eval $(call targets,PUSH,push))

#----------------------------------------------------------------------------------------------

ifeq ($(ARTIFACTS),1)
ifeq ($(ART_DIR),)
$(error ART_DIR is not defined.)
endif
export ART_DIR
ifeq ($(ART_INT_DIR),)
$(error ART_INT_DIR is not defined.)
endif
export ART_INT_DIR
endif

define build_x64 # (1=arch)
build_$(1):
	$(SHOW)docker build $(BUILD_OPT) -t $(call D_NAME,$(1)) -f $(DOCKERFILE_STEM) \
		$(foreach A,$(DOCKER_BUILD_ARGS),--build-arg $(A)) \
		$(ROOT)
ifeq ($(ARTIFACTS),1)
	$(SHOW)IMAGE=$(call D_NAME,$(1)) $(MK)/docker-collect-artifacts
endif
ifeq ($(LATEST),1)
	$(SHOW)docker tag $(call D_NAME,$(1)) $(call D_LATEST_NAME,$(1))
endif

.PHONY: build_$(1)
endef

define build_arm  # (1=arch)
build_$(1):
	$(SHOW)docker build $(BUILD_OPT) -t $(call D_NAME,$(1)) -f $(DOCKERFILE_STEM).arm \
		$(foreach A,$(DOCKER_BUILD_ARGS),--build-arg $(A)) \
		--build-arg ARCH=$(1) \
		$(ROOT)
ifeq ($(ARTIFACTS),1)
	$(SHOW)IMAGE=$(call D_NAME,$(1)) $(MK)/docker-collect-artifacts
endif
ifeq ($(LATEST),1)
	$(SHOW)docker tag $(call D_NAME,$(1)) $(call D_LATEST_NAME,$(1))
endif

.PHONY: build_$(1)
endef

define push # (1=arch)
push_$(1):
	$(SHOW)docker push $(call D_NAME,$(1))
ifeq ($(LATEST),1)
	$(SHOW)docker push $(call D_LATEST_NAME,$(1))
endif

.PHONY: push_$(1)
endef

define create_manifest # (1=version)
$(SHOW)docker manifest create -a $(STEM):$(1)-$(OSNICK) \
	-a $(STEM):$(VERSION)-x64-$(OSNICK) \
	-a $(STEM):$(VERSION)-arm64v8-$(OSNICK) \
	-a $(STEM):$(VERSION)-arm32v7-$(OSNICK)
$(SHOW)docker manifest annotate $(STEM):$(1)-$(OSNICK) $(STEM):$(VERSION)-arm32v7-$(OSNICK) --os linux --arch arm --variant v7
$(SHOW)docker manifest annotate $(STEM):$(1)-$(OSNICK) $(STEM):$(VERSION)-arm64v8-$(OSNICK) --os linux --arch arm64 --variant v8
$(SHOW)docker manifest push -p $(STEM):$(1)-$(OSNICK)
endef

#----------------------------------------------------------------------------------------------

DEFAULT_TARGETS += $(BUILD_TARGETS)

include $(MK)/defs

include $(MK)/rules

$(eval $(call build_x64,x64))
$(eval $(call build_arm,arm64v8))
$(eval $(call build_arm,arm32v7))

$(eval $(call push,x64))
$(eval $(call push,arm64v8))
$(eval $(call push,arm32v7))

ifeq ($(MULTI),1)

ifneq ($(PUSH),0)
publish: $(PUSH_TARGETS) ;
else
publish:
endif
	$(SHOW)$(call create_manifest,$(VERSION))
	$(SHOW)$(call create_manifest,latest)

else

publish: $(PUSH_TARGETS) ;

endif # MULTI

show:
	@echo "$(STEM):"
ifeq ($(INSPECT),1)
	$(SHOW)docker manifest inspect $(STEM):$(VERSION)-$(OSNICK) | jq
else
	$(SHOW)curl -s -X "GET" https://cloud.docker.com/v2/repositories/$(STEM)/tags/ | jq
endif

.PHONY: build publish show
