
For some reason -n doesn't work with arrays, probably becuase the array has an entry by the array's indexed value is empty. By quoting it we get it as one unit, which behaves as expected. Change-Id: Ic3243d13d3f8fc9978c460f816e33ad348302d8e
176 lines
4.0 KiB
Bash
Executable File
176 lines
4.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Depends on bash 4 and gawk
|
|
|
|
TOPDIR=$(git rev-parse --show-toplevel)
|
|
DOCKERDIR="$TOPDIR/docker"
|
|
|
|
declare -A dependency
|
|
declare -A img_dirs
|
|
declare -A status
|
|
|
|
function info {
|
|
[[ -n $1 ]] && printf "%s\n" "$1"
|
|
}
|
|
|
|
function success {
|
|
[[ -n $1 ]] && printf "\033[00;32m%s\033[00m\n" "$1"
|
|
}
|
|
|
|
function warn {
|
|
[[ -n $1 ]] && printf "\033[00;31m%s\033[00m\n" "$1"
|
|
}
|
|
|
|
function set_defaults {
|
|
PREFIX=fedora-rdo-
|
|
NAMESPACE=kollaglue
|
|
}
|
|
|
|
function has_changed {
|
|
local image=$1
|
|
# Rebuild everything unless given git revision
|
|
# We don't really care about the order of the $FROM and $TO parameters, all
|
|
# we need is the list of changed files between the revisions, or HEAD if
|
|
# only one of them is specified
|
|
[[ -z $FROM && -z $TO ]] || git diff --name-only $FROM $TO | grep -q "${img_dirs[$image]#$TOPDIR/}"
|
|
}
|
|
|
|
function requires_build {
|
|
local image=$1
|
|
local dep=${dependency[$image]}
|
|
# An image requires a built if it meets the following conditions:
|
|
# - it has instructions to build the image
|
|
# - it hasn't been processed yet
|
|
# - its dependency was rebuilt or its build instruction was modified
|
|
[[ ${img_dirs[$image]} && -z ${status[$image]} ]] && \
|
|
([[ ${status[$dep]} == "rebuilt" ]] || has_changed $image)
|
|
}
|
|
|
|
function build_image {
|
|
local dir=$1
|
|
if [ -x "$dir/build" ]; then
|
|
printf "\n"
|
|
info "Building image in $dir"
|
|
if $dir/build $ARGS; then
|
|
success "Successfully built image in $dir"
|
|
status[$image]="rebuilt"
|
|
else
|
|
warn "Failed to build image in $dir"
|
|
status[$image]="fail"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
function init_image {
|
|
local img_dir=$1
|
|
|
|
set_defaults
|
|
[ -f $TOPDIR/.buildconf ] && . $TOPDIR/.buildconf
|
|
[ -f $img_dir/.buildconf ] && . $img_dir/.buildconf
|
|
[ -n $FORCE_NAMESPACE ] && NAMESPACE=$FORCE_NAMESPACE
|
|
|
|
local image="${NAMESPACE:+${NAMESPACE}/}${PREFIX}${img_dir##*/}"
|
|
local base_image=$(cat $img_dir/Dockerfile | gawk 'match($0, /^\s*FROM\s+(\S+)/, matches) {print matches[1]}' )
|
|
|
|
img_dirs[$image]=$img_dir
|
|
dependency[$image]=$base_image
|
|
|
|
# Restore defaults to minimize risk of side effects
|
|
set_defaults
|
|
}
|
|
|
|
function process_image {
|
|
local image=$1
|
|
if [ -n "${dependency[$image]}" ]; then
|
|
process_image ${dependency[$image]}
|
|
fi
|
|
if requires_build $image; then
|
|
build_image ${img_dirs[$image]}
|
|
fi
|
|
if [ -z "${status[$image]}" ]; then
|
|
status[$image]="up-to-date"
|
|
fi
|
|
}
|
|
|
|
function print_summary {
|
|
printf "\nSummary\n=======\n"
|
|
for image in "${!status[@]}"; do
|
|
case "${status[$image]}" in
|
|
("fail") warn "Failed to process $image" ;;
|
|
("rebuilt") success "Rebuilt $image" ;;
|
|
(*) info "$image: ${status[$image]}" ;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
function interrupted {
|
|
info "Interrupted..."
|
|
print_summary
|
|
exit 1
|
|
}
|
|
|
|
function usage () {
|
|
read -r -d '' HELP <<EOF
|
|
A wrapper to build-docker-image that build all images in order.
|
|
|
|
Options:
|
|
|
|
--from <git-revision>
|
|
--to <git-revision>
|
|
|
|
$($TOPDIR/tools/build-docker-image --help)
|
|
EOF
|
|
printf "%s\n" "${HELP/$TOPDIR\/tools\/build-docker-image/$0}"
|
|
}
|
|
|
|
trap 'interrupted' INT
|
|
|
|
|
|
ARGS=$@
|
|
PARSED_ARGS=$(getopt -q -o hn: -l help,namespace:,from:,to: -- "$@")
|
|
|
|
eval set -- "$PARSED_ARGS"
|
|
|
|
while :; do
|
|
case "$1" in
|
|
|
|
(--help|-h) usage
|
|
exit 0
|
|
;;
|
|
|
|
(--namespace|-n)
|
|
shift
|
|
FORCE_NAMESPACE="$1"
|
|
;;
|
|
|
|
(--from)
|
|
shift
|
|
FROM="$1"
|
|
ARGS=${ARGS/\-\-from*$FROM/}
|
|
;;
|
|
|
|
(--to)
|
|
shift
|
|
TO="$1"
|
|
ARGS=${ARGS/\-\-to*$TO/}
|
|
;;
|
|
|
|
(--) break
|
|
;;
|
|
|
|
esac
|
|
|
|
shift
|
|
done
|
|
|
|
# Do a first pass to find images to build and their dependencies
|
|
for dockerfile in $(find $DOCKERDIR -name Dockerfile); do
|
|
init_image $(dirname $dockerfile)
|
|
done
|
|
|
|
# Process all images
|
|
for image in "${!img_dirs[@]}"; do
|
|
process_image $image
|
|
done
|
|
|
|
print_summary
|