Skip to content

Instantly share code, notes, and snippets.

@wrouesnel
Created October 5, 2023 21:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wrouesnel/bfd8cebc4238c83be2ba78d46b579594 to your computer and use it in GitHub Desktop.
Save wrouesnel/bfd8cebc4238c83be2ba78d46b579594 to your computer and use it in GitHub Desktop.
Bash script to build and tag containers in Gitlab
#!/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