Created
October 5, 2023 21:11
-
-
Save wrouesnel/bfd8cebc4238c83be2ba78d46b579594 to your computer and use it in GitHub Desktop.
Bash script to build and tag containers in Gitlab
This file contains 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 | |
# Script to build a container from common gitlab CI parameters. | |
declare -a logstack | |
function log() { | |
echo -e "\033[0;93m$*\e[0m" | |
} | |
function glog() { | |
echo -e "\033[1;92m$*\e[0m" | |
} | |
function rlog() { | |
echo -e "\033[1;31m$*\e[0m" | |
} | |
function fatal() { | |
rlog "$*" | |
exit 1 | |
} | |
function pushlog() { | |
logstack+=( "$1" ) | |
local collapsed | |
collapsed=false | |
if [ -n "$2" ]; then | |
collapsed="true" | |
fi | |
printf "\e[0Ksection_start:%s:section_%s[collapsed=%s]\r\e[0K%s\n" "$(date +%s)" "${#logstack[@]}" "$collapsed" "$1" | |
} | |
function poplog() { | |
printf "section_end:%s:section_%s\r\e[0K" "$(date +%s)" "${#logstack[@]}" | |
unset "logstack[-1]" | |
} | |
pushlog "Execution Info" true | |
pushlog "Environment" | |
id || true | |
pwd || true | |
mount || true | |
uname -a || true | |
poplog | |
pushlog "CPU Info" | |
cat /proc/cpuinfo || true | |
poplog | |
pushlog "Limits Info" | |
ulimit -a || true | |
poplog | |
pushlog "Tool Info" | |
capsh --print || true | |
poplog | |
pushlog "Buildah Info" | |
buildah version || true | |
buildah info || true | |
poplog | |
pushlog "Podman Info" | |
podman version || true | |
podman info || true | |
poplog | |
pushlog "Skopeo Info" | |
skopeo --version || true | |
poplog | |
poplog | |
if [ -z "$REGISTRY_HOST" ] || [ -z "$REGISTRY_PREFIX" ]; then | |
fatal "Refusing to proceed without REGISTRY_HOST and REGISTRY_PREFIX" | |
fi | |
if [ -z "$CI_PROJECT_NAME" ]; then | |
export CI_PROJECT_NAME | |
if ! CI_PROJECT_NAME="$(basename $(pwd))"; then | |
fatal "Could not determine a project name" | |
fi | |
fi | |
if [ -z "$CI_COMMIT_SHA" ]; then | |
export CI_COMMIT_SHA | |
if ! CI_COMMIT_SHA="$(git rev-parse HEAD)"; then | |
unset CI_COMMIT_SHA | |
fi | |
fi | |
if [ -z "$CI_COMMIT_SHORT_SHA" ]; then | |
export CI_COMMIT_SHORT_SHA | |
if ! CI_COMMIT_SHORT_SHA="$(git rev-parse HEAD | cut -c-7)"; then | |
unset CI_COMMIT_SHORT_SHA | |
fi | |
fi | |
if [ ! -z "$CI_PROJECT_OVERRIDE" ]; then | |
export IMAGE_PATH="${REGISTRY_HOST}/${REGISTRY_PREFIX}/${CI_PROJECT_OVERRIDE}" | |
else | |
export IMAGE_PATH="${REGISTRY_HOST}/${REGISTRY_PREFIX}/${CI_PROJECT_NAME}" | |
fi | |
if [ ! -z "$IMAGE_NAME" ]; then | |
export IMAGE_PATH="${IMAGE_PATH}/${IMAGE_NAME}" | |
fi | |
if [ -z "$DOCKER_BUILD_FILE" ]; then | |
export DOCKER_BUILD_FILE="Dockerfile" | |
fi | |
if [ -z "$DOCKER_BUILD_DIR" ]; then | |
export DOCKER_BUILD_DIR="." | |
fi | |
glog "Base Image Path: $IMAGE_PATH" | |
_build_tag_file=$(mktemp) | |
_build_iid_file=$(mktemp) | |
log "Determining tags to apply" | |
if [ ! -z "$CI_COMMIT_SHORT_SHA" ]; then | |
echo "${IMAGE_PATH}:sha-${CI_COMMIT_SHORT_SHA}${TAG_SUFFIX}" >> "${_build_tag_file}" | |
fi | |
if [ ! -z "$CI_COMMIT_SHA" ]; then | |
echo "${IMAGE_PATH}:sha-${CI_COMMIT_SHA}${TAG_SUFFIX}" >> "${_build_tag_file}" | |
fi | |
if [ ! -z "$CI_BUILD_TAG" ]; then | |
echo "${IMAGE_PATH}:$(printenv CI_BUILD_TAG | tr -s '/' '-')${TAG_SUFFIX}" >> "${_build_tag_file}" | |
fi | |
if [ ! -z "$CI_COMMIT_BRANCH" ]; then | |
echo "${IMAGE_PATH}:branch-$(printenv CI_COMMIT_BRANCH | tr -s '/' '-')${TAG_SUFFIX}" >> "${_build_tag_file}" | |
fi | |
if [ "$CI_DEFAULT_BRANCH" = "$CI_COMMIT_BRANCH" ]; then | |
echo "${IMAGE_PATH}:latest${TAG_SUFFIX}" >> "${_build_tag_file}" | |
fi | |
log "Build Tags to Output" | |
while read -r tag; do | |
glog "$tag" | |
done < "${_build_tag_file}" | |
# Configure labelling | |
declare -A labelling | |
# Add the Dockerfile as a label | |
labelling["Dockerfile"]="$(cat "$DOCKER_BUILD_FILE")" | |
#org.opencontainers.artifact.created | |
#org.opencontainers.artifact.description | |
labelling["org.opencontainers.image.created"]="$(date --rfc-3339=seconds | sed 's/ /T/')" | |
labelling["org.opencontainers.image.authors"]="Private Developers <root@localhost>" | |
# org.opencontainers.image.url | |
# org.opencontainers.image.documentation | |
if [ ! -z "$CI_PROJECT_URL" ]; then | |
labelling["org.opencontainers.image.source"]="$CI_PROJECT_URL" | |
fi | |
if [ ! -z "$CI_COMMIT_TAG" ]; then | |
labelling["org.opencontainers.image.version"]="$CI_COMMIT_TAG" | |
fi | |
if [ ! -z "$CI_COMMIT_SHA" ]; then | |
labelling["org.opencontainers.image.revision"]="$CI_COMMIT_SHA" | |
fi | |
labelling["org.opencontainers.image.vendor"]="Private" | |
labelling["org.opencontainers.image.licenses"]="Proprietary" | |
#org.opencontainers.image.ref.name | |
if [ ! -z "${CI_PROJECT_TITLE}" ]; then | |
labelling["org.opencontainers.image.title"]="${CI_PROJECT_TITLE}" | |
fi | |
if [ ! -z "${CI_PROJECT_DESCRIPTION}" ]; then | |
labelling["org.opencontainers.image.description"]="$CI_PROJECT_DESCRIPTION" | |
fi | |
log "Will set labels on image:" | |
declare -a _labelling | |
for key in "${!labelling[@]}"; do | |
log "${key}=\"${labelling[$key]}\"" | |
_labelling+=( "--label" "${key}=${labelling[$key]}" ) | |
done | |
# org.opencontainers.image.base.digest | |
# org.opencontainers.image.base.name | |
#org.opencontainers.referrers.filtersApplied | |
# Configure image arguments | |
declare -A build_args | |
while read -r build_arg; do | |
key="${build_arg%%=*}" | |
value="${build_arg#*"="}" | |
build_args["${key#BUILDARG_}"]="$value" | |
done < <(env | grep '^BUILDARG_') | |
log "Will pass build args to image:" | |
declare -a _buildargs | |
for key in "${!build_args[@]}"; do | |
log "${key}=\"${build_args[$key]}\"" | |
_buildargs+=( "--build-arg" "${key}=${build_args[$key]}" ) | |
done | |
pushlog "Logging in to registry" true | |
if ! buildah login --get-login "${REGISTRY_HOST}"; then | |
if ! printenv REGISTRY_PASSWORD | buildah login -v -u "$(printenv REGISTRY_USERNAME)" --password-stdin "${REGISTRY_HOST}"; then | |
fatal "Failed to login to Harbor: ${REGISTRY_HOST} as $REGISTRY_USERNAME" | |
fi | |
fi | |
poplog | |
pushlog "Executing the build" | |
log "Dockerfile: ${DOCKER_BUILD_FILE}" | |
log "Context Dir: ${DOCKER_BUILD_DIR} " | |
if ! buildah build \ | |
"--ulimit=nofile=$(ulimit -S -n):$(ulimit -H -n)" \ | |
--pull-always \ | |
--iidfile "${_build_iid_file}" \ | |
--file "${DOCKER_BUILD_FILE}" \ | |
--label - "${_labelling[@]}" "${_buildargs[@]}" "${DOCKER_BUILD_DIR}"; then | |
fatal "Container Build Failed: ${DOCKER_BUILD_FILE} ${DOCKER_BUILD_DIR}" | |
fi | |
pushlog "Tagging images" | |
while read -r tag ; do | |
if ! buildah tag "$(cat "${_build_iid_file}")" "${tag}"; then | |
fatal "Error tagging images" | |
fi | |
done < "$_build_tag_file" | |
poplog | |
pushlog "Pushing to repository" | |
_pushed_digests=$(mktemp) | |
_artifact_file="${CI_PROJECT_DIR}/.images.yml" | |
_digest_dir="${CI_PROJECT_DIR}/.digests" | |
mkdir -p "${_digest_dir}" || fatal "Could not make .digests directory" | |
while read -r tag ; do | |
_digestfile=$(mktemp) | |
if ! skopeo copy --digestfile "${_digestfile}" containers-storage:"$(cut -d':' -f2 < "${_build_iid_file}")" "docker://${tag}"; then | |
fatal "Error pushing tag to repository: ${tag}" | |
fi | |
echo "\"${tag}\": \"$(cat "$_digestfile")\"" >> "${_artifact_file}" | |
cat "$_digestfile" > "${_digest_dir}/$(echo "${tag}" | rev | cut -d':' -f1 | rev)" | |
done < "$_build_tag_file" | |
poplog | |
glog "Pushed Digests" | |
while read -r line ; do | |
glog "$line" | |
done < "${_artifact_file}" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment