#!/usr/bin/env bash set -Eeuo pipefail ROOT="${ROOT:-/var/www/dhv2.korexlabs.com}" ZIP="${ZIP:-$ROOT/DH_V2_PATCH_DASHBOARD_D5_6_3.zip}" STAMP="$(date +%Y%m%d_%H%M%S)" STAGE="/root/dhv2-dashboard-d563-stage-$STAMP" BACKUP_ROOT="/root/DH_V2_BACKUPS" PRE_BACKUP="$BACKUP_ROOT/D5_6_3_DASH_PRE_$STAMP" POST_BACKUP="$BACKUP_ROOT/D5_6_3_DASH_OK_$STAMP" TEST_IMAGE="dhv2-web:d563-test" cleanup() { rm -rf "$STAGE" docker image rm "$TEST_IMAGE" >/dev/null 2>&1 || true } trap cleanup EXIT trap 'echo; echo "ERROR D5.6.3 dashboard en línea $LINENO: $BASH_COMMAND"' ERR cd "$ROOT" test -f "$ZIP" CURRENT_WEB="$(node -p "require('./web-v2/package.json').version")" [[ "$CURRENT_WEB" == "0.19.6-2" ]] || { echo "ERROR: este patch requiere WEB 0.19.6-2. Actual: $CURRENT_WEB"; exit 1; } echo '[1/7] Staging del patch' mkdir -p "$STAGE" cp -a web-v2 "$STAGE/web-v2" unzip -oq "$ZIP" 'web-v2/*' -d "$STAGE" [[ "$(node -p "require('$STAGE/web-v2/package.json').version")" == "0.19.6-3" ]] grep -Fq "APP_PHASE = 'Fase D5.6.3 · Navegación contextual'" "$STAGE/web-v2/src/config/version.ts" echo '[2/7] Build web en staging' docker build -t "$TEST_IMAGE" "$STAGE/web-v2" echo '[3/7] Validaciones de navegación' grep -Fq 'OperationalContextBar' "$STAGE/web-v2/src/layout/AppLayout.tsx" grep -Fq 'OperationalContextProvider' "$STAGE/web-v2/src/app/App.tsx" grep -Fq 'path="/planificacion"' "$STAGE/web-v2/src/app/App.tsx" ! grep -Fq "label: 'Planificación'" "$STAGE/web-v2/src/layout/AppLayout.tsx" grep -Fq 'Planificar inspección' "$STAGE/web-v2/src/pages/InspectionVisitsPage.tsx" grep -Fq 'inspection-status-tabs' "$STAGE/web-v2/src/pages/InspectionVisitsPage.tsx" grep -Fq 'useOperationalContext' "$STAGE/web-v2/src/pages/AssetsPage.tsx" grep -Fq 'useOperationalContext' "$STAGE/web-v2/src/pages/ActsPage.tsx" grep -Fq 'useOperationalContext' "$STAGE/web-v2/src/pages/ReportsPage.tsx" grep -Fq 'useOperationalContext' "$STAGE/web-v2/src/pages/FindingsPage.tsx" grep -Fq 'operationalContext.areaId' "$STAGE/web-v2/src/pages/InspectionVisitEditorPage.tsx" echo '[4/7] Backup PRE del dashboard' mkdir -p "$PRE_BACKUP"; chmod 700 "$PRE_BACKUP" tar -czf "$PRE_BACKUP/web-v2-source.tar.gz" --exclude='web-v2/node_modules' --exclude='web-v2/dist' web-v2 printf 'WEB previa=%s\nAPI sin cambios=%s\n' "$CURRENT_WEB" "$(node -p "require('./api-v3/package.json').version")" > "$PRE_BACKUP/BASE_VERSION.txt" ( cd "$PRE_BACKUP" && sha256sum web-v2-source.tar.gz BASE_VERSION.txt > SHA256SUMS.txt && sha256sum -c SHA256SUMS.txt ) echo '[5/7] Aplicando patch incremental' unzip -oq "$ZIP" 'web-v2/*' 'scripts/check-dashboard-d5-6-3.sh' 'scripts/deploy-dashboard-d5-6-3.sh' -d "$ROOT" chmod +x scripts/check-dashboard-d5-6-3.sh scripts/deploy-dashboard-d5-6-3.sh bash scripts/check-dashboard-d5-6-3.sh echo '[6/7] Build y recreación del dashboard' docker compose build web docker compose up -d --force-recreate web for i in $(seq 1 30); do WEB_ADDR="$(docker compose port web 80 2>/dev/null | tail -1)" WEB_PORT="${WEB_ADDR##*:}" if [[ "$WEB_PORT" =~ ^[0-9]+$ ]] && curl -fsS "http://127.0.0.1:$WEB_PORT/" >/dev/null 2>&1; then break; fi if [[ "$i" == "30" ]]; then docker compose logs --tail=160 web; exit 1; fi sleep 1 done echo '[7/7] Backup POST' mkdir -p "$POST_BACKUP"; chmod 700 "$POST_BACKUP" tar -czf "$POST_BACKUP/web-v2-source.tar.gz" --exclude='web-v2/node_modules' --exclude='web-v2/dist' web-v2 cp -a "$ZIP" "$POST_BACKUP/" printf 'D5.6.3 DASHBOARD OK\nWEB final=0.19.6-3\nAPI sin cambios=%s\n' "$(node -p "require('./api-v3/package.json').version")" > "$POST_BACKUP/BACKUP_OK.txt" ( cd "$POST_BACKUP" && sha256sum web-v2-source.tar.gz "$(basename "$ZIP")" BACKUP_OK.txt > SHA256SUMS.txt && sha256sum -c SHA256SUMS.txt ) echo echo 'D5.6.3 DASHBOARD: OK' echo 'WEB: 0.19.6-3' echo "API: $(node -p "require('./api-v3/package.json').version") (sin cambios)" echo "Backup PRE: $PRE_BACKUP" echo "Backup POST: $POST_BACKUP"