61 lines
2.5 KiB
Bash
Executable File
61 lines
2.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Usage: tools/deploy-rootfs [-h] <archive> <ssh-target> <directory> [<repo>...]
|
|
#
|
|
# Deploys a werkrevisor rootfs archive to a Werkator host:
|
|
# uploads it into <directory> on <ssh-target>, checks its checksum,
|
|
# and in ~/<repo>/.git/werkator/.werkator.yml of each <repo> replaces the old archive name with the new one,
|
|
# after a backup .werkator.yml.bak-before-<version>; 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 <directory>, 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" "$@")"
|