aboutsummaryrefslogblamecommitdiff
path: root/v2/aux/ci/git-post-receive.sh
blob: 76adccf6b13939a3b5b87f09c56b022c945feaad (plain) (tree)

























































































































































































                                                                                                         
#!/bin/sh
# shellcheck source=/dev/null disable=2317
. /etc/rc
set -eu


# shellcheck disable=2034
read -r _oldrev SHA REFNAME

if [ "$SHA" = '0000000000000000000000000000000000000000' ]; then
	exit
fi


SKIP_DEPLOY=false
for n in $(seq 0 $((GIT_PUSH_OPTION_COUNT - 1))); do
	opt="$(eval "printf '%s' \"\$GIT_PUSH_OPTION_$n\"")"
	case "$opt" in
		ci.skip)
			cat <<-EOF

				"$opt" option detected, not running CI.

			EOF
			exit
			;;
		deploy.skip)
			SKIP_DEPLOY=true
			;;
		*)
			;;
	esac
done


epoch() {
	awk 'BEGIN { srand(); print(srand()); }'
}

now() {
	date '+%Y-%m-%dT%H:%M:%S%:z'
}

NAME="$(basename "$PWD" .git)"
LOGS_DIR=/var/log/ci/"$NAME"/
HTML_OUTDIR="/srv/www/s/$NAME"
TIMESTAMP="$(now)"
FILENAME="$TIMESTAMP-$SHA.log"
LOGFILE="$LOGS_DIR/$FILENAME"
mkdir -p "$LOGS_DIR"


END_MARKER='\033[0m'
LIGHT_BLUE_B='\033[1;36m'
YELLOW='\033[1;33m'

blue() {
	printf "${LIGHT_BLUE_B}%s${END_MARKER}" "$1"
}

yellow() {
	printf "${YELLOW}%s${END_MARKER}" "$1"
}

info() {
	sed "s|^\(.\)|$(blue 'CI'): \1|"
}


uuid() {
	od -xN20 /dev/urandom |
		head -n1 |
		awk '{OFS="-"; print $2$3,$4,$5,$6,$7$8$9}'
}

tmpname() {
	printf '%s/uuid-tmpname with spaces.%s' "${TMPDIR:-/tmp}" "$(uuid)"
}

mkdtemp() {
	name="$(tmpname)"
	mkdir -- "$name"
	printf '%s' "$name"
}


{
	cat <<-EOF | info
		Starting CI job at: $(now)
	EOF
	START="$(epoch)"

	duration() {
		if [ "$RUN_DURATION" -gt 60 ]; then
			cat <<-EOF
				$(yellow 'WARNING'): run took more than 1 minute! ($RUN_DURATION seconds)
			EOF
		else
			cat <<-EOF
				Run took $RUN_DURATION seconds.
			EOF
		fi
	}

	finish() {
		STATUS="$?"
		END="$(epoch)"
		RUN_DURATION=$((END - START))
		cat <<-EOF | info
			Finishing CI job at: $(now)
			Exit status was $STATUS
			Re-run with:
			  \$ $CMD
			$(duration)
		EOF

		NOTE="$(
			cat <<-EOF
				See CI logs with:
				  git notes --ref=refs/notes/ci-logs show $SHA
				  git notes --ref=refs/notes/ci-data show $SHA

				Exit status: $STATUS
				Duration: $RUN_DURATION
			EOF
		)"
		git notes --ref=refs/notes/ci-data add -f -m "$(
			cat <<-EOF
				status $STATUS
				sha $SHA
				filename $FILENAME
				duration $RUN_DURATION
				timestamp $TIMESTAMP
				to-prod $TO_PROD
				refname $REFNAME
			EOF
		)" "$SHA"
		git notes --ref=refs/notes/ci-logs add -f -F "$LOGFILE" "$SHA"
		git notes add -f -m "$NOTE" "$SHA"

		{
			printf 'Git CI HTML report for %s (%s) started.\n' "$NAME" "$SHA" >&2
			DIR="$(mkdtemp)"
			REMOTE="$PWD"
			cd "$DIR"
			{
				git clone "$REMOTE" .
				git fetch origin 'refs/notes/*:refs/notes/*'
			} 1>/dev/null 2>&1
			sh aux/ci/report.sh -n "$NAME" -o public-ci
			sudo -u deployer mkdir -p "$HTML_OUTDIR"/ci/
			sudo -u deployer rsync \
				--chmod=D775,F664         \
				--chown=deployer:deployer \
				--delete                  \
				-a                        \
				public-ci/ "$HTML_OUTDIR"/ci/
			rm -rf "$DIR"
			printf 'Git CI HTML report for %s (%s) finished.\n' "$NAME" "$SHA" >&2
		} 2>&1 | logger -i -p local0.warn -t git-ci 1>/dev/null 2>&1 &
	}
	trap finish EXIT

	unset GIT_DIR

	if [ "$REFNAME" = 'refs/heads/main' ] && [ "$SKIP_DEPLOY" = false ]; then
		cat <<-EOF | info
			In branch "main", running deploy for $SHA.
		EOF
		TO_PROD=true
		CMD="sudo cicd $NAME $SHA"
	else
		if [ "$SKIP_DEPLOY" = true ]; then
			cat <<-EOF | info
				"deploy.skip" option detected, skipping deploy for $SHA.
			EOF
		else
			cat <<-EOF | info
				Not on branch "main", skipping deploy for $SHA.
			EOF
		fi
		TO_PROD=false
		CMD="sudo cicd -n $NAME $SHA"
	fi
	$CMD
} 2>&1 | ts -s '%.s' | tee "$LOGFILE"