#!/usr/bin/env bash set -euo pipefail : "${DEPLOY_HOST:?Missing DEPLOY_HOST}" : "${DEPLOY_USER:?Missing DEPLOY_USER}" : "${DEPLOY_PATH:?Missing DEPLOY_PATH}" : "${DEPLOY_SSH_KEY:?Configure the DEPLOY_SSH_KEY Actions secret}" : "${DEPLOY_KNOWN_HOSTS:?Configure the DEPLOY_KNOWN_HOSTS Actions secret}" : "${GITHUB_SHA:?Missing build commit}" : "${GITHUB_RUN_NUMBER:?Missing run number}" : "${GITHUB_RUN_ATTEMPT:?Missing run attempt}" DEPLOY_PORT=${DEPLOY_PORT:-22} # These values cross an SSH shell boundary. Reject shell syntax. [[ $DEPLOY_HOST =~ ^[a-zA-Z0-9][a-zA-Z0-9.-]*$ ]] [[ $DEPLOY_USER =~ ^[a-zA-Z0-9_][a-zA-Z0-9_-]*$ ]] [[ $DEPLOY_PATH =~ ^/[a-zA-Z0-9_/-]+$ && $DEPLOY_PATH != / ]] [[ $DEPLOY_PORT =~ ^[0-9]+$ && $GITHUB_SHA =~ ^[a-f0-9]{40}$ ]] [[ $GITHUB_RUN_NUMBER =~ ^[0-9]+$ && $GITHUB_RUN_ATTEMPT =~ ^[0-9]+$ ]] test -f _site/art/index.html test -f _site/photo-publication.json credentials=$(mktemp -d) trap 'rm -rf "$credentials"' EXIT chmod 700 "$credentials" printf '%s\n' "$DEPLOY_SSH_KEY" > "$credentials/key" printf '%s\n' "$DEPLOY_KNOWN_HOSTS" > "$credentials/known_hosts" chmod 600 "$credentials/key" "$credentials/known_hosts" target="$DEPLOY_USER@$DEPLOY_HOST" release="$DEPLOY_PATH/releases/$GITHUB_RUN_NUMBER-$GITHUB_RUN_ATTEMPT-$GITHUB_SHA" ssh_options=(-i "$credentials/key" -p "$DEPLOY_PORT" -o BatchMode=yes -o IdentitiesOnly=yes -o StrictHostKeyChecking=yes -o "UserKnownHostsFile=$credentials/known_hosts") ssh "${ssh_options[@]}" "$target" "mkdir -p '$release'" # Checksums and hard links avoid retransmitting existing photos on every build. printf -v transport 'ssh -i %q -p %q -o BatchMode=yes -o IdentitiesOnly=yes -o StrictHostKeyChecking=yes -o UserKnownHostsFile=%q' \ "$credentials/key" "$DEPLOY_PORT" "$credentials/known_hosts" rsync -azc --delete --link-dest="$DEPLOY_PATH/current/" -e "$transport" _site/ "$target:$release/" ssh "${ssh_options[@]}" "$target" "bash -s -- '$DEPLOY_PATH' '$release' '$GITHUB_RUN_NUMBER'" <<'REMOTE' set -euo pipefail destination=$1 release=$2 run=$3 exec 9>"$destination/deploy.lock" flock 9 test -f "$release/art/index.html" test -f "$release/photo-publication.json" previous=0 if [ -f "$destination/current/deployment-run" ]; then previous=$(cat "$destination/current/deployment-run") fi if (( run < previous )); then echo "A newer workflow has already deployed; leaving the current site intact." exit 0 fi printf '%s\n' "$run" > "$release/deployment-run" chmod -R a+rX "$release" temporary="$destination/.current-$run-$$" ln -s "releases/$(basename "$release")" "$temporary" mv -Tf "$temporary" "$destination/current" echo "Deployed $release" REMOTE