#!/bin/sh

# Usage:
#
#  ./images-manifest BRANCH DOCKERFILE1 [DOCKERFILE2 ...]
#
# Create a new manifest list (fat manifest) containing the images built with
# “images-build”, whether in this pipeline or previously, tagged with the Git
# branch.
#
# This is needed because there is no way (that I could figure out) to push a
# multi-arch image without the architectures racing. So we build and push the
# images with their (skinny) manifests, then after all architectures are done,
# run this script to set up the manifest lists. We do this unconditionally
# because it’s relatively quick and then we don’t need to match any existing
# state.
#
# Note that commits within the same branch still race (see #1981), but that
# seemed hard to fix and thus acceptable.

set -e  # needs to be POSIX so can’t use our fancy traps

# Add directory containing script to PATH so it doesn’t yell about arch.sh and
# friends during manual testing.
PATH=$(cd "$(dirname "$0")" && pwd):$PATH
export PATH

. images.sh

branch=$1
shift
echo "branch:        $branch" 1>&2

for df in "$@"; do

    echo
    echo "file:          $df" 1>&2
    name=$(tag_from_filename "$df")
    echo "image name:    $name" 1>&2

    refs=''
    for arch in amd64 arm64; do
        echo "arch:          $arch"
        digest=$(fulldigest "$arch" "$df")
        echo "  digest:      $digest" 1>&2
        ref=$regy/$name:$digest
        #echo "  ref:         $ref" 1>&2
        printf '  in registry: ' 1>&2
        if registry_exists "$ref"; then
            echo 'yes' 1>&2
            refs="$refs $ref"
        else
            echo "no, skipping" 1>&2
        fi
    done

    echo 1>&2
    ref_branch=$regy/$name:$branch
    ref_latest=$regy/$name:latest
    if [ "$refs" = '' ]; then
        # Nothing to put in a new manifest list, and we cannot create an empty
        # one (thanks OCI!).
        echo 'NOTE: No registry images to put in manifest list.' 1>&2
        # Deleting an existing stale manifest list is hairy (you have to use
        # GitLab APIs and the Docker image has no tool that can send HTTP
        # DELETE), so just warn and YOLO.
        if docker buildx imagetools inspect "$ref_branch" 1>&2; then
            echo 1>&2
            echo 'WARNING: Found stale manifest list; do not use it.' 1>&2
            echo 1>&2
        fi
    else
        # We also push the “latest” tag because various things keep using it.
        # Anything that cares about its content should definitely use the
        # branch-specific tag.
        for ref in "$ref_branch" "$ref_latest"; do
            # Write new manifest list, replacing any existing list.
            # shellcheck disable=SC2086  # POSIX sh has no arrays
            docker buildx imagetools create $refs --tag "$ref" 1>&2
            docker buildx imagetools inspect "$ref" 1>&2
        done
    fi

done
