Files
suaveplan/ops/registry/rollback.sh
2026-05-27 23:29:53 +01:00

75 lines
2.3 KiB
Bash

#!/usr/bin/env bash
# rollback.sh — atomic-swap the live registry tree with the most
# recent snapshot under /srv/registry/.previous/.
#
# Usage (on the OVH host, as deploy-registry or root):
# bash /srv/registry/ops/rollback.sh
#
# Idempotent within reason: a second invocation immediately after the
# first promotes what was previously live (effectively roll-forward).
# Exits non-zero with a clear message if no snapshot exists.
set -euo pipefail
REGISTRY_ROOT="${REGISTRY_ROOT:-/srv/registry}"
LIVE_R="${REGISTRY_ROOT}/r"
LIVE_SB="${REGISTRY_ROOT}/storybook"
SNAPSHOT_ROOT="${REGISTRY_ROOT}/.previous"
ROLLBACK_PARK="${REGISTRY_ROOT}/.rollback-park"
log() {
printf '[rollback %s] %s\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "$*" >&2
}
err() {
log "ERROR: $*"
exit 1
}
if [[ ! -d "${SNAPSHOT_ROOT}" ]]; then
err "no snapshot directory at ${SNAPSHOT_ROOT}; nothing to roll back to"
fi
# Pick the most recent snapshot directory by name (ISO-8601 lexically sorts).
LATEST="$(find "${SNAPSHOT_ROOT}" -mindepth 1 -maxdepth 1 -type d -printf '%f\n' 2>/dev/null | sort | tail -n 1)"
if [[ -z "${LATEST}" ]]; then
err "no snapshots present under ${SNAPSHOT_ROOT}; cannot roll back"
fi
SNAPSHOT_DIR="${SNAPSHOT_ROOT}/${LATEST}"
log "rolling back to snapshot: ${SNAPSHOT_DIR}"
# Park the current tree as the next-snapshot so we can roll-forward
# by re-running the script.
PARK_DIR="${ROLLBACK_PARK}/$(date -u +%Y%m%dT%H%M%SZ)"
mkdir -p "${PARK_DIR}"
if [[ -d "${LIVE_R}" ]]; then
mv "${LIVE_R}" "${PARK_DIR}/r"
fi
if [[ -d "${LIVE_SB}" ]]; then
mv "${LIVE_SB}" "${PARK_DIR}/storybook"
fi
# Promote snapshot to live.
if [[ -d "${SNAPSHOT_DIR}/r" ]]; then
mv "${SNAPSHOT_DIR}/r" "${LIVE_R}"
fi
if [[ -d "${SNAPSHOT_DIR}/storybook" ]]; then
mv "${SNAPSHOT_DIR}/storybook" "${LIVE_SB}"
fi
# Move the parked tree into the snapshots dir so the next rollback
# call (a roll-forward) can find it.
NEW_SNAPSHOT="${SNAPSHOT_ROOT}/$(basename "${PARK_DIR}")"
mv "${PARK_DIR}" "${NEW_SNAPSHOT}"
# Drained snapshot dir is now empty — clean up so next rollback picks
# the right "latest".
rmdir "${SNAPSHOT_DIR}" 2>/dev/null || true
rmdir "${ROLLBACK_PARK}" 2>/dev/null || true
log "rollback complete; live tree now serves contents from ${LATEST}"
log "previous live tree parked at ${NEW_SNAPSHOT} (re-run to roll forward)"