#!/bin/sh set -eu require_value() { key="$1" value="$2" if [ -z "$value" ]; then echo "Missing required rollback configuration: $key" >&2 exit 1 fi } validate_tag() { key="$1" value="$2" case "$value" in [A-Za-z0-9_]* ) ;; *) echo "Invalid Docker image tag for $key" >&2 exit 1 ;; esac case "$value" in *[!A-Za-z0-9_.-]* ) echo "Invalid Docker image tag for $key" >&2 exit 1 ;; esac if [ "${#value}" -gt 128 ]; then echo "Docker image tag for $key exceeds 128 characters" >&2 exit 1 fi } require_value "DEPLOY_TARGET" "${DEPLOY_TARGET:-}" require_value "CALENDAR_URL" "${CALENDAR_URL:-}" require_value "PRIMARY_DOMAIN" "${PRIMARY_DOMAIN:-}" require_value "TRAEFIK_CERTRESOLVER" "${TRAEFIK_CERTRESOLVER:-}" require_value "REGISTRY" "${REGISTRY:-}" require_value "REGISTRY_USERNAME" "${REGISTRY_USERNAME:-}" require_value "REGISTRY_TOKEN" "${REGISTRY_TOKEN:-}" case "$DEPLOY_TARGET" in dev) default_stack_name="website-starter-dev" default_traefik_network="traefik-external" ;; master|production) default_stack_name="website-starter-prod" default_traefik_network="traefik" ;; *) echo "Unsupported rollback target: $DEPLOY_TARGET" >&2 exit 1 ;; esac require_value "APP_IMAGE_REPOSITORY" "${APP_IMAGE_REPOSITORY:-}" require_value "APP_IMAGE_TAG" "${APP_IMAGE_TAG:-}" validate_tag "APP_IMAGE_TAG" "$APP_IMAGE_TAG" APP_IMAGE_NAME="$APP_IMAGE_REPOSITORY:$APP_IMAGE_TAG" APP_URL="${APP_URL:-https://$PRIMARY_DOMAIN}" CORS_ORIGIN="${CORS_ORIGIN:-$APP_URL}" COMPOSE_PROJECT_NAME="${COMPOSE_PROJECT_NAME:-$default_stack_name}" TRAEFIK_STACK_NAME="${TRAEFIK_STACK_NAME:-$COMPOSE_PROJECT_NAME}" TRAEFIK_NETWORK_NAME="${TRAEFIK_NETWORK_NAME:-$default_traefik_network}" export CALENDAR_URL export PRIMARY_DOMAIN export APP_URL export CORS_ORIGIN export COMPOSE_PROJECT_NAME export TRAEFIK_STACK_NAME export TRAEFIK_CERTRESOLVER export TRAEFIK_NETWORK_NAME export APP_IMAGE_NAME docker_config="$(mktemp -d)" cleanup_registry_credentials() { DOCKER_CONFIG="$docker_config" docker logout "$REGISTRY" >/dev/null 2>&1 || true rm -rf "$docker_config" } trap cleanup_registry_credentials EXIT trap 'exit 1' HUP INT TERM export DOCKER_CONFIG="$docker_config" echo "$REGISTRY_TOKEN" | docker login "$REGISTRY" -u "$REGISTRY_USERNAME" --password-stdin docker pull "$APP_IMAGE_NAME" docker logout "$REGISTRY" >/dev/null rm -rf "$docker_config" trap - EXIT HUP INT TERM unset DOCKER_CONFIG REGISTRY_USERNAME REGISTRY_TOKEN echo "Rollback target: $DEPLOY_TARGET" echo "Site host: $PRIMARY_DOMAIN" echo "Compose project: $COMPOSE_PROJECT_NAME" echo "App image: $APP_IMAGE_NAME" sh scripts/deploy-and-verify.sh