#!/bin/sh

set -e

. /etc/pkgos/pkgos.conf

if [ -z "${SALSA_TOKEN}" ] ; then
        echo "The \$SALSA_TOKEN variable is empty. Please export it with" >/dev/stderr
        echo "a valid salsa.debian.org token as content." >/dev/stderr
        exit 1
fi

ME=$(basename $0)

usage () {
	echo "$ME --project-name PROJECT_NAME [--openstack-release OPENSTACK_RELEASE] [--debian-release DEBIAN_RELEASE] [--jenkins-token JENKINS_TOKEN] [--repair] [--debug]"
	exit 1
}

OPENSTACK_RELEASE=${TARGET_OPENSTACK_REL}
DEBIAN_RELEASE=${TARGET_DISTRO}
DEBUG=no
REPAIR=no
NEED_BRANCH=""
NEED_DEFAULT_BRANCH=""
NEED_CI_CONFIG=""
NEED_IRKER=""
NEED_TAGPENDING=""
NEED_JENKINS=""
NEED_EMAILS=""
for i in $@ ; do
	case "${1}" in
	"--openstack-release")
		if [ -z "${2}" ] ; then
			echo "No parameter defining the OpenStack release."
			usage
		fi
		OPENSTACK_RELEASE=${2}
		shift
		shift
	;;
	"--debian-release")
		if [ -z "${2}" ] ; then
			echo "No parameter defining the Debian release."
			usage
		fi
		DEBIAN_RELEASE=${2}
		shift
		shift
	;;
	"--project-id")
		if [ -z "${2}" ] ; then
			echo "No parameter defining the project ID."
			usage
		fi
		PROJECT_ID=${2}
		shift
		shift
	;;
	"--project-name")
		if [ -z "${2}" ] ; then
			echo "No parameter defining the project name."
			usage
		fi
		PROJECT_NAME=${2}
		shift
		shift
	;;
	"--jenkins-token")
		if [ -z "${2}" ] ; then
			echo "No parameter defining the Jenkins token."
			usage
		fi
		JENKINS_TOKEN=${2}
		shift
		shift
	;;
	"--repair")
		REPAIR=yes
		shift
	;;
	"--debug")
		DEBUG=yes
		shift
	;;
	*)
	;;
	esac
done

if [ -z "${PROJECT_ID}" ] ; then
	if [ -z "${PROJECT_NAME}" ] ; then
		usage
	fi
	PROJECT_ID=$(pkgos-salsa-get-project-id --project-name ${PROJECT_NAME})
	if [ -z "${PROJECT_ID}" ] ; then
		echo "Cannot find project id for ${PROJECT_NAME}"
		exit 1
	fi
fi

    BLUE="\033[1;34m"
   LGRAY="\033[0;37m"
  NO_COL="\033[0m"
   LBLUE="\033[1;36m"
     RED="\033[1;31m"
   GREEN="\033[1;32m"
   WHITE="\033[1;37m"
  YELLOW="\033[1;33m"
LINEWRAP="\033[7h"
      UP="\033[1A"
    DOWN="\033[1B"
      NL="\033[1E"
      RN="\033[1S"

API_BASE="https://salsa.debian.org/api/v4"

# Fetch and print to stderr the API GET which is going to be done.
# $1: the API path to fetch.
api_get () {
	if [ "${DEBUG}" = "yes" ] ; then
		echo "   curl -s ${API_BASE}/${1}" >/dev/stderr
	fi
	curl -s -H "PRIVATE-TOKEN: ${SALSA_TOKEN}" "${API_BASE}/${1}"
}

check_wrong () {
	echo "   ${1}: ${RED}WRONG (got: ${2})${NO_COL}"
}

check_wrong_hint () {
	echo "   ${1}: ${RED}WRONG (got: ${2}, expected: ${3})${NO_COL}"
}

# Run one repair action, and count its success or failure.
# $1: human readable description of the action (must not include secrets).
# $2...: the command to run.
run_repair () {
	REPAIR_DESC=${1}
	shift
	echo "   ${YELLOW}repair:${NO_COL} ${REPAIR_DESC}"
	if "${@}" ; then
		REPAIRED=$(( ${REPAIRED} + 1 ))
	else
		echo "   ${RED}repair FAILED: ${REPAIR_DESC}${NO_COL}"
		REPAIR_FAILED=$(( ${REPAIR_FAILED} + 1 ))
	fi
}

CHECK_TOTAL=7
CHECK_OK=0

# Project infos, also used to resolve the project name if only --project-id was used.
PROJECT_INFO=$(api_get "projects/${PROJECT_ID}")
if [ -z "${PROJECT_NAME}" ] ; then
	PROJECT_NAME=$(printf '%s' "${PROJECT_INFO}" | jq -r '.path_with_namespace // ""' | cut -d/ -f3)
fi

echo "${YELLOW}-> Checking ${PROJECT_NAME} (project ${PROJECT_ID})${NO_COL}"

