From bd3e9aab51b22cd9364ce2f46a3264693dae43d1 Mon Sep 17 00:00:00 2001 From: awltux Date: Fri, 11 Sep 2020 15:12:15 +0100 Subject: [PATCH] Added Makefile: Uses docker to compile, test and package sbt project --- Makefile | 159 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 56 +++++++++++++++++++ 2 files changed, 215 insertions(+) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..84e2d2e47 --- /dev/null +++ b/Makefile @@ -0,0 +1,159 @@ + +# Enable debug output +debug ?= 0 + +# DockerHub image to build FROM: openjdk:$(open_jdk_version) +open_jdk_version ?= jdk8u265-b01-centos +open_jdk_image ?= adoptopenjdk/openjdk8 + +#Version of sbt package to install: https://dl.bintray.com/sbt/debian/sbt-$(sbt_version).deb +# Must match entry in project/build.properties +sbt_version ?= 1.3.3 + +mesos_version ?= 1.9.0 + +# Docker image tag +# This must exist as ${docker_image_name}:$(docker_image_tag) in either: +## Local docker image cache +## DockerHub +docker_image_tag=$(open_jdk_version)-$(sbt_version) +docker_image_name=mesos/sbt +docker_builder=builder + +dockerfile_url=https://raw.githubusercontent.com/mozilla/docker-sbt/main/Dockerfile + +quiet := @ +sbt_debug_flag := +ifneq ($(debug),0) +ifneq ($(debug),) +$(info Debug output enabled at level $(debug)) +quiet = +sbt_debug_flag := -v +endif +endif + +# Create a default target +.PHONY: no_targets__ +@no_targets__: list + +# List the make targets +.PHONY: list +list: + $(quiet) echo "List make targets:" &&\ + cat Makefile | grep "^[A-Za-z0-9_-]\+:" | grep -v "^_[A-Za-z0-9_-]\+" | awk '{print $$1}' | sed "s/://g" | sed "s/^/ /g" | sort + +# Create the docker entrypoint file +.PHONY: _create-dockerfile +_create-dockerfile: + $(quiet) \ + mkdir -p $(docker_builder) &&\ + echo 'ARG OPENJDK_TAG=$(open_jdk_version)' > $(docker_builder)/Dockerfile &&\ + echo 'ARG OPENJDK_NAME=$(open_jdk_image)' >> $(docker_builder)/Dockerfile &&\ + echo 'FROM $${OPENJDK_NAME}:$${OPENJDK_TAG}' >> $(docker_builder)/Dockerfile &&\ + echo 'ARG SBT_VERSION=$(sbt_version)' >> $(docker_builder)/Dockerfile &&\ + echo 'ARG MESOS_VERSION=$(mesos_version)' >> $(docker_builder)/Dockerfile &&\ + echo 'ENV DOCKER_FROM=$${OPENJDK_NAME}:$${OPENJDK_TAG}' >> $(docker_builder)/Dockerfile &&\ + echo 'ENV SBT_VERSION=$${SBT_VERSION}' >> $(docker_builder)/Dockerfile &&\ + echo 'ENV MESOS_VERSION=$${MESOS_VERSION}' >> $(docker_builder)/Dockerfile &&\ + echo 'RUN \' >> $(docker_builder)/Dockerfile &&\ + echo ' curl -L -o /etc/yum.repos.d/bintray-sbt-rpm.repo https://bintray.com/sbt/rpm/rpm &&\' >> $(docker_builder)/Dockerfile &&\ + echo ' rpm -Uvh http://repos.mesosphere.io/el/7/noarch/RPMS/mesosphere-el-repo-7-1.noarch.rpm &&\' >> $(docker_builder)/Dockerfile &&\ + echo ' yum install -y sbt-$${SBT_VERSION} mesos-$${MESOS_VERSION} git' >> $(docker_builder)/Dockerfile + + +# Build local copy of docker image if public image doesn't exist +.PHONY: docker-build +docker-build: _create-dockerfile + $(quiet) \ + mkdir -p $(docker_builder) &&\ + docker build \ + --rm \ + --tag $(docker_image_name):$(docker_image_tag) \ + -f $(docker_builder)/Dockerfile \ + . + + +# Create the docker entrypoint file +.PHONY: _create-entrypoint +_create-entrypoint: + $(quiet) \ + mkdir -p $(docker_builder) &&\ + echo "#!/bin/bash -eu" > $(docker_builder)/entrypoint.sh &&\ + echo 'USER_NAME=$(docker_builder)' >> $(docker_builder)/entrypoint.sh &&\ + echo 'echo "USER_UID=$${USER_UID}"' >> $(docker_builder)/entrypoint.sh &&\ + echo 'echo "USER_GID=$${USER_GID}"' >> $(docker_builder)/entrypoint.sh &&\ + echo 'if ! getent group $${USER_GID} &>/dev/null; then' >> $(docker_builder)/entrypoint.sh &&\ + echo ' groupadd --non-unique -g $${USER_GID} $${USER_NAME}' >> $(docker_builder)/entrypoint.sh &&\ + echo 'fi' >> $(docker_builder)/entrypoint.sh &&\ + echo 'if ! getent passwd $${USER_UID} &>/dev/null; then' >> $(docker_builder)/entrypoint.sh &&\ + echo ' useradd --non-unique -u $${USER_UID} -g $${USER_GID} $${USER_NAME} -d /app' >> $(docker_builder)/entrypoint.sh &&\ + echo 'fi' >> $(docker_builder)/entrypoint.sh &&\ + echo 'su $${USER_NAME} -c "sbt $$@"' >> $(docker_builder)/entrypoint.sh &&\ + chmod u+x $(docker_builder)/entrypoint.sh + + +# Clean the target directories and sbt cache +# Also cleans files created when using docker-shell-root +.PHONY: deep-clean +deep-clean: + $(quiet) \ + sudo find . -type d -name target -prune -exec rm -r {} + &&\ + sudo rm -rf $(docker_builder) &&\ + echo "Cleaning complete" + +.PHONY: _sbt-run +_sbt-run: + $(quiet) \ + docker run -it --rm \ + --entrypoint "/app/$(docker_builder)/entrypoint.sh" \ + -e USER_GID=$(shell id -g) \ + -e USER_UID=$(shell id -u) \ + -v $$PWD:/app \ + -v $$PWD/$(docker_builder)/.sbt:/home/$(docker_builder)/.sbt \ + -v $$PWD/$(docker_builder)/.ivy2:/home/$(docker_builder)/.ivy2 \ + -v $$PWD/$(docker_builder)/.cache:/home/$(docker_builder)/.cache \ + -w /app \ + $(docker_image_name):$(docker_image_tag) \ + $(sbt_debug_flag) $(sbt_command) + +.PHONY: sbt-clean +sbt-clean: _create-entrypoint + $(quiet) \ + $(MAKE) sbt_command=clean debug=$(debug) open_jdk_version=$(open_jdk_version) sbt_version=$(sbt_version) _sbt-run + +.PHONY: sbt-compile +sbt-compile: _create-entrypoint + $(quiet) \ + $(MAKE) sbt_command=compile debug=$(debug) open_jdk_version=$(open_jdk_version) sbt_version=$(sbt_version) _sbt-run + +.PHONY: sbt-test +sbt-test: _create-entrypoint + $(quiet) \ + $(MAKE) sbt_command=test debug=$(debug) open_jdk_version=$(open_jdk_version) sbt_version=$(sbt_version) _sbt-run + +.PHONY: sbt-package +sbt-package: _create-entrypoint + $(quiet) \ + $(MAKE) sbt_command=package debug=$(debug) open_jdk_version=$(open_jdk_version) sbt_version=$(sbt_version) _sbt-run &&\ + targetPath=$$(ls -1 target/scala*/*.jar) &&\ + echo "Plugin JAR file: $${targetPath}" + +.PHONY: sbt-shell +sbt-shell: _create-entrypoint + $(quiet) \ + $(MAKE) sbt_command=shell debug=$(debug) open_jdk_version=$(open_jdk_version) sbt_version=$(sbt_version) _sbt-run + +# BEWARE: Compiling from this bash shell can create build artifacts owned by root; use deep-clean to remove +# Uses a separate set of sbt cache directories +.PHONY: docker-shell +docker-shell: + $(quiet) \ + docker run -it --rm \ + -v $$PWD:/app \ + -v $$PWD/$(docker_builder)/root/.sbt:/root/.sbt \ + -v $$PWD/$(docker_builder)/root/.ivy2:/root/.ivy2 \ + -v $$PWD/$(docker_builder)/root/.cache:/root/.cache \ + -w /app \ + $(docker_image_name):$(docker_image_tag) \ + /bin/bash + \ No newline at end of file diff --git a/README.md b/README.md index 5f828b910..97890b754 100644 --- a/README.md +++ b/README.md @@ -36,3 +36,59 @@ For example version 1.1.0 and 2.0.0 will not have a compatible API, but Please take note that API below version 1.0.0 aren't considered stable and may change at any time. + +## Building using Docker sbt image + +Assuming you have docker installed, the Makefile targets can be used to clean, build and experiment with the sbt command line. +The docker container runs with the same UID and GID as the calling user preventing permission issues on mounted files. +The sbt working files are mounted from the 'builder' folder, so they persist across invocations. + +Make parameters: + + debug=[0|1]: Optional. defaults to 0, set to 1 for debug output from makefile and sbt command + open_jdk_version=[jdk8u265-b01-centos]: Optional, use this to override default. Image ${open_jdk_image}:${open_jdk_version} must exist. + open_jdk_image=[adoptopenjdk/openjdk8]: Optional, use this to override default. Image ${open_jdk_image}:${open_jdk_version} must exist. + mesos_version=[1.9.0]: Optional, use this to override default. Package mesos-${mesos_version} must exist. + sbt_version=[1.3.3]: Optional, use this to override default. Package sbt-${sbt_version} must exist. + +List available Makefile targets. The 'list' target is optional. Private _targets are not listed. + + make [list] + +Build a local docker image called mesos/sbt:${open_jdk_version}-${sbt_version}: + + make [debug=0] [open_jdk_image=adoptopenjdk/openjdk8] [open_jdk_version=jdk8u265-b01-centos] [sbt_version=1.3.3] [mesos_version=1.9.0] docker-build + +Run the sbt clean command: + + make [debug=0] [open_jdk_version=jdk8u265-b01-centos] [sbt_version=1.3.3] sbt-clean + +Run the sbt compile command: + + make [debug=0] [open_jdk_version=jdk8u265-b01-centos] [sbt_version=1.3.3] sbt-compile + +Run the sbt test command: +FIXME: Some Mesos tests timeout after 30sec. Investigate why. + + make [debug=0] [open_jdk_version=jdk8u265-b01-centos] [sbt_version=1.3.3] sbt-test + +Run the sbt package command: + + make [debug=0] [open_jdk_version=jdk8u265-b01-centos] [sbt_version=1.3.3] sbt-package + +Run the sbt shell command to experiment with other sbt commands: + + make [debug=0] sbt-shell + +Open a docker bash prompt to experiment with the build process. +NOTE: Uses the docker 'root' user, which can create subsequent file permission + conflicts in the mounted folders. + Use 'deep-clean' target to remove ALL intermediary files + + make [debug=0] docker-shell + +Remove the target directories and the sbt working directories. +NOTE: This can be useful if using the 'docker-shell', which can create root permission conflicts + + make [debug=0] deep-clean +