diff --git a/makefiles/check-defined.mk b/makefiles/check-defined.mk new file mode 100644 index 0000000..6942cbb --- /dev/null +++ b/makefiles/check-defined.mk @@ -0,0 +1,16 @@ +# check_defined is a function that will error if the passed in variable is +# undefined. +# +# usage: +# install: +# $(call check_defined, var1) +# $(call check_defined, var2) +# +# Copied this from https://gist.github.com/bbl/bf4bf5875d0c705c4cd78d264f98a8b1 +check_defined = \ + $(strip $(foreach 1,$1, \ + $(call __check_defined,$1,$(strip $(value 2))))) +__check_defined = \ + $(if $(value $1),, \ + $(error Undefined $1$(if $2, ($2)))) + diff --git a/makefiles/common.mk b/makefiles/common.mk new file mode 100644 index 0000000..a90cd03 --- /dev/null +++ b/makefiles/common.mk @@ -0,0 +1,143 @@ +DOCKERFILE_LIST := $(strip $(shell \ + for version in $(VERSION_LIST); do \ + printf "Dockerfile.%s " $$version ; \ + done)) + +REGISTRY = docker.shnee.net +NAMESPACE = shnee +SUBMODULE_PATH = common + +# TODO STARTHERE this is wring just find a way to create tags, command will be +# the same except the tag. +BUILD_CMDS := $(shell \ + for version in $(VERSION_LIST); do \ + echo "docker build . $(DOCKER_BUILD_ARGS) -f Dockerfile.$$version \ + -t $(IMAGE_NAME):$$version"; done) + +$(call check_defined, IMAGE_NAME) +DOCKER_BUILD_ARGS = +BUILD_CMD = docker build . $(DOCKER_BUILD_ARGS) -f Dockerfile.$(VERSION) -t \ + $(IMAGE_NAME):$(VERSION) + +# These variables are used to create a unique tag for the image being built. +DATE = $(shell date +%F) +SHORT_COMMIT_HASH = $(shell git log -1 --format=%h) + +ANSIBLE_CONST_ARGS ?= all \ + -i localhost, \ + -m template \ + --connection=local \ + +################################################################################ +# tags +################################################################################ + +LATEST_TAG = latest +# UNIQUE_TAG_SUFFIX ?= $(DATE)-$(SHORT_COMMIT_HASH) +UNIQUE_TAG_SUFFIX = $(DATE) + +################################################################################ +# end tags +################################################################################ + +common-submodule: common/.git + +update-common-submodule: + git submodule update --init + +# $(DOCKERFILE_LIST): +# @echo ansible template $@ + +.drone.yml: common/templates/drone.yml.tpl + # TODO ansible template command. + +# version-check: +# # TODO Consider makign sure that given version is in the version list. +# $(call check_defined, VERSION) + +set-version-%: + + @# Set the version using the wildcard from the target. + $(eval VERSION=$*) + + @# Make sure that the VERSION_LIST is set. + $(call check_defined, VERSION_LIST) + + @# Check that the version from the targets wildcard is in our + @# VERSION_LIST. If not then error out with a message. + @if echo $(VERSION_LIST) | grep -q $* ; then :; else \ + echo "ERROR: Version $* is not in VERSION_LIST: $(VERSION_LIST)"; \ + exit 1; fi + +Dockerfile.j2: ;@: + +Dockerfile.%: set-version-% Dockerfile.j2 + # TODO the fact that this target depends on BASE_IMAGE_NAME is really a + # detail of the Dockerfile template. We need to come up with a way to + # call a target in the parent repo to check that vars are defined and + # that adds ansible var arguments. + $(call check_defined, BASE_IMAGE_NAME) + ansible $(ANSIBLE_CONST_ARGS) \ + -e "version=$*" \ + -e "base_image_name=$(BASE_IMAGE_NAME)" \ + -a "src=Dockerfile.j2 dest=$@" + +foreach-version = \ + for version in $(VERSION_LIST); do \ + make $1-$$version; \ + done + +build-all: + for version in $(VERSION_LIST); do \ + make build-$$version; \ + done + +tag-all: + $(call foreach-version,tag) + +push-all: + $(call foreach-version,push) + +# TODO REM STARTHERE it would be cool if we could pull base images. If we do +# that consider templating the base-image in the Dockerfile. +build-%: set-version-% Dockerfile.% + $(BUILD_CMD) + +.PHONY: tag-% +tag-%: set-version-% build-% + docker tag $(IMAGE_NAME):$* $(REGISTRY)/$(NAMESPACE)/$(IMAGE_NAME):$* + +# TODO REM adda comment, this target has to be before `push-%` +.PHONY: push-$(IMAGE_NAME) +push-$(IMAGE_NAME)\:%: push-% ;@: + +.PHONY: push-% +push-%: set-version-% tag-% + docker push $(REGISTRY)/$(NAMESPACE)/$(IMAGE_NAME):$* + +.PHONY: no-cache +no-cache: + $(eval DOCKER_BUILD_ARGS=$(DOCKER_BUILD_ARGS) --no-cache) + +# TODO is this used? (no) do we need it. +.PHONY: pull-base-% +pull-base-%: set-version-% + $(call check_defined, BASE_IMAGE_NAME) + docker pull $(BASE_IMAGE_NAME):$* + +.PHONY: $(IMAGE_NAME)\:% +$(IMAGE_NAME)\:%: build-% ;@: + +include $(SUBMODULE_PATH)/makefiles/check-defined.mk + +.SUFFIXES: + +.PHONY: build-% set-version-% +.PHONY: update-common-submodule + +# From make manual: +# .SECONDARY with no prerequisites causes all targets to be treated as secondary +# (i.e., no target is removed because it is considered intermediate). +# +# Without this target the Dockerfiles were getting removed. +.SECONDARY: diff --git a/templates/drone.yml.tpl b/templates/drone.yml.tpl new file mode 100644 index 0000000..8f0f269 --- /dev/null +++ b/templates/drone.yml.tpl @@ -0,0 +1,31 @@ +--- +kind: pipeline +type: docker +name: docker-build + +steps: + - name: docker build + # When using 20.10 there is an issue when running on hosts with older + # versions of docker, runc, and libseccomp. See + # https://wiki.alpinelinux.org/wiki/Release_Notes_for_Alpine_3.14.0#faccessat2 + # for info on the issue. So to avoid the bug we're using an older version, + # 19.03. + image: shnee/dind + volumes: + - name: dockersock + path: /var/run + commands: + - sleep 5 # give docker enough time to start + "{{ docker_build_yaml }}" + +services: + - name: docker + image: shnee/dind + privileged: true + volumes: + - name: dockersock + path: /var/run + +volumes: + - name: dockersock + temp: {}