#!/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"