New git container builder work flow_

May 29, 2020 @15:19

I currently have a handful of containerized apps that I maintain in a shared repository and a few more that are in their own repositories. I wanted to be able to trigger builds of all my container projects from a single post-receive hook so I leaned on the work I did previously cleaning up my git hooks and created a script that will look in the root of the repository for a Dockerfile and if it finds one will launch a builder container using the same python script that I wrote about previously.

Now any time I push to master the post-receive hook will launch a container which will build the container, push it to my private registry and export a copy to a tarball on an internal website. This simplifies my work flow quite a bit as I no longer have to remember to run make(1) after I commit my work.

If you are interested, the hooks are available in my misc git repository. The one you are interested is likely post-receive.d/build-single-container. There is a slightly more complex script that runs in the shared repository that is able to call builders for any project inside the repository that needs building. That script is below.

#!/bin/sh
# container post-receive hook
# (c) 2019 Matthew J. Ernisse <matt@going-flying.com>
# All Rights Reserved.
#

set -e

GIT_AUTHOR=""
GIT_BRANCH=""
GIT_DIR=$(git rev-parse --git-dir 2>/dev/null)
PROJECTS=""
REV=0

add_to()
{
    local global_var new_var
    # $1 may be blank on first iter
    if [ -z "$2" ]; then
        echo "$1"
        return
    fi

    global_var="$1"
    new_var="$2"

    for x in $global_var; do
        if [ "$x" = "$new_var" ]; then
            echo "$global_var"
            return
        fi
    done

    echo "$global_var $new_var"
    return
}

try_container()
{
    if [ -z "$1" ]; then
        echo "usage: try_container project"
        return 1
    fi

    echo "*** Launching builder for $1"
    /srv/git/global-hooks/start-container-builder.py \
        "$1" "$REV" "$GIT_AUTHOR"
}

if [ -z "$GIT_DIR" ]; then
    echo >&2 "fatal: post-receive GIT_DIR not set"
    exit 1
fi


while read oldrev newrev refname; do
    GIT_BRANCH=$refname
    REV=$newrev
done

GIT_AUTHOR=$(git show --format='%ae' --no-patch $REV)

for fn in $(git diff-tree --no-commit-id --name-only -r $REV); do
    PROJECTS="$(add_to $PROJECTS $(dirname $fn))"
done

if [ ! "$GIT_BRANCH" = "refs/heads/master" ]; then
    echo "*** Non master commit (${GIT_BRANCH}), refusing to build..."
    exit
fi

if [ -n "$PROJECTS" ]; then
    for project in $PROJECTS; do
        if [ -z "$project" ]; then
            continue
        fi

        if [ "$project" = "." ]; then
            continue
        fi

        try_container "$project"
    done
fi

I hope this helps you or at least proves that you do not need a large and complex CI/CD system for small projects, git comes with all the pieces you need built in.

Subscribe via RSS. Send me a comment.