#!/bin/bash

##
# Docker image build and publish script. 
#
# We use getoptions to manage the options for this script
# See: https://github.com/ko1nksm/getoptions
#
# To regenerate the options for this script please run:
#
#    $ gengetoptions embed --overwrite publish-docker-containers.sh
##

set -euxo pipefail

VERSION="0.1.0"
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

# Edit the following section to update the options for get options
# @getoptions
parser_definition() {
  setup   REST help:usage -- "Usage: publish-docker-containers.sh [options]... [arguments]..." ''
  msg -- 'Options:'
  flag    DEPLOY -d +d --{no-}deploy on:ON no:NO init:@on -- "Do we deploy?"
  option  LATEST_TAG  -l --latest-tag init:="latest"  -- "Set the latest tag to something other than latest"
  option  SCRIPT_DIR  -s --script-dir init:@none
  disp    :usage  -h --help
  disp    VERSION    --version
}
# @end

################################
# START GENERATED CODE SECTION #
################################

# @gengetoptions parser -i parser_definition parse
# Generated by getoptions (BEGIN)
# URL: https://github.com/ko1nksm/getoptions (v3.3.2)
DEPLOY='ON'
LATEST_TAG='latest'
REST=''
parse() {
  OPTIND=$(($#+1))
  while OPTARG= && [ "${REST}" != x ] && [ $# -gt 0 ]; do
    case $1 in
      --?*=*) OPTARG=$1; shift
        eval 'set -- "${OPTARG%%\=*}" "${OPTARG#*\=}"' ${1+'"$@"'}
        ;;
      --no-*|--without-*) unset OPTARG ;;
      -[ls]?*) OPTARG=$1; shift
        eval 'set -- "${OPTARG%"${OPTARG#??}"}" "${OPTARG#??}"' ${1+'"$@"'}
        ;;
      -[dh]?*) OPTARG=$1; shift
        eval 'set -- "${OPTARG%"${OPTARG#??}"}" -"${OPTARG#??}"' ${1+'"$@"'}
        case $2 in --*) set -- "$1" unknown "$2" && REST=x; esac;OPTARG= ;;
      +[d]?*) OPTARG=$1; shift
        eval 'set -- "${OPTARG%"${OPTARG#??}"}" +"${OPTARG#??}"' ${1+'"$@"'}
        unset OPTARG ;;
      +*) unset OPTARG ;;
    esac
    case $1 in
      '-d'|'+d'|'--deploy'|'--no-deploy')
        [ "${OPTARG:-}" ] && OPTARG=${OPTARG#*\=} && set "noarg" "$1" && break
        eval '[ ${OPTARG+x} ] &&:' && OPTARG='ON' || OPTARG='NO'
        DEPLOY="$OPTARG"
        ;;
      '-l'|'--latest-tag')
        set -- "$1" "$@"
        [ ${OPTARG+x} ] && {
          case $1 in --no-*|--without-*) set "noarg" "${1%%\=*}"; break; esac
          [ "${OPTARG:-}" ] && { shift; OPTARG=$2; } || OPTARG='1'
        } || OPTARG=''
        LATEST_TAG="$OPTARG"
        shift ;;
      '-s'|'--script-dir')
        set -- "$1" "$@"
        [ ${OPTARG+x} ] && {
          case $1 in --no-*|--without-*) set "noarg" "${1%%\=*}"; break; esac
          [ "${OPTARG:-}" ] && { shift; OPTARG=$2; } || OPTARG='1'
        } || OPTARG=''
        SCRIPT_DIR="$OPTARG"
        shift ;;
      '-h'|'--help')
        usage
        exit 0 ;;
      '--version')
        echo "${VERSION}"
        exit 0 ;;
      --)
        shift
        while [ $# -gt 0 ]; do
          REST="${REST} \"\${$(($OPTIND-$#))}\""
          shift
        done
        break ;;
      [-+]?*) set "unknown" "$1"; break ;;
      *)
        REST="${REST} \"\${$(($OPTIND-$#))}\""
    esac
    shift
  done
  [ $# -eq 0 ] && { OPTIND=1; unset OPTARG; return 0; }
  case $1 in
    unknown) set "Unrecognized option: $2" "$@" ;;
    noarg) set "Does not allow an argument: $2" "$@" ;;
    required) set "Requires an argument: $2" "$@" ;;
    pattern:*) set "Does not match the pattern (${1#*:}): $2" "$@" ;;
    notcmd) set "Not a command: $2" "$@" ;;
    *) set "Validation error ($1): $2" "$@"
  esac
  echo "$1" >&2
  exit 1
}
usage() {
cat<<'GETOPTIONSHERE'
Usage: publish-docker-containers.sh [options]... [arguments]...

Options:
  -d, --{no-}deploy           Do we deploy?
  -l, --latest-tag[=LATEST_TAG] 
                              Set the latest tag to something other than latest
  -s, --script-dir[=SCRIPT_DIR] 
  -h, --help                  
      --version               
GETOPTIONSHERE
}
# Generated by getoptions (END)
# @end

parse "$@"
eval "set -- $REST"

##############################
# END GENERATED CODE SECTION #
##############################

cd "${SCRIPT_DIR}/../../"
REPO_DIR=$(pwd)

# Publish all images 
images_to_build="$(find ./docker/images/* -type f -name 'Dockerfile' -exec sh -c 'dirname $0' {} \;)"
immutable_tag="$(git rev-parse HEAD)"
immutable_ordered_tag="deploy-$(date +%Y%m%d%H%M%S)-$(git rev-parse --short HEAD)"

if [[ `git status --porcelain` ]]; then
  # We don't actually want to commit this image if things aren't clean
  # so we use a different tag for the lexical tag
  immutable_tag="build-$(date +%s)"
  immutable_ordered_tag="temp-$(date +%s)"
fi

# By default, the target tag is the latest
target_tag="$LATEST_TAG"

if [[ "${DEPLOY}" == "ON" ]]; then
    echo "Building and deploying the images ${DEPLOY}"
else
    echo "Building the images (no deployment)"
fi


for path in $images_to_build; do
    # if directory has an image_name file use that for the image name
    if [ -f "${path}/image_name" ]; then
        image_name=$(cat "${path}/image_name")
    else
        image_name=$(basename "$path")
    fi
    image_dir_name=$(basename "$path")

    image_repo="ghcr.io/opensource-observer/${image_name}"
    sha_image="${image_repo}:${immutable_tag}"
    ordered_image="${image_repo}:${immutable_ordered_tag}"
    target_image="${image_repo}:${target_tag}"

    echo "Building ${image_name} image"
    docker build \
        -t ${sha_image} \
        -t ${target_image} \
        -t ${ordered_image} \
        --label "org.opencontainers.image.source=https://github.com/opensource-observer/oso" \
        --label "observer.opensource.oso.sha=${immutable_tag}" \
        --label "observer.opensource.oso.created_at=$(date +%s)" \
        --build-arg REPO_SHA=${immutable_tag} \
        --build-arg IMAGE_NAME=${image_name} \
        --build-arg ORDERED_TAG=${immutable_ordered_tag} \
        -f docker/images/${image_dir_name}/Dockerfile \
        .
    
    if [[ "${DEPLOY}" == "ON" ]]; then
        echo "Publishing the image to ${sha_image}"
        docker push "${sha_image}"
        echo "Publishing the image to ${ordered_image}"
        docker push "${ordered_image}"
        echo "Publishing ${target_tag} to ${target_image}"
        docker push "${target_image}"
    else
        echo "Not deploying ${image_name} image"
    fi
done
