Files
claude-code 841bc82867
werkator build succeeded after 00:11
werkator/werkrevisor-statistics build succeeded after 00:28
werkator/release build succeeded after 00:15
werkrevisor 0.46.0: Werkator releases werkrevisor after each merge (#118)
Co-authored-by: claude-code <claude-code@javagil.de>
2026-10-17 14:27:48 +02:00

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" "$@")"