From c84b119ec231d4c418bcf75d8de3cf2195dbdd74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Andr=C3=A9?= Date: Mon, 22 Dec 2014 17:24:27 +0900 Subject: [PATCH] Add script to build all docker images in the correct order The script is a wrapper for the `build-docker-image` script and thus respond to the same options. It also responds to two additional `--from` and `--to` options that allows building only images that have changed between the specified git revisions. Examples: # Build all images contained in docker directory and push new release build-all-docker-images --release --push # Build only images modified in test-branch along with their children build-all-docker-images --from master --to test-branch Change-Id: Ib83bf475cd2a21965071c13eec4456df5c332edd --- tools/build-all-docker-images | 162 ++++++++++++++++++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100755 tools/build-all-docker-images diff --git a/tools/build-all-docker-images b/tools/build-all-docker-images new file mode 100755 index 0000000000..285a218cd6 --- /dev/null +++ b/tools/build-all-docker-images @@ -0,0 +1,162 @@ +#!/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" + fi + fi +} + +function init_image { + local img_dir=$1 + + set_defaults + [ -f $TOPDIR/.buildconf ] && . $TOPDIR/.buildconf + [ -f $img_dir/.buildconf ] && . $img_dir/.buildconf + if [ ! -z $FORCE_NAMESPACE ]; then + NAMESPACE=$FORCE_NAMESPACE + fi + + 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 [ ${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]="processed" + fi +} + +function usage () { + read -r -d '' HELP < +--to + +$($TOPDIR/tools/build-docker-image --help) +EOF + printf "%s\n" "${HELP/$TOPDIR\/tools\/build-docker-image/$0}" +} + + +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 + +# Report failed images +for image in "${!status[@]}"; do + if [ -z ${status[$image]} ]; then + warn "Failed to process $image" + fi +done