#!/usr/bin/env bash # Usage: tools/deploy-rootfs [-h] [...] # # Deploys a werkrevisor rootfs archive to a Werkator host: # uploads it into on , checks its checksum, # and in ~//.git/werkator/.werkator.yml of each replaces the old archive name with the new one, # after a backup .werkator.yml.bak-before-; a second deploy of the same version keeps the first backup. # Without repos it takes each machine config on the host that names a werkrevisor archive. # It prints only the changed line numbers, since these files hold tokens. # Then it keeps the two newest archives in , never one that a .werkator.yml still names, # and the two newest versioned backups per repository. # It opens two connections, the upload and one for the rest, and retries a refused connection, # since the host refuses connections that follow too quickly. # # Example: # tools/deploy-rootfs werkrevisor-rootfs-0.31.3.tar.zst user@host.example.org /home/storage/werkator werkprobe werkator set -euo pipefail if [[ $# -lt 3 || "$1" =~ ^(-h|-\?|--help)$ ]]; then awk 'NR > 1 && /^#/ { sub(/^# ?/, ""); print; next } NR > 1 { exit }' "$0" exit 0 fi archive="$1" target="$2" directory="$3" shift 3 name=$(basename "$archive") [[ "$name" =~ ^werkrevisor-rootfs-([0-9]+(\.[0-9]+)+)\.tar\.zst$ ]] || { echo "not a rootfs archive: $name" >&2; exit 2; } sum=$(sha256sum "$archive" | cut -d' ' -f1) retrying() { local attempt for attempt in 1 2 3 4 5 6; do "$@" && return 0 local status=$? [[ $status -eq 255 || $status -eq 1 && "$1" == scp ]] || return $status [[ $attempt -lt 6 ]] || break echo "connection refused, retry in $((30 * attempt)) s" >&2 sleep $((30 * attempt)) done return 1 } retrying scp -q -o BatchMode=yes "$archive" "$target:$directory/" echo "uploaded: $name" # The script and its Python files travel as arguments, so that a retry after a refused connection sends them again. script=$(cat <<'REMOTE' set -euo pipefail tmp=$(mktemp -d) trap 'rm -rf "$tmp"' EXIT printf '%s\n' "$1" > "$tmp/release_files.py" printf '%s\n' "$2" > "$tmp/release_rootfs.py" shift 2 python3 "$tmp/release_rootfs.py" install "$@" REMOTE ) tools=$(dirname "$0") retrying ssh -o BatchMode=yes "$target" \ "bash -c $(printf '%q' "$script") deploy-rootfs $(printf '%q ' "$(cat "$tools/release_files.py")" \ "$(cat "$tools/release_rootfs.py")" "$directory" "$name" "$sum" "$@")"