#!/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)"