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.