DEFAULT_BRANCH=$(printf '%s' "${PROJECT_INFO}" | jq -r '.default_branch // ""')
CI_CONFIG_PATH=$(printf '%s' "${PROJECT_INFO}" | jq -r '.ci_config_path // ""')
BRANCH=debian/${OPENSTACK_RELEASE}
# The GitLab API needs the branch name URL-encoded in the path.
BRANCH_API=$(printf '%s' "${BRANCH}" | sed 's|/|%2F|g')
BRANCH_INFO=$(api_get "projects/${PROJECT_ID}/repository/branches/${BRANCH_API}")
BRANCH_EXISTS=$(printf '%s' "${BRANCH_INFO}" | jq -r 'if .name then "true" else "false" end')
HOOK_LIST=$(api_get "projects/${PROJECT_ID}/hooks?per_page=100")
IRKER_OK=$(printf '%s' "${HOOK_LIST}" | jq -r '[.[] | select((.url | test("kgb\\.debian\\.net:9418/webhook")) and (.url | test("channel=debian-openstack-commits")) and .push_events == true)] | length > 0')
TAGPENDING_URL="https://webhook.salsa.debian.org/tagpending/${PROJECT_NAME}"
TAGPENDING_OK=$(printf '%s' "${HOOK_LIST}" | jq -r --arg url "${TAGPENDING_URL}" '[.[] | select(.url == $url and .push_events == true and .tag_push_events == true and .merge_requests_events == true)] | length > 0')
JENKINS_URL="https://${DEBIAN_RELEASE}-${OPENSTACK_RELEASE}.debian.net/project/${PROJECT_NAME}"
JENKINS_OK=$(printf '%s' "${HOOK_LIST}" | jq -r --arg prefix "${JENKINS_URL}" --arg filter "${BRANCH}" '[.[] | select((.url | startswith($prefix)) and .push_events_branch_filter == $filter)] | length > 0')
EMAILS_INFO=$(api_get "projects/${PROJECT_ID}/integrations/emails-on-push")
EMAILS_OK=$(printf '%s' "${EMAILS_INFO}" | jq -r 'if ((.properties.recipients // .recipients // "") | test("dispatch@tracker\\.debian\\.org")) then "true" else "false" end')

if [ "${DEFAULT_BRANCH}" = "${BRANCH}" ] ; then
	CHECK_OK=$(( ${CHECK_OK} + 1 ))
	echo "   default branch is ${BRANCH}: ${GREEN}OK${NO_COL}"
else
	check_wrong_hint "default branch is ${BRANCH}" "${DEFAULT_BRANCH}" "${BRANCH}"
	NEED_DEFAULT_BRANCH=yes
fi

if [ "${BRANCH_EXISTS}" = "true" ] ; then
	CHECK_OK=$(( ${CHECK_OK} + 1 ))
	echo "   branch ${BRANCH} exists: ${GREEN}OK${NO_COL}"
else
	check_wrong "branch ${BRANCH} exists" "missing"
	NEED_BRANCH=yes
fi

if [ "${CI_CONFIG_PATH}" = "debian/salsa-ci.yml" ] ; then
	CHECK_OK=$(( ${CHECK_OK} + 1 ))
	echo "   ci_config_path is debian/salsa-ci.yml: ${GREEN}OK${NO_COL}"
else
	check_wrong_hint "ci_config_path is debian/salsa-ci.yml" "${CI_CONFIG_PATH}" "debian/salsa-ci.yml"
	NEED_CI_CONFIG=yes
fi

if [ "${IRKER_OK}" = "true" ] ; then
	CHECK_OK=$(( ${CHECK_OK} + 1 ))
	echo "   irker webhook (kgb.debian.net): ${GREEN}OK${NO_COL}"
else
	check_wrong "irker webhook (kgb.debian.net)" "missing"
	NEED_IRKER=yes
fi

if [ "${TAGPENDING_OK}" = "true" ] ; then
	CHECK_OK=$(( ${CHECK_OK} + 1 ))
	echo "   tagpending hook (webhook.salsa.debian.org): ${GREEN}OK${NO_COL}"
else
	check_wrong "tagpending hook (webhook.salsa.debian.org)" "missing"
	NEED_TAGPENDING=yes
fi

if [ "${JENKINS_OK}" = "true" ] ; then
	CHECK_OK=$(( ${CHECK_OK} + 1 ))
	echo "   jenkins webhook (${JENKINS_URL}): ${GREEN}OK${NO_COL}"
else
	check_wrong "jenkins webhook (${JENKINS_URL})" "missing"
	NEED_JENKINS=yes
fi

if [ "${EMAILS_OK}" = "true" ] ; then
	CHECK_OK=$(( ${CHECK_OK} + 1 ))
	echo "   emails-on-push to dispatch@tracker.debian.org: ${GREEN}OK${NO_COL}"
else
	check_wrong "emails-on-push to dispatch@tracker.debian.org" "missing"
	NEED_EMAILS=yes
