Skip to content

Instantly share code, notes, and snippets.

@alexjoedt
Last active November 2, 2023 14:09
Show Gist options
  • Save alexjoedt/8fe1de8d8bd4558987e4e6801358f28e to your computer and use it in GitHub Desktop.
Save alexjoedt/8fe1de8d8bd4558987e4e6801358f28e to your computer and use it in GitHub Desktop.
#!/bin/bash
# This script build docker images and create docker tags using git tags with Semantic Versioning pattern
# https://semver.org/spec/v2.0.0.html
# However, it only partially supports pre-release tags as mentioned in part 9 (https://semver.org/spec/v2.0.0.html#spec-item-9)
# Supported git tags: v1.0.0, v1.0.0-beta.1, v1.0.0-alpha.1
# Array of repos for the docker image
REPOS=("<REPO_URL_1>" "<REPO_URL_2>")
SEMANTIC_VERSION_PATTERN="^v([0-9]+)\.([0-9]+)\.([0-9]+)(-([A-Za-z-]+(\.[0-9A-Za-z-]+)?))?$"
usage() {
echo "Usage: $0 [options...]" 1>&2
echo "-f Forces clean build, if HEAD is ahead of git tag" 1>&2
echo "-r Pushs the docker images" 1>&2
echo "-t Test run, only prints docker image tags" 1>&2
exit 1
}
while getopts ":frt" o; do
case "${o}" in
f)
FORCE="true"
;;
r)
RELEASE="true"
;;
t)
DRY_RUN="true"
;;
*)
usage
;;
esac
done
shift $((OPTIND - 1))
if [ "$1" = "--help" ] || [ "$1" = "-h" ]; then
usage
fi
# get the last tag which matches the semantic versioning pattern
VERSION_TAG=$(git describe --tags --abbrev=0 --match "v*.*.*" 2>/dev/null)
# if it is a gitlab job, it uses the CI_COMMIT_TAG
if [[ "$CI_COMMIT_TAG" =~ $SEMANTIC_VERSION_PATTERN ]]; then
echo "Build from CI_COMMIT_TAG: $CI_COMMIT_TAG"
VERSION_TAG="$CI_COMMIT_TAG"
fi
if [ -z "$VERSION_TAG" ]; then
echo "Keine Git-Versions-Tags vorhanden" 1>&2
exit 1
fi
# If there are changes in the tree and/or the version tag is behind the HEAD, the build is "dirty".
# However, a nigthly tag is ALWAYS created
GIT_REVISION=$(git rev-parse --short HEAD)
SUFFIX=""
if [ -n "$(git status --porcelain)" ]; then
echo "Dirty build..."
SUFFIX="-dirty"
fi
# If HEAD is ahead of the version tag, we also have a dirty build
if [ "$(git rev-list -n 1 $VERSION_TAG)" != "$(git rev-parse HEAD)" ] && [ "$SUFFIX" = "" ]; then
echo "Dirty build..."
SUFFIX="-dirty"
fi
# remove the suffix if we force a clean build
if [[ "$FORCE" == "true" ]]; then SUFFIX=""; fi
# Extract Major Minor, Patch and Pre-release
MAJOR=""
MINOR=""
PATCH=""
PRE_RELEASE=""
if [[ $VERSION_TAG =~ $SEMANTIC_VERSION_PATTERN ]]; then
MAJOR="${BASH_REMATCH[1]}"
MINOR="${BASH_REMATCH[2]}"
PATCH="${BASH_REMATCH[3]}"
PRE_RELEASE="${BASH_REMATCH[5]}"
test -n "$PRE_RELEASE" && PRE_RELEASE="-${PRE_RELEASE}"
else
echo "invalid Semantic Versioning Tag (source: https://semver.org/spec/v2.0.0.html)"
exit 1
fi
VERSION="${MAJOR}.${MINOR}.${PATCH}${PRE_RELEASE}${SUFFIX}"
if [[ "$DRY_RUN" == "true" ]]; then
echo "=== Images ==="
for IMAGE_TAG in ${REPOS[@]}; do
echo
echo "$IMAGE_TAG:nightly"
test -z "$PRE_RELEASE" && echo "$IMAGE_TAG:latest${SUFFIX}"
echo "$IMAGE_TAG:${MAJOR}${PRE_RELEASE}${SUFFIX}"
echo "$IMAGE_TAG:${MAJOR}.${MINOR}${PRE_RELEASE}${SUFFIX}"
echo "$IMAGE_TAG:${MAJOR}.${MINOR}.${PATCH}${PRE_RELEASE}${SUFFIX}"
echo "$IMAGE_TAG:${MAJOR}.${MINOR}.${PATCH}${PRE_RELEASE}${SUFFIX}-${GIT_REVISION}"
echo
done
exit 0
fi
# build the --tag args for the build command
TAGS=
for IMAGE in ${REPOS[@]}; do
TAGS+=" --tag $IMAGE:nightly"
test -z "$PRE_RELEASE" && TAGS+=" --tag $IMAGE:latest${SUFFIX}" # only latest if we haven't a pre-release
TAGS+=" --tag $IMAGE:${MAJOR}${PRE_RELEASE}${SUFFIX}"
TAGS+=" --tag $IMAGE:${MAJOR}.${MINOR}${PRE_RELEASE}${SUFFIX}"
TAGS+=" --tag $IMAGE:${MAJOR}.${MINOR}.${PATCH}${PRE_RELEASE}${SUFFIX}"
TAGS+=" --tag $IMAGE:${MAJOR}.${MINOR}.${PATCH}${PRE_RELEASE}${SUFFIX}-${GIT_REVISION}"
done
docker build $TAGS \
--build-arg VERSION="$VERSION" \
--build-arg GIT_REVISION="$GIT_REVISION" \
--build-arg DATE="$(date +%Y-%m-%dT%H:%M:%S%z)" .
if [[ $? == 0 ]] && [[ "$RELEASE" == "true" ]]; then
for IMAGE_TAG in ${REPOS[@]}; do
docker push "$IMAGE_TAG:nightly"
test -z "$PRE_RELEASE" && docker push "$IMAGE_TAG:latest${SUFFIX}" # only latest if we haven't a pre-release
docker push "$IMAGE_TAG:${MAJOR}${PRE_RELEASE}${SUFFIX}"
docker push "$IMAGE_TAG:${MAJOR}.${MINOR}${PRE_RELEASE}${SUFFIX}"
docker push "$IMAGE_TAG:${MAJOR}.${MINOR}.${PATCH}${PRE_RELEASE}${SUFFIX}"
docker push "$IMAGE_TAG:${MAJOR}.${MINOR}.${PATCH}${PRE_RELEASE}${SUFFIX}-${GIT_REVISION}"
done
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment