balena-supervisor/automation/build.sh
Felipe Lalanne 458e2a16cf Use balena CLI for pushing to balenaCloud
Updates the circle CI configuration to use the balena CLI to build the
supervisor image and deploy directly to the related balenaCloud app on merge
to master. This allows to build the supervisor as any other app,
including the posibility of creating a contract and a docker-compose

Change-type: patch
2021-09-24 13:26:13 +00:00

151 lines
3.4 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
# * 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
PROJECT_NAME="${PROJECT_NAME:-${ARCH}-supervisor}"
SERVICE_NAME="${SERVICE_NAME:-main}"
# This is the supervisor image we will produce
TARGET_IMAGE=balena/$ARCH-supervisor:$TAG
MASTER_IMAGE=balena/$ARCH-supervisor:master
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
}
function deviceType() {
case ${ARCH} in
aarch64)
echo "raspberrypi4-64"
;;
armv7hf)
echo "raspberrypi3"
;;
rpi)
echo "raspberry-pi"
;;
i386)
echo "qemux86"
;;
amd64)
echo "intel-nuc"
;;
*)
echo "unrecognized architecture ${ARCH}"
exit 1
;;
esac
}
export ARCH
useCache "${TARGET_IMAGE}"
useCache "${MASTER_IMAGE}"
# Wait for our cache to be downloaded
wait
BUILD_ARGS="$CACHE_FROM --buildArg ARCH=$ARCH"
# Make a copy of the file to match the architecture
processDockerfile > Dockerfile.${ARCH}
# Build the image
balena build --deviceType $(deviceType) --arch ${ARCH} --dockerfile ./Dockerfile.${ARCH} \
--projectName ${PROJECT_NAME} --tag ${TAG} ${BUILD_ARGS}
if [ "${PUSH_IMAGES}" == "true" ]; then
# Tag the CLI generated image with the target
docker tag "${PROJECT_NAME}_${SERVICE_NAME}:${TAG}" ${TARGET_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}" \
"${MASTER_IMAGE}"
fi