diff --git a/scripts/docker-library-build.sh b/scripts/docker-library-build.sh index 24fa2289..16d220a3 100755 --- a/scripts/docker-library-build.sh +++ b/scripts/docker-library-build.sh @@ -33,6 +33,7 @@ commit=${4:-0} branch=${5:-${master_branch}} artifacts_url=${ARTIFACTS_URL:-https://ci.mariadb.org} + # keep in sync with docker-cleanup script if [[ $branch =~ ^preview ]]; then container_tag=${branch#preview-} @@ -45,6 +46,7 @@ fi # Container tags must be lower case. container_tag=${container_tag,,*} ubi= +arches=( linux/amd64 linux/arm64/v8 linux/ppc64le linux/s390x ) case "${buildername#*ubuntu-}" in 2404-deb-autobake) @@ -58,6 +60,8 @@ case "${buildername#*ubuntu-}" in ;; *-rhel-9-rpm-autobake) ubi=-ubi + # first arch only + arches=( linux/amd64 ) master_branch=${master_branch}-ubi ;; *) @@ -66,8 +70,30 @@ case "${buildername#*ubuntu-}" in ;; esac -builderarch=${buildername%%-*} +image=mariadb-${tarbuildnum}${ubi} + +# keep a count of architectures that have reached this step +# and only build once they are all here. + +# UBI for the moment only triggers on one arch +reffile="${container_tag}-${tarbuildnum}${ubi}-reference.txt" + +# ensure unique entries for each arch +echo "$buildername" >> "$reffile" +sort -u "$reffile" -o "$reffile" + +entries=$(wc -l < "$reffile") +if [ "$entries" -lt ${#arches[@]} ]; then + echo "Only $entries architectures so far" + exit +fi + +# Don't remove file here. Leave a manual retrigger of +# any build of the same tarbuildnum / ubi there to redo +# start the rebuild, without the server rebuild. +# rm "$reffile" +# Annotations - https://github.com/opencontainers/image-spec/blob/main/annotations.md#pre-defined-annotation-keys declare -a annotations=( "--annotation" "org.opencontainers.image.authors=MariaDB Foundation" "--annotation" "org.opencontainers.image.documentation=https://hub.docker.com/_/mariadb" @@ -87,49 +113,81 @@ annotate() { done } -image=mariadb-${tarbuildnum}-${builderarch}$ubi -if [ -n "$ubi" ] -then +# +# BUILD Image +# +builder_noarch=${buildername#*-} -build() { - local repo="mariadb-docker/$master_branch"/MariaDB.repo - curl "$artifacts_url"/galera/mariadb-4.x-latest-gal-"${buildername%-rpm-autobake}".repo \ - -o "$repo" - curl "$artifacts_url/$tarbuildnum/${buildername}"/MariaDB.repo \ - >> "$repo" - buildah bud --tag "${image}" \ - --layers \ - --arch "$@" \ - --build-arg MARIADB_VERSION="$mariadb_version" \ - "${annotations[@]}" \ - "mariadb-docker/$master_branch" -} +galera_distro=${buildername%-*-autobake} +galera_distro_noarch=${galera_distro#*-} -else -# Annotations - https://github.com/opencontainers/image-spec/blob/main/annotations.md#pre-defined-annotation-keys build() { - local galera_repo - galera_repo="deb [trusted=yes] $(curl "$artifacts_url"/galera/mariadb-4.x-latest-gal-"${buildername%-deb-autobake}".sources | sed '/URIs: /!d ; s///;q') ./" - buildah bud --tag "${image}" \ + local arch=$1 + declare -a args + local bbarch=${arch#*/} + if [ "$bbarch" = arm64/v8 ]; then + bbarch=aarch64; + fi + if [ -n "$ubi" ] + then + local repo="mariadb-docker/$master_branch"/MariaDB.repo + curl "${artifacts_url}/galera/mariadb-4.x-latest-gal-${bbarch}-${galera_distro_noarch}".repo \ + -o "$repo" + curl "${artifacts_url}/$tarbuildnum/${bbarch}-${builder_noarch}"/MariaDB.repo \ + >> "$repo" + args=( --build-arg MARIADB_VERSION="$mariadb_version" ) + else + local galera_repo + galera_repo="deb [trusted=yes] $(curl "${artifacts_url}/galera/mariadb-4.x-latest-gal-${bbarch}-${galera_distro_noarch}.sources" | sed '/URIs: /!d ; s///;q') ./" + args=( + --build-arg REPOSITORY="[trusted=yes] ${artifacts_url}/${tarbuildnum}/${bbarch}-${builder_noarch}/debs ./\n$galera_repo" \ + --build-arg MARIADB_VERSION="1:$mariadb_version+maria~$pkgver" ) + fi + buildah bud --tag "${image}-${arch}" \ --layers \ - --arch "$@" \ - --build-arg REPOSITORY="[trusted=yes] $artifacts_url/$tarbuildnum/${buildername}/debs ./\n$galera_repo" \ - --build-arg MARIADB_VERSION="1:$mariadb_version+maria~$pkgver" \ + --platform "$arch" \ + "${args[@]}" \ "${annotations[@]}" \ - "mariadb-docker/$master_branch" + "mariadb-docker/$master_branch" } -fi +## Because our repos aren't multiarch, or paramitizable by $TARGET_ARCH, we do it separately +## +## intentionally array to simple +## shellcheck disable=SC2124 +#archlist="${arches[@]}" # -# BUILD Image +## comma separated +#archlist=${archlist// /,} +#buildah bud --manifest "${image}" \ +# --jobs 4 \ +# --layers \ +# --platform "${archlist}" \ +# "${args[@]}" \ +# "${annotations[@]}" \ +# "mariadb-docker/$master_branch" + +buildah manifest rm "$image" || echo "already not there" + +cleanup() +{ + buildah manifest rm "$image" || echo "already gone" + for arch in "${arches[@]}"; do + # -f will remove all tags of same, like wordpress + buildah rmi -f "${image}-${arch}" || echo "already gone" + done + buildah rmi --prune --force +} -if [ "${builderarch}" = aarch64 ]; then - build arm64 --variant v8 -else - build "${builderarch}" -fi +trap cleanup ERR -if [ "${builderarch}" = amd64 ]; then - podman tag "${image}" "${image}-wordpress" -fi +buildah manifest create "$image" + +for arch in "${arches[@]}"; do + build "$arch" + buildah manifest add "$image" "$image-$arch" + if [ "$arch" = amd64 ]; then + buildah tag "${image}-${arch}" "${image}-wordpress" + fi +done diff --git a/scripts/docker-library-manifest.sh b/scripts/docker-library-manifest.sh index 005f3471..8364faff 100755 --- a/scripts/docker-library-manifest.sh +++ b/scripts/docker-library-manifest.sh @@ -7,11 +7,12 @@ mariadb_version=${2} mariadb_version=${mariadb_version#*-} buildername=${3:-amd64-ubuntu-2004-deb-autobake} master_branch=${mariadb_version%\.*} -commit=${4:-0} +#commit=${4:-0} branch=${5:-${master_branch}} prod_environment=${6:-True} rm -f last_tag + # keep in sync with docker-cleanup script if [[ $branch = *pkgtest* ]]; then container_tag=${branch#bb-} @@ -30,194 +31,156 @@ fi # Container tags must be lower case. container_tag=${container_tag,,*}${ubi} -builderarch=${buildername%%-*} - - -declare -a annotations=( - "--annotation" "org.opencontainers.image.authors=MariaDB Foundation" - "--annotation" "org.opencontainers.image.documentation=https://hub.docker.com/_/mariadb" - "--annotation" "org.opencontainers.image.source=https://github.com/MariaDB/mariadb-docker/tree/$( - cd "mariadb-docker/$master_branch" - git rev-parse HEAD - )/$master_branch" - "--annotation" "org.opencontainers.image.licenses=GPL-2.0" - "--annotation" "org.opencontainers.image.title=MariaDB Server $container_tag CI build" - "--annotation" "org.opencontainers.image.description=This is not a Release.\nBuild of the MariaDB Server from CI as of commit $commit" - "--annotation" "org.opencontainers.image.version=$mariadb_version+$commit" - "--annotation" "org.opencontainers.image.revision=$commit") - -annotate() { - for item in "${annotations[@]}"; do - echo " --annotation" \""$item"\" - done -} +image=mariadb-${tarbuildnum}${ubi} + +# keep a count of architectures that have reached this step +# and only build once they are all here. -image=mariadb-${tarbuildnum}-${builderarch}${ubi} +if ! buildah manifest exists "$image"; then + echo "No manifest we can't push" + exit +fi # -# METADATA: +# Dev manifest is already made +# -# Add manifest file of version and fix mariadb version in the configuration -# because otherwise 'buildah manifest add "$devmanifest" "$image"' would be sufficient +devmanifest=$image -container=$(buildah from "$image") -manifestfile=$(mktemp) -for item in "${annotations[@]}"; do - [ "$item" != "--annotation" ] && echo -e "$item\n" -done >"$manifestfile" -buildah copy --add-history "$container" "$manifestfile" /manifest.txt -rm -f "$manifestfile" # -# MAKE it part of the mariadb-devel manifest +# PUSHIT - if the manifest if complete, i.e. all supported arches are there, we push # +if [ -n "$ubi" ]; then + arches=( linux/amd64 ) +else + arches=( linux/amd64 linux/arm64/v8 linux/ppc64le linux/s390x ) +fi + +manifest_image_cleanup() { + local manifest=$1 + buildah manifest rm "$manifest" || echo "already removed" + + for arch in "${arches[@]}"; do + # -f will remove all tags of same, like wordpress + buildah rmi -f "${manifest}-${arch}" || echo "already gone" + done + buildah rmi --prune --force -buildmanifest() { - manifest=$1 - shift - container=$1 shift - # create a manifest, and if it already exists, remove the one for the - # current architecture as we're replacing this. - # This could happen due to triggered rebuilds on buildbot. - - buildah manifest create "$manifest" || buildah manifest inspect "$manifest" | - jq ".manifests[] | select( .platform.architecture == \"$builderarch\") | .digest" | - xargs --no-run-if-empty -n 1 buildah manifest remove "$manifest" - - t=$(mktemp) - buildah commit "$@" --iidfile "$t" --manifest "$manifest" "$container" - image=$(<"$t") - ##buildah push --rm "$image" "docker://quay.io/mariadb-foundation/${base}:${container_tag}-${builderarch}" && - ## buildah rmi "$image" - # $image is the wrong sha for annotation. Config vs Blog? - # Even below doesn't annotate manifest. Unknown reason, doesn't error - buildah manifest inspect "$manifest" | - jq ".manifests[] | select( .platform.architecture == \"$builderarch\") | .digest" | - xargs --no-run-if-empty -n 1 buildah manifest annotate \ - "${annotations[@]}" \ - "$manifest" + local t=$1 rm -f "$t" } -devmanifest=mariadb-devel-${container_tag}-$commit +t=$(mktemp) -trap 'buildah rm "$container"' EXIT -buildmanifest "$devmanifest" "$container" +# Anything fails, like the API, cleanup +trap 'manifest_image_cleanup "$devmanifest" "$t"' EXIT + +declare -A specialtags +if ! wget -nv https://downloads.mariadb.org/rest-api/mariadb/ -O "$t"; then + echo >&2 "Wget failed" +fi +if [ "$branch" = 'main' ]; then + specialtags['verylatest']=\"${container_tag}\" +else + specialtags['verylatest']=$(jq '.major_releases[0].release_id' <"$t") +fi +specialtags['latest']=$(jq '.major_releases | map(select(.release_status == "Stable"))[0].release_id' <"$t") +specialtags['latest-lts']=$(jq '.major_releases | map(select(.release_status == "Stable" and .release_support_type == "Long Term Support"))[0].release_id' <"$t") +specialtags['earliest']=$(jq '.major_releases | map(select( (( (.release_eol_date // "2031-01-01") + "T00:00:00Z") | fromdate) > now))[-1].release_id' <"$t") +specialtags['earliest-lts']=$(jq '.major_releases | map(select(.release_status == "Stable" and .release_support_type == "Long Term Support" and (( (.release_eol_date // "2031-01-01") + "T00:00:00Z") | fromdate) > now ))[-1].release_id' <"$t") +for tag in "${!specialtags[@]}"; do + if [ \""$container_tag"\" == "${specialtags[$tag]}" ]; then + if [ "$prod_environment" = "True" ]; then + buildah manifest push --all "$devmanifest" "docker://quay.io/mariadb-foundation/mariadb-devel:${tag}${ubi}" + else + echo "not pushing quay.io/mariadb-foundation/mariadb-devel:${tag}${ubi} as in DEV environment" + fi + fi +done +rm "$t" + +buildah manifest inspect "$devmanifest" | tee "${t}" +trap 'manifest_image_cleanup "$devmanifest" "$t"' EXIT + +if [ "$prod_environment" = "True" ]; then + buildah manifest push --all "$devmanifest" "docker://quay.io/mariadb-foundation/mariadb-devel:${container_tag}" + echo "${container_tag}" > last_tag +else + rm -f last_tag +fi # # MAKE Debug manifest -debugimage=mariadb-debug-${tarbuildnum}-${builderarch}${ubi} -buildah bud --tag "$debugimage" --build-arg BASE="$image" -f "mariadb-docker/Containerfile.debug$ubi" -container=$(buildah from "$debugimage") +debugmanifest=${image}-debug -debugmanifest=mariadb-debug-${container_tag}-$commit +# --all-platforms incompatible with --build-arg +# https://github.com/containers/buildah/issues/5850 +# buildah bud --all-platforms --jobs 4 --manifest "$debugmanifest" --build-arg BASE="$image" -f "mariadb-docker/Containerfile.debug$ubi" -buildmanifest "$debugmanifest" "$container" --rm -trap - EXIT -expected=4 +# Temp disable this as it also wasn't functioning +manifest_image_cleanup "$devmanifest" "$t" +if false; then +## intentionally array to simple +# shellcheck disable=SC2124 +archlist="${arches[@]}" +# comma separated +archlist=${archlist// /,} +buildah bud --platform "${archlist}" --jobs 4 --manifest "$debugmanifest" --build-arg BASE="$image" -f "mariadb-docker/Containerfile.debug$ubi" -if [ -n "$ubi" ]; then - expected=1 +# now $debugmanifest is build, we can cleanup $devmanifest +manifest_image_cleanup "$devmanifest" "$t" + +buildah manifest inspect "$debugmanifest" + +if [ "$prod_environment" = "True" ]; then + buildah manifest push --all --rm "$debugmanifest" "docker://quay.io/mariadb-foundation/mariadb-debug:${container_tag}" +else + buildah manifest rm "$debugmanifest" fi -# -# -# PUSHIT - if the manifest if complete, i.e. all supported arches are there, we push -# +# end of broken debug container build +fi -manifest_image_cleanup() { - local manifest=$1 - shift - local t=$1 - if [ ! -f "$t" ]; then - return - fi - buildah manifest rm "$manifest" || echo "already removed" - for arch in amd64 ppc64le s390x aarch64; do - buildah rm "mariadb-${tarbuildnum}-${arch}${ubi}" || echo 'trouble removing this image' - buildah rm "mariadb-debug-${tarbuildnum}-${arch}${ubi}" || echo 'trouble removing this image' - done - rm -f "$t" -} +# all untagged images removed, and any containers that might be running on them +buildah rmi --prune --force -if (($(buildah manifest inspect "$devmanifest" | jq '.manifests | length') >= expected)); then - t=$(mktemp) +# Delete old reference files +find . -name \*reference.txt -type f -mtime +7 -delete - declare -A specialtags - if ! wget -nv https://downloads.mariadb.org/rest-api/mariadb/ -O "$t"; then - echo >&2 "Wget failed" - fi - if [ "$branch" = 'main' ]; then - specialtags['verylatest']=\"${container_tag}\" - else - specialtags['verylatest']=$(jq '.major_releases[0].release_id' <"$t") - fi - specialtags['latest']=$(jq '.major_releases | map(select(.release_status == "Stable"))[0].release_id' <"$t") - specialtags['latest-lts']=$(jq '.major_releases | map(select(.release_status == "Stable" and .release_support_type == "Long Term Support"))[0].release_id' <"$t") - specialtags['earliest']=$(jq '.major_releases | map(select( (( (.release_eol_date // "2031-01-01") + "T00:00:00Z") | fromdate) > now))[-1].release_id' <"$t") - specialtags['earliest-lts']=$(jq '.major_releases | map(select(.release_status == "Stable" and .release_support_type == "Long Term Support" and (( (.release_eol_date // "2031-01-01") + "T00:00:00Z") | fromdate) > now ))[-1].release_id' <"$t") - for tag in "${!specialtags[@]}"; do - if [ \""$container_tag"\" == "${specialtags[$tag]}" ]; then - if [ "$prod_environment" = "True" ]; then - buildah manifest push --all "$devmanifest" "docker://quay.io/mariadb-foundation/mariadb-devel:${tag}${ubi}" - else - echo "not pushing quay.io/mariadb-foundation/mariadb-devel:${tag}${ubi} as in DEV environment" - fi - fi - done - rm "$t" - - buildah manifest inspect "$devmanifest" | tee "${t}" - trap 'manifest_image_cleanup "$devmanifest" "$t"' EXIT - if [ "$prod_environment" = "True" ]; then - buildah manifest push --all --rm "$devmanifest" "docker://quay.io/mariadb-foundation/mariadb-devel:${container_tag}" - echo "${container_tag}" > last_tag - else - rm -f last_tag - fi - manifest_image_cleanup "$devmanifest" "$t" +buildah images +# lost and forgotten (or just didn't make enough manifest items - build failure on an arch) +lastweek=$(date +%s --date='1 week ago') +# note - jq args are treated as strings and need to be cast tonumber to make the value comparable. + +# clear buildah images +buildah images --json | + jq --arg lastweek "$lastweek" '.[] | select(.created <= ( $lastweek | tonumber ) and any( .names[]? ; startswith("localhost/mariadb")) ) | .id' | + xargs --no-run-if-empty buildah rmi --force || echo "had trouble removing buildah images" + +# old ubuntu and base images that got updated so are Dangling +podman images --format=json | + jq --arg lastweek "$lastweek" '.[] | select(.Created <= ( $lastweek | tonumber ) and .Dangling? ) | .Id' | + xargs --no-run-if-empty podman rmi --force || echo "continuing cleanup anyway" + +# clean buildah containers (nothing should be running) +buildah containers --format "{{.ContainerID}}" | xargs --no-run-if-empty buildah rm || echo "had trouble cleaning containers" + +# clean images +buildah images --json | + jq --arg lastweek "$lastweek" '.[] | select(.readonly ==false and .created <= ( $lastweek | tonumber ) and .names == null) | .id' | + xargs --no-run-if-empty buildah rmi || echo "had trouble cleaning images" + +# clean manifests +buildah images --json | + jq --arg lastweek "$lastweek" '.[] | select(.readonly ==false and .created <= ( $lastweek | tonumber ) and ( try .names[0]? catch "" | startswith("localhost/mariadb-") )) | .id' | + xargs --no-run-if-empty buildah manifest rm || echo "trouble cleaning manifests" + +# what's left? +buildah images - t=$(mktemp) - buildah manifest inspect "$debugmanifest" | tee "${t}" - trap 'manifest_image_cleanup "$debugmanifest" "$t"' EXIT - if [ "$prod_environment" = "True" ]; then - buildah manifest push --all --rm "$debugmanifest" "docker://quay.io/mariadb-foundation/mariadb-debug:${container_tag}" - fi - manifest_image_cleanup "$debugmanifest" "$t" - - buildah images - # lost and forgotten (or just didn't make enough manifest items - build failure on an arch) - lastweek=$(date +%s --date='1 week ago') - # note - jq args are treated as strings and need to be cast tonumber to make the value comparable. - - # clear buildah images - buildah images --json | - jq --arg lastweek "$lastweek" '.[] | select(.created <= ( $lastweek | tonumber ) and any( .names[]? ; startswith("localhost/mariadb")) ) | .id' | - xargs --no-run-if-empty buildah rmi --force || echo "had trouble removing buildah images" - - # old ubuntu and base images that got updated so are Dangling - podman images --format=json | - jq --arg lastweek "$lastweek" '.[] | select(.Created <= ( $lastweek | tonumber ) and .Dangling? ) | .Id' | - xargs --no-run-if-empty podman rmi --force || echo "continuing cleanup anyway" - - # clean buildah containers (nothing should be running) - buildah containers --format "{{.ContainerID}}" | xargs --no-run-if-empty buildah rm || echo "had trouble cleaning containers" - - # clean images - buildah images --json | - jq --arg lastweek "$lastweek" '.[] | select(.readonly ==false and .created <= ( $lastweek | tonumber ) and .names == null) | .id' | - xargs --no-run-if-empty buildah rmi || echo "had trouble cleaning images" - - # clean manifests - buildah images --json | - jq --arg lastweek "$lastweek" '.[] | select(.readonly ==false and .created <= ( $lastweek | tonumber ) and ( try .names[0]? catch "" | startswith("localhost/mariadb-") )) | .id' | - xargs --no-run-if-empty buildah manifest rm || echo "trouble cleaning manifests" - - # what's left? - buildah images -fi trap - EXIT diff --git a/scripts/docker-library-test.sh b/scripts/docker-library-test.sh index 98c10d98..a93207c8 100755 --- a/scripts/docker-library-test.sh +++ b/scripts/docker-library-test.sh @@ -7,11 +7,16 @@ buildername=${2} builderarch=${buildername%%-*} -image=mariadb-${tarbuildnum}-${builderarch} +image=mariadb-${tarbuildnum} + if [[ "$buildername" = *-rhel-9-rpm-autobake ]]; then image=${image}-ubi fi +if ! buildah manifest exists "$image"; then + echo "No manifest we can't test" + exit +fi # # TEST Image #