uci-docker-build/build

302 lines
7.6 KiB
Bash
Executable File

#!/bin/bash
udbuild () {
local targets=(dev arm64 amd64 publish multi default)
local log_dir; local no_prompt; local packages
declare -A dimage; declare -A dinstall; declare -A dupdate
declare OPTION; declare OPTARG; declare OPTIND
BDIR=$(dirname "$(realpath "$BASH_SOURCE")")
export BDIR
# load script library
source $BDIR/lib/load.sh
BUILD_EFILE=""
# check for subcommands first
case "$1" in
try)
shift 1; try_container "$@"; return $? ;;
load_env_file)
echo -e "@@@@@@ loading build environment file for external use @@@@@@"
BUILD_EFILE=$(echo -- "$@" | grep -oP -- '(?<=-e )[^ ]*')
if source_env_file "$BUILD_EFILE"; then
echo -e "@@@@@@@@@@@@@@@@@ returning to calling script @@@@@@@@@@@@@@@"
else
return 1
fi
;;
build_src) shift 1; get_build_src "$@"; return $? ;;
help)
;&
--help)
;&
-help) shift 1; usage "$@"; return $? ;;
source) type udbuild; return $? ;;
image)
shift 1
case "$1" in
name) shift 1; image_name "$@" ;;
tag) shift 1; image_tag "$@" ;;
push) shift 1; image_push "$@" ;;
delete) shift 1; image_delete "$@" ;;
exists) shift 1; image_exists "$@" ;;
info)
shift 1
case "$1" in
arch) shift 1; image_arch "$@" ;;
tags) shift 1; image_tags "$@" ;;
id) shift 1; image_id "$@" ;;
* ) image_info "$@"
esac
;;
*) echo no image subcommand $1 ;;
esac
return $?
;;
esac
[[ -z "$PS1" ]] || no_prompt=true
overwrite=true
while getopts 'ya:b:c:d:e:f:g:hi:lnopr:s:t:u:v:j:' OPTION; do
# echo processing: option:$OPTION argument:$OPTARG index:$OPTIND remaining:${@:$OPTIND}
case "$OPTION" in
a)
APPEND_BUILD_ENV=$OPTARG
;;
b)
# CUSTOM BASE IMAGE
BASE_IMAGE=$OPTARG
;;
y)
# CUSTOM BASE IMAGE
BASE_IMAGE_COPY=true
;;
c)
TRY_CMD=$OPTARG
;;
d)
# LINUX_DISTRO=$OPTARG
LINUX_DISTRO=$OPTARG
;;
e)
BUILD_EFILE=$OPTARG
if ! source_env_file $BUILD_EFILE; then return 2; fi
;;
f)
REBUILD=$OPTARG
;;
g)
TAG=$OPTARG
;;
h)
usage
return 0
;;
i)
IMAGE_INFO=$OPTARG
;;
o)
unset overwrite
;;
v)
VOLUME=$OPTARG
;;
j)
VERBOSE=$OPTARG
;;
l)
# append distro name to image name
APPEND_DISTRO=true
;;
n)
nocache="--no-cache"
;;
p)
echo "build script will be run WITHOUT user prompts (i.e. non-interactive)"
no_prompt=true
;;
r)
REPO=$OPTARG
;;
s)
# building source from which to bind into build, default is src/ in current directory
BUILD_SRC=$OPTARG
;;
t)
TARGET=$OPTARG
;;
u)
RUSER=$OPTARG
;;
*)
echo "unknown $0 option -$OPTARG"
usage
return 1
;;
esac
done
shift $((OPTIND - 1))
[[ ! $BUILD_EFILE ]] && source_env_file
if ! get_build_src; then
if [[ $no_prompt ]] ; then
echo aborting the build...
echo -e "\e[1;31mNOTE: use '_core_' to explicitly build with only the UCI core repo\e[1;37m"
return 2
else
echo "Do you want to build with only the UCI core"
read -n 1 -p "instead? [y]=>" REPLY
[[ $REPLY != "y" ]] && echo -e "\n" && return 2
BUILD_SRC="_core_"
echo -e "\n\e[1;31mNOTE: use '_core_' to explicitly build with only the UCI core\e[1;37m"
fi
fi
TARGET=${TARGET:-default}
[[ ! "${targets[@]}" =~ $TARGET ]] && echo $TARGET is not a valid target && echo valid targets are: ${targets[@]} && exit 4
LINUX_DISTRO=${LINUX_DISTRO:-alpine}
if ! get_base_image; then return $?; fi
IMAGE_NAME=$(make_image_name $@)
# TODO writing to existing tag untags existing image so write a new tag to that image then continue
# retag existing image and remove former tag
if [[ $(image_exists $IMAGE_NAME) ]]; then
if [[ $overwrite ]]; then
image_delete $IMAGE_NAME
else
newtag=$(date +'%d%H%M%S')
echo image exists retaging $(image_name $IMAGE_NAME) with tag :$newtag
image_tag $IMAGE_NAME $IMAGE_NAME:$newtag
image_tag -r $IMAGE_NAME
fi
fi
ARCH=$(get_arch)
log_dir=$PWD/logs
mkdir -p $log_dir
[[ $TARGET == "dev" ]] && VERBOSE=true
export BASE_IMAGE
export TAG
export IMAGE_NAME
export LINUX_DISTRO
export BUILD_SRC
export ARCH
export VERBOSE
export REBUILD
build_info
if [[ ! $no_prompt ]]; then
read -n 1 -p "do you want to continue [y]=>" REPLY
[[ $REPLY != "y" ]] && echo -e "\n" && return 4
fi
# cat $BDIR/Dockerfile | grep -b5 -a5 ENTRY
# return
builder=default
if [[ $TARGET == "publish" ]]; then
builder=publish
pushd "$BDIR" > /dev/null || return 3
if ! docker buildx ls | grep -q publish ; then
echo publish builder does not exist, creating with docker-container driver
docker buildx create --name publish --driver docker-container >/dev/null
docker buildx ls | grep publish
fi
popd > /dev/null || return 4
fi
# make a copy of build source locally in build directory
if [[ ! $BUILD_SRC = "_core_" ]]; then
# copy or bind build source directory to temporary .src/ subdirectory in build repo
_env_dir=rootfs/opt/env
[[ -d $BDIR/.src ]] && rm -rf $BDIR/.src
[[ -d $BDIR/core/$_env_dir ]] && rm -rf $BDIR/core/$_env_dir
if [[ $(which rsync 2> /dev/null ) ]]; then
rsync -aAru ${BUILD_SRC:-src}/ $BDIR/.src
rsync -aAru $BDIR/.src/$_env_dir/ $BDIR/core/$_env_dir > /dev/null 2>&1
else
echo no rsync copying with cp
/bin/cp -a ${BUILD_SRC:-src}/. $BDIR/.src > /dev/null 2>&1
/bin/cp -a $BDIR/.src/rootfs/opt/env/. $BDIR/core/rootfs/opt/env > /dev/null 2>&1
fi
fi
echo run environment directory copied to core at $BDIR/core/$_env_dir
ls -la $BDIR/core/$_env_dir
# create Dockerfile from template
if ! source $BDIR/Dockerfile.d/create; then
echo unable to create Dockerfile from template, aborting build
return 3
fi
if [[ -f $APPEND_BUILD_ENV ]]; then
if [[ ! $BUILD_SRC = "_core_" ]]; then
echo "------ Including custom build environment at $APPEND_BUILD_ENV -------"
cat $APPEND_BUILD_ENV
echo -e "\n--------------------"
echo | tee -a "$BDIR/.src/init/build.env" > /dev/null
tee -a "$BDIR/.src/init/build.env" > /dev/null < "$APPEND_BUILD_ENV"
fi
cat "$APPEND_BUILD_ENV" > "$BDIR/core/build.env"
# run in subshell to not affect $USER
/bin/bash <<"EOF"
unset USER
source "$BDIR/core/build.env"
[[ $USER_PW ]] && USER=${USER:-sysadmin}
if [[ $USER ]]; then
if [[ -f $PWD/$USER-permits ]]; then
echo sudo permits file: \'$USER-permits\' added to core build
/bin/cp -f $PWD/$USER-permits $BDIR/core
fi
fi
EOF
fi
pushd "$BDIR" > /dev/null || return 3
export BUILDING=true
echo -e "\n\e[1;31m######### RUNNING THE DOCKER BUILD COMMAND ######################"
echo running build command: docker buildx --builder ${builder} bake ${nocache} ${TARGET}
echo -e "#################################################################\e[1;37m"
docker buildx --builder ${builder} bake ${nocache} ${TARGET} 2>&1 | tee "$log_dir/${IMAGE_NAME//\//-}build.log"
[[ $? == 0 ]] && echo succcess building image $IMAGE_NAME || exit_abnormal 5
popd > /dev/null || return 4
# cleanup
echo cleaning up..
rm -rf $BDIR/.src $BDIR/core/build.env $BDIR/core/*-permits > /dev/null 2<&1
echo done cleaning
# try in container
if [[ ($TRY_CMD || $TARGET == "dev") ]]; then
echo trying newly built image in a container
echo name before try $IMAGE_NAME
try_container build -m opt $([[ $TARGET == "publish" ]] && echo -p) ${TRY_CMD:-shell}
fi
if [[ $TARGET == "private" ]]; then
echo pushing arm64 image $IMAGE_NAME to ${REPO:-docker hub}
image_push -a -r $REPO $IMAGE_NAME
echo pushing amd image $IMAGE_NAME to ${REPO:-docker hub}
image_push -r $REPO $IMAGE_NAME
fi
}
# if script was executed then call the function
(return 0 2>/dev/null) || udbuild "$@"