#!/bin/sh
# canonical: nsoclassic-workspace/docs/ci-cd-contract.md
#
# Runs this repository's gate on the exact commits being pushed, in a detached
# worktree so the state of the working tree cannot change the verdict. A green
# gate writes a note on refs/notes/gate-verified for that commit id; the note is
# pushed before the branch. A red gate, or a note that cannot be pushed, rejects
# the whole push.
set -eu

# The note push below re-enters this hook. Let it through.
if [ "${GATE_NOTE_PUSH:-}" = 1 ]; then
	exit 0
fi

remote_name="${1:-origin}"
zero=$(git hash-object --stdin </dev/null | tr '[:xdigit:]' '0')
repo_root=$(git rev-parse --show-toplevel)

while read -r _local_ref local_sha _remote_ref _remote_sha; do
	[ "$local_sha" = "$zero" ] && continue        # branch deletion

	if git notes --ref=gate-verified show "$local_sha" >/dev/null 2>&1; then
		echo "gate: $local_sha already certified"
		continue
	fi

	tmp=$(mktemp -d "${TMPDIR:-/tmp}/gate.XXXXXX")
	trap 'git -C "$repo_root" worktree remove --force "$tmp" >/dev/null 2>&1 || rm -rf "$tmp"' EXIT INT TERM
	git worktree add --detach --quiet "$tmp" "$local_sha"

	echo "gate: running $repo_root/scripts/gate.sh on $local_sha"
	if ( cd "$tmp" && exec sh scripts/gate.sh ); then
		git -C "$repo_root" worktree remove --force "$tmp" >/dev/null 2>&1 || rm -rf "$tmp"
		trap - EXIT INT TERM
	else
		status=$?
		git -C "$repo_root" worktree remove --force "$tmp" >/dev/null 2>&1 || rm -rf "$tmp"
		trap - EXIT INT TERM
		echo "push rejected: gate failed on $local_sha (exit $status)"
		exit 1
	fi

	sh "$repo_root/scripts/gate-note.sh" "$local_sha" "$remote_name" || {
		echo "push rejected: the gate passed but its note could not be published"
		exit 1
	}
done

exit 0
