#! /bin/bash
# Target to Photon OS version
VERSION=3
# Keep running container instance alive?
KEEP_SANDBOX_AFTER_FAILURE=1
# Draw spinner while waiting
DRAW_SPINNER=1
test "$#" -ne 1 && echo "Usage: $0 spec-file-to-build.spec" && exit 1
CONTAINER=build_spec
SPECPATH=$(readlink -m $1)
SPECFILE=$(basename $SPECPATH)
SPECDIR=$(dirname $SPECPATH)
mkdir -p $SPECDIR/stage/LOGS
LOGFILE=$SPECDIR/stage/LOGS/$(basename $SPECFILE .spec).log
# use &3 for user output
exec 3>&1
# redirect &1 and &2 to the log file
exec &>$LOGFILE
function wait_for_result() {
local pid=$!
if [ "$DRAW_SPINNER" -eq 1 ]; then
local spin='-\|/'
local i=0
echo -n " " >&3
while [ -d /proc/$pid ]; do
sleep .25
echo -ne "\b${spin:i++%4:1}" >&3
done
echo -ne "\b" >&3
fi
wait $pid
if [ $? -eq 0 ]; then
echo -e "\033[0;32mOK\033[0m" >&3
else
echo -e "\033[0;31mFAIL\033[0m" >&3
fail
fi
}
function run() {
echo -ne "\t$1 " >&3
shift
echo "run: $@"
$@ &
wait_for_result
}
function in_sandbox() {
docker exec $CONTAINER "$@"
}
function create_sandbox() {
docker ps -f "name=$CONTAINER" && docker rm -f $CONTAINER
docker inspect --format='{{.Created}}' photon_build_spec:$VERSION.0
local status=$?
local cdate=$(date --date=`docker inspect --format='{{.Created}}' photon_build_spec:$VERSION.0` '+%s')
# image exists?
if [ $status -eq 0 ]; then
local vdate=$((`date '+%s'` - 1209600))
# image is less then 2 weeks
if [ $cdate -gt $vdate ]; then
# use this image
run "Use local build template image" docker run -d --name $CONTAINER --network="host" photon_build_spec:$VERSION.0 tail -f /dev/null
return 0
else
# remove old image
docker image rm photon_build_spec:$VERSION.0
fi
fi
run "Pull photon image" docker run -d --name $CONTAINER --network="host" photon:$VERSION.0 tail -f /dev/null
# replace toybox with coreutils and install default build tools
run "Replace toybox with coreutils" in_sandbox tdnf remove -y toybox
run "Install default build tools" in_sandbox tdnf install -y rpm-build build-essential tar sed findutils file gzip patch
run "Create build template image for future use" docker commit `docker ps -q -f "name=$CONTAINER"` photon_build_spec:$VERSION.0
}
function prepare_buildenv() {
run "Create source folder" in_sandbox mkdir -p /usr/src/photon/SOURCES
run "Copy sources from $SPECDIR" docker cp $SPECDIR/. $CONTAINER:/usr/src/photon/SOURCES
local br=`sed -n 's/BuildRequires://p' $SPECPATH | sed 's/ \(<\|\)= /=/g;s/>\(=\|\) [^ ]*//g'`
if [ "$br" != "" ]; then
run "Install build requirements" in_sandbox tdnf install -y $br
fi
}
function build() {
echo -ne "\tRun rpmbuild " >&3
docker exec $CONTAINER rpmbuild -bb --define "dist .ph$VERSION" /usr/src/photon/SOURCES/$SPECFILE &
wait_for_result
}
function get_rpms() {
run "Copy RPMS" docker cp $CONTAINER:/usr/src/photon/RPMS $SPECDIR/stage
run "Copy SRPMS" docker cp $CONTAINER:/usr/src/photon/SRPMS $SPECDIR/stage
}
function destroy_sandbox() {
run "Stop container" docker kill $CONTAINER
run "Remove container" docker rm $CONTAINER
}
function clean_up() {
echo "Post clean up" >&3
docker ps -f "name=$CONTAINER" &>/dev/null && destroy_sandbox &>/dev/null
}
function fail() {
test "$KEEP_SANDBOX_AFTER_FAILURE" -ne 1 && clean_up || \
echo "Sandbox is preserved for analisys. Use 'docker exec -it $CONTAINER /bin/bash'" >&3
echo "Build failed. See $LOGFILE for full output" >&3
echo -e "\033[1;33m" >&3
tail $LOGFILE >&3
echo -e "\033[0m" >&3
exit 1
}
trap clean_up SIGINT SIGTERM
echo "1. Create sandbox" >&3
create_sandbox
echo "2. Prepare build environment" >&3
prepare_buildenv
echo "3. Build" >&3
build
echo "4. Get binaries" >&3
get_rpms
echo "5. Destroy sandbox" >&3
destroy_sandbox
echo "Build completed. RPMS are in '$SPECDIR/stage' folder" >&3