#!/usr/bin/env bash set -euo pipefail DOCKER_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" ROOT_DIR="$(cd "$DOCKER_DIR/.." && pwd)" ENV_FILE="${ENV_FILE:-$DOCKER_DIR/.env.multisite}" COMPOSE_FILE="$DOCKER_DIR/docker-compose.multisite.yml" UPDATE_MODE="${UPDATE_MODE:-local}" PROD_APP_CONTAINER="${PROD_APP_CONTAINER:-netgescon_prod_app}" DEMO_APP_CONTAINER="${DEMO_APP_CONTAINER:-netgescon_demo_app}" MAINTENANCE_RENDER="${NETGESCON_MAINTENANCE_RENDER:-errors::503}" MAINTENANCE_RETRY="${NETGESCON_MAINTENANCE_RETRY:-60}" MAINTENANCE_REFRESH="${NETGESCON_MAINTENANCE_REFRESH:-15}" RUN_DB_BACKUP="${RUN_DB_BACKUP:-false}" if command -v docker >/dev/null 2>&1; then if docker compose version >/dev/null 2>&1; then COMPOSE_CMD=(docker compose) elif command -v docker-compose >/dev/null 2>&1; then COMPOSE_CMD=(docker-compose) else echo "Errore: non trovo né 'docker compose' né 'docker-compose'." exit 127 fi elif command -v docker-compose >/dev/null 2>&1; then COMPOSE_CMD=(docker-compose) else echo "Errore: Docker non installato in questa VM." exit 127 fi if [[ ! -f "$ENV_FILE" ]]; then echo "Env mancante: $ENV_FILE" exit 1 fi upsert_env_var() { local key="$1" local value="$2" if grep -qE "^${key}=" "$ENV_FILE"; then sed -i "s#^${key}=.*#${key}=${value}#" "$ENV_FILE" else printf '\n%s=%s\n' "$key" "$value" >> "$ENV_FILE" fi } source "$ENV_FILE" if [[ -z "${APP_KEY:-}" ]]; then GENERATED_APP_KEY="base64:$(openssl rand -base64 32 | tr -d '\n')" upsert_env_var "APP_KEY" "$GENERATED_APP_KEY" APP_KEY="$GENERATED_APP_KEY" echo "APP_KEY generata automaticamente in $ENV_FILE" fi declare -a MAINTENANCE_CONTAINERS=() bring_apps_up() { for container in "${MAINTENANCE_CONTAINERS[@]}"; do docker exec "$container" php artisan up >/dev/null 2>&1 || true done } cleanup() { local exit_code=$? bring_apps_up exit "$exit_code" } enable_maintenance() { local container="$1" local -a command=(php artisan down --retry="$MAINTENANCE_RETRY" --refresh="$MAINTENANCE_REFRESH") if [[ -n "$MAINTENANCE_RENDER" ]]; then command+=(--render="$MAINTENANCE_RENDER") fi docker exec "$container" "${command[@]}" MAINTENANCE_CONTAINERS+=("$container") } trap cleanup EXIT echo "[1/7] Backup DB" if [[ "$RUN_DB_BACKUP" == "true" ]]; then "$DOCKER_DIR/backup-multisite.sh" else echo "Backup DB automatico disattivato: procedura prevista ma sospesa su questa distribuzione." fi echo "[2/7] Maintenance mode applicativa" enable_maintenance "$PROD_APP_CONTAINER" enable_maintenance "$DEMO_APP_CONTAINER" echo "[3/7] Update codice (mode: $UPDATE_MODE)" cd "$ROOT_DIR" case "$UPDATE_MODE" in local) echo "Uso codice locale già presente sulla VM." ;; distro) if [[ -z "${DISTRO_UPDATE_URL:-}" || -z "${DISTRO_UPDATE_TOKEN:-}" ]]; then echo "Errore: per UPDATE_MODE=distro servono DISTRO_UPDATE_URL e DISTRO_UPDATE_TOKEN nel file env." exit 1 fi curl -fL -H "Authorization: Bearer ${DISTRO_UPDATE_TOKEN}" "$DISTRO_UPDATE_URL" -o /tmp/netgescon-update.tgz tar -xzf /tmp/netgescon-update.tgz -C "$ROOT_DIR" ;; github) if [[ -z "${GITHUB_RELEASE_URL:-}" ]]; then echo "Errore: per UPDATE_MODE=github serve GITHUB_RELEASE_URL nel file env." exit 1 fi curl -fL "$GITHUB_RELEASE_URL" -o /tmp/netgescon-update.tgz tar -xzf /tmp/netgescon-update.tgz -C "$ROOT_DIR" ;; *) echo "Errore: UPDATE_MODE non valido ($UPDATE_MODE). Valori: local | distro | github" exit 1 ;; esac echo "[4/7] Build app" "${COMPOSE_CMD[@]}" --env-file "$ENV_FILE" -f "$COMPOSE_FILE" build prod_app echo "[5/7] Rolling restart" "${COMPOSE_CMD[@]}" --env-file "$ENV_FILE" -f "$COMPOSE_FILE" up -d prod_app prod_nginx demo_app demo_nginx echo "[6/7] Clear cache Laravel" docker exec "$PROD_APP_CONTAINER" php artisan optimize:clear || true docker exec "$DEMO_APP_CONTAINER" php artisan optimize:clear || true echo "[7/7] Riapertura siti" bring_apps_up MAINTENANCE_CONTAINERS=() echo "[7/7] Stato finale" "${COMPOSE_CMD[@]}" --env-file "$ENV_FILE" -f "$COMPOSE_FILE" ps echo "Update completato."