fi

if [ "${CHECK_OK}" -eq "${CHECK_TOTAL}" ] ; then
	echo "${GREEN}-> ${PROJECT_NAME}: fully configured (${CHECK_OK}/${CHECK_TOTAL} checks OK)${NO_COL}"
else
	echo "${YELLOW}-> ${PROJECT_NAME}: ${RED}${CHECK_OK}/${CHECK_TOTAL} checks OK${NO_COL}"
fi

if [ "${REPAIR}" = "yes" ] ; then
	# Concatenation of all the repair flags: empty means everything was OK.
	ALL_NEEDS="${NEED_BRANCH}${NEED_DEFAULT_BRANCH}${NEED_CI_CONFIG}${NEED_IRKER}${NEED_TAGPENDING}${NEED_JENKINS}${NEED_EMAILS}"
	if [ -z "${ALL_NEEDS}" ] ; then
		echo "${GREEN}-> ${PROJECT_NAME}: nothing to repair${NO_COL}"
	else
		REPAIRED=0
		REPAIR_FAILED=0
		DEBUG_ARG=""
		if [ "${DEBUG}" = "yes" ] ; then
			DEBUG_ARG="--debug"
		fi
		if [ "${NEED_BRANCH}" = "yes" ] ; then
			OLD_RELEASE=""
			if [ -r /etc/pkgos/openstack-release.txt ] ; then
				OLD_RELEASE=$(awk -v rel="${OPENSTACK_RELEASE}" '
					{ lines[NR] = $0 }
					$0 == rel { found = NR }
					END {
						if (found > 1)
							print lines[found - 1]
					}' /etc/pkgos/openstack-release.txt)
			fi
			if [ -n "${OLD_RELEASE}" ] ; then
				run_repair "branch ${BRANCH} from debian/${OLD_RELEASE} (pkgos-salsa-new-branch)" \
					pkgos-salsa-new-branch --old-release ${OLD_RELEASE} --new-release ${OPENSTACK_RELEASE} \
					--project-id ${PROJECT_ID} --project-name ${PROJECT_NAME} ${DEBUG_ARG}
			else
				echo "   ${YELLOW}repair: cannot find the release preceding ${OPENSTACK_RELEASE} in /etc/pkgos/openstack-release.txt, please create ${BRANCH} with pkgos-salsa-new-branch manually${NO_COL}"
			fi
		fi
		if [ "${NEED_DEFAULT_BRANCH}" = "yes" ] ; then
			run_repair "default branch -> ${BRANCH} (pkgos-salsa-set-default-branch)" \
				pkgos-salsa-set-default-branch --project-id ${PROJECT_ID} --project-name ${PROJECT_NAME} \
				--new-release ${OPENSTACK_RELEASE} ${DEBUG_ARG}
		fi
		if [ "${NEED_CI_CONFIG}" = "yes" ] ; then
			run_repair "ci_config_path -> debian/salsa-ci.yml (pkgos-salsa-set-ci-config-path)" \
				pkgos-salsa-set-ci-config-path --project-id ${PROJECT_ID} ${DEBUG_ARG}
		fi
		if [ "${NEED_IRKER}" = "yes" ] ; then
			run_repair "irker webhook (pkgos-salsa-set-irker)" \
				pkgos-salsa-set-irker --project-id ${PROJECT_ID}
		fi
		if [ "${NEED_TAGPENDING}" = "yes" ] ; then
			run_repair "tagpending hook (pkgos-salsa-set-tagpending-hook)" \
				pkgos-salsa-set-tagpending-hook --project-id ${PROJECT_ID} --project-name ${PROJECT_NAME}
		fi
		if [ "${NEED_JENKINS}" = "yes" ] ; then
			if [ -n "${JENKINS_TOKEN}" ] ; then
				run_repair "jenkins webhook ${JENKINS_URL} (pkgos-salsa-set-webhook)" \
					pkgos-salsa-set-webhook --new-release ${OPENSTACK_RELEASE} --debian-release ${DEBIAN_RELEASE} \
					--project-id ${PROJECT_ID} --project-name ${PROJECT_NAME} --jenkins-token ${JENKINS_TOKEN} ${DEBUG_ARG}
			else
				echo "   ${YELLOW}repair: no --jenkins-token passed, please add the jenkins webhook with pkgos-salsa-set-webhook manually${NO_COL}"
			fi
		fi
		if [ "${NEED_EMAILS}" = "yes" ] ; then
			run_repair "emails-on-push integration (pkgos-salsa-set-emails-on-push)" \
				pkgos-salsa-set-emails-on-push --project-id ${PROJECT_ID} ${DEBUG_ARG}
		fi
		echo "${YELLOW}-> ${PROJECT_NAME}: repair pass finished (${REPAIRED} repaired, ${REPAIR_FAILED} failed); re-run ${ME} to confirm${NO_COL}"
	fi
fi
