Last active
March 10, 2023 19:41
-
-
Save shanduur/1aa06b85e2f6f061393a05ed940da4e5 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash -e | |
echo 'This script is used to build and push multi-arch images to a container registry.' | |
echo '' | |
echo 'The script is intended to be used in a CI/CD pipeline.' | |
echo '' | |
echo 'The following variables can be set:' | |
echo '' | |
echo '| variable | value | default value | required |' | |
echo '|----------------|---------------------------------------------------|-------------------------------|-----------------------------|' | |
echo '| EXECUTOR | podman or docker | podman or docker if available | optional |' | |
echo '| REGISTRY | docker.io, quay.io, ... | docker.io | optional |' | |
echo '| REPOSITORY | e.g. example-project | not set | required |' | |
echo '| IMAGE_NAME | e.g. example | not set | required |' | |
echo '| IMAGE_TAG | e.g. v1.0.0 | latest commit sha | optional |' | |
echo '| GIT_SHA | e.g. 1234567890abcdef | latest commit sha | required, if git is missing |' | |
echo '| CONTEXT | e.g. ./example | . | optional |' | |
echo '| CONTAINERFILE | e.g. ./example/Dockerfile | Dockerfile | optional |' | |
echo '| PUSH | if set, the image will be pushed to the registry | not set | optional |' | |
echo '| ROBOT_USERNAME | username for the registry | not set | required, if PUSH is set |' | |
echo '| ROBOT_PASSWORD | password for the registry | not set | required, if PUSH is set |' | |
echo '| DEBUG | if set, the script will be executed in debug mode | not set | optional |' | |
echo '' | |
echo 'All arguments after the first one will be passed to the build command as build-args.' | |
echo 'They should be in the format: ARG=VALUE' | |
echo '' | |
echo 'example: ./build.sh ARG1=VALUE1 ARG2=VALUE2' | |
echo '' | |
echo "starting build" | |
# Validate if required variables are set | |
if [[ -z "${EXECUTOR}" ]]; then | |
echo "EXECUTOR not set" | |
if which podman ; then | |
echo "using podman as EXECUTOR" | |
EXECUTOR=$(which podman) | |
elif which docker ; then | |
echo "using docker as EXECUTOR" | |
EXECUTOR=$(which docker) | |
else | |
echo "no executor found on the system" | |
exit 1 | |
fi | |
fi | |
if [[ -n "${DEBUG}" ]]; then | |
set -x | |
if [[ "${EXECUTOR}" == "podman" ]]; then | |
EXTRA_FLAGS=(--log-level=debug) | |
fi | |
fi | |
if [[ -z "${GIT_SHA}" ]]; then | |
GIT_SHA=$(git rev-parse HEAD) | |
fi | |
if [[ -z "${REGISTRY}" ]]; then | |
echo "REGISTRY not set" | |
echo "using docker.io" | |
REGISTRY='docker.io' | |
fi | |
if [[ -z "${REPOSITORY}" ]]; then | |
echo "REPOSITORY not set" | |
exit 1 | |
fi | |
if [[ -z "${IMAGE_NAME}" ]]; then | |
echo "IMAGE_NAME not set" | |
exit 1 | |
fi | |
# combine variables to easier refer to the image | |
IMAGE="${REGISTRY}"/"${REPOSITORY}"/"${IMAGE_NAME}" | |
if [[ -z "${IMAGE_TAG}" ]]; then | |
echo "IMAGE_TAG not set" | |
echo "tagging '${GIT_SHA}'" | |
IMAGE_TAG="${GIT_SHA}" | |
else | |
# validate if the tag is correct SEMVER without additional info | |
if [[ "${IMAGE_TAG}" =~ ^v(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$ ]]; then | |
LATEST=1 | |
fi | |
fi | |
if [[ -z "${CONTEXT}" ]]; then | |
echo "CONTEXT not set" | |
echo "using '.'" | |
CONTEXT='.' | |
fi | |
if [[ -z "${CONTAINERFILE}" ]]; then | |
echo "CONTAINERFILE not set" | |
echo "using 'Dockerfile'" | |
CONTAINERFILE='Dockerfile' | |
fi | |
BUILD_ARGS=() | |
for ARG in "${@}"; do | |
# add args to list | |
BUILD_ARGS+=("--build-arg=${ARG}") | |
done | |
for ARCH in amd64 arm64; do | |
"${EXECUTOR}" build \ | |
--tag="${IMAGE}":"${GIT_SHA}"-"${ARCH}" \ | |
--platform="linux/${ARCH}" \ | |
--file "${CONTAINERFILE}" \ | |
"${BUILD_ARGS[@]}" \ | |
--pull \ | |
--rm \ | |
"${EXTRA_FLAGS[@]}" \ | |
"${CONTEXT}" | |
done | |
if [[ -n "${PUSH}" ]]; then | |
# Login into the container registry: | |
"${EXECUTOR}" login \ | |
"${EXTRA_FLAGS[@]}" \ | |
--username "${ROBOT_USERNAME}" \ | |
--password "${ROBOT_PASSWORD}" \ | |
"${REGISTRY}" | |
# Set manifest name | |
export MANIFEST_NAME="${IMAGE}":"${IMAGE_TAG}" | |
MANIFESTS=() | |
for ARCH in amd64 arm64; do | |
MANIFESTS+=("${IMAGE}":"${GIT_SHA}"-"${ARCH}") | |
done | |
# Create a multi-architecture manifest | |
if ! "${EXECUTOR}" manifest create --amend "${MANIFEST_NAME}" "${MANIFESTS[@]}"; then | |
echo "creation of manifest failed" | |
exit 1 | |
fi | |
for ARCH in amd64 arm64; do | |
"${EXECUTOR}" manifest add \ | |
"${EXTRA_FLAGS[@]}" \ | |
"${MANIFEST_NAME}" \ | |
"${IMAGE}":"${GIT_SHA}"-"${ARCH}" | |
done | |
# Push the full manifest, with all CPU Architectures, with IMAGE_TAG tag | |
"${EXECUTOR}" manifest push \ | |
--all \ | |
"${EXTRA_FLAGS[@]}" \ | |
"${MANIFEST_NAME}" \ | |
docker://"${IMAGE}":"${IMAGE_TAG}"; | |
if [[ -n "${LATEST}" ]]; then | |
# Push the full manifest, with all CPU Architectures, with latest tag | |
"${EXECUTOR}" manifest push \ | |
--all \ | |
"${EXTRA_FLAGS[@]}" \ | |
"${MANIFEST_NAME}" \ | |
docker://"${IMAGE}":latest; | |
fi | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment