#!/usr/bin/env bash # Archive old build images on the fileserver before publishing new ones. # # Usage: tools/archive-images.sh ... # # Zero matching files is fine (nothing to archive yet); a missing directory # or a failed move aborts non-zero so CI stops before publishing. # The remote half is piped to `bash -s` over stdin so there is no nested # shell quoting to get wrong. set -euo pipefail die() { echo "error: $*" >&2; exit 1; } (( $# >= 4 )) || die "usage: $0 ..." target=$1 images_dir=$2 archive_dir=$3 shift 3 patterns=("$@") for v in "$images_dir" "$archive_dir" "${patterns[@]}"; do case $v in *[[:space:]\'\"]*) die "unsafe argument (whitespace/quotes): $v" ;; esac done echo "Archiving previous images on $target:" printf ' pattern: %s\n' "${patterns[@]}" # Assignments prefixed to `bash -s` are parsed by the remote shell as # environment variables for the script below; the quoted heredoc marker # keeps every byte of the payload literal until bash executes it. ssh "$target" "IMAGES_DIR=$images_dir ARCHIVE_DIR=$archive_dir bash -s" <<'REMOTE' set -euo pipefail shopt -s nullglob if [ ! -d "$IMAGES_DIR" ]; then echo "error: images dir not found: $IMAGES_DIR" >&2 exit 1 fi if [ ! -d "$ARCHIVE_DIR" ]; then echo "error: archive dir not found: $ARCHIVE_DIR" >&2 exit 1 fi moved=0 for pat in "${PATTERNS[@]}"; do for f in "$IMAGES_DIR"/$pat; do echo " archiving $(basename "$f")" mv "$f" "$ARCHIVE_DIR/" moved=$((moved + 1)) done done echo "Archived $moved file(s)." REMOTE