mirror of
https://github.com/balena-os/balena-supervisor.git
synced 2024-12-28 01:28:52 +00:00
a54b1ce048
Signed-off-by: Cameron Diver <cameron@balena.io>
128 lines
3.2 KiB
Bash
Executable File
128 lines
3.2 KiB
Bash
Executable File
#!/bin/bash
|
|
#
|
|
# balena-supervisor automated build
|
|
#
|
|
# Required variables:
|
|
# * ARCH
|
|
#
|
|
# Optional variables:
|
|
# * TAG: The default will be the current branch name
|
|
# * PUSH_IMAGES
|
|
# * CLEANUP
|
|
# * MIXPANEL_TOKEN: default key to inject in the supervisor image
|
|
# * EXTRA_TAG: when PUSH_IMAGES is true, additional tag to push to the registries
|
|
#
|
|
# Builds the supervisor for the architecture defined by $ARCH.
|
|
# Will produce and push an image tagged as balena/$ARCH-supervisor:$TAG
|
|
#
|
|
# It pulls intermediate images for caching, if available:
|
|
# balena/$ARCH-supervisor-node:$TAG
|
|
#
|
|
# In all of these cases it will use "master" if $TAG is not found.
|
|
#
|
|
# If PUSH_IMAGES is "true", it will also push the supervisor and intermediate images (must be logged in to dockerhub)
|
|
# to the docker registry.
|
|
# If CLEANUP is "true", all images will be removed after pushing - including any relevant images
|
|
# that may have been on the host from before the build, so be careful!
|
|
#
|
|
# Requires docker >= 17.05
|
|
#
|
|
|
|
set -e
|
|
|
|
THIS_FILE=$0
|
|
if [ -z "$ARCH" ] ; then
|
|
awk '{if(/^#/)print;else exit}' "${THIS_FILE}" | tail -n +2 | sed 's/\#//'
|
|
exit 1
|
|
fi
|
|
|
|
if [ -z "$TAG" ]; then
|
|
TAG=$(git rev-parse --abbrev-ref HEAD)
|
|
fi
|
|
|
|
if ! [ -x "$(command -v npx)" ]; then
|
|
echo 'NPM/npx is required to execute this script' >&2
|
|
exit 1
|
|
fi
|
|
|
|
# This is the supervisor image we will produce
|
|
TARGET_IMAGE=balena/$ARCH-supervisor:$TAG
|
|
TARGET_BUILD_IMAGE=balena/$ARCH-supervisor:$TAG-build
|
|
|
|
MASTER_IMAGE=balena/$ARCH-supervisor:master
|
|
MASTER_BUILD_IMAGE=balena/$ARCH-supervisor:master-build
|
|
|
|
CACHE_FROM=""
|
|
function useCache() {
|
|
image=$1
|
|
# Always add the cache because we can't do it from
|
|
# a subshell and specifying a missing image is fine
|
|
CACHE_FROM="${CACHE_FROM} --cache-from $image"
|
|
# Pull in parallel for speed
|
|
docker pull "$image" &
|
|
}
|
|
|
|
function retryImagePush() {
|
|
local image=$1
|
|
local -i retries
|
|
local success=1
|
|
|
|
while (( retries < 3 )); do
|
|
retries+=1
|
|
if docker push "${image}"; then
|
|
success=0
|
|
break
|
|
fi
|
|
done
|
|
|
|
return $success
|
|
}
|
|
|
|
# If we're building for an ARM architecture, we uncomment
|
|
# the cross-build commands, to enable emulation
|
|
function processDockerfile() {
|
|
if [ "${ARCH}" == "aarch64" ] || [ "${ARCH}" == "armv7hf" ] || [ "${ARCH}" == "rpi" ]; then
|
|
sed -E 's/#(.*"cross-build-(start|end)".*)/\1/g' Dockerfile
|
|
else
|
|
cat Dockerfile
|
|
fi
|
|
}
|
|
|
|
export ARCH
|
|
|
|
useCache "${TARGET_IMAGE}"
|
|
useCache "${TARGET_BUILD_IMAGE}"
|
|
useCache "${MASTER_IMAGE}"
|
|
useCache "${MASTER_BUILD_IMAGE}"
|
|
|
|
# Wait for our cache to be downloaded
|
|
wait
|
|
|
|
BUILD_ARGS="$CACHE_FROM --build-arg ARCH=${ARCH}"
|
|
# Try to build the first stage
|
|
processDockerfile | docker build -f - -t "${TARGET_BUILD_IMAGE}" --target BUILD ${BUILD_ARGS} .
|
|
|
|
# Now try to build the final stage
|
|
processDockerfile | docker build -f - -t "${TARGET_IMAGE}" ${BUILD_ARGS} .
|
|
|
|
if [ "${PUSH_IMAGES}" == "true" ]; then
|
|
retryImagePush "${TARGET_BUILD_IMAGE}" &
|
|
retryImagePush "${TARGET_IMAGE}" &
|
|
|
|
if [ -n "${EXTRA_TAG}" ]; then
|
|
docker tag "${TARGET_IMAGE}" "balena/${ARCH}-supervisor:${EXTRA_TAG}"
|
|
retryImagePush "balena/${ARCH}-supervisor:${EXTRA_TAG}" &
|
|
fi
|
|
fi
|
|
|
|
# Wait for any ongoing deploys
|
|
wait
|
|
|
|
if [ "$CLEANUP" = "true" ]; then
|
|
docker rmi \
|
|
"${TARGET_IMAGE}" \
|
|
"${TARGET_BUILD_IMAGE}" \
|
|
"${MASTER_IMAGE}" \
|
|
"${MASTER_BUILD_IMAGE}"
|
|
fi
|