Repository navigation
Expand file tree
/
Copy pathdev.sh
More file actions
executable file
·162 lines (142 loc) · 5.79 KB
/
Copy pathdev.sh
File metadata and controls
executable file
·162 lines (142 loc) · 5.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#!/usr/bin/env bash
#
# Levanta la plataforma entera con un solo comando:
#
# ./dev.sh
#
# No hay servidor propio que arrancar —Supabase ES el backend—, así que "todo" es:
# dependencias puestas, credenciales en su sitio, esquema al día, y el front escuchando.
#
# Lo que comprueba antes de arrancar no es ceremonia: el esquema se pega a mano en el
# editor de Supabase, así que es normal que el repo vaya por delante de la base. Que la
# interfaz salga vacía por eso, y descubrirlo delante del jurado, es el fallo caro.
#
# ./dev.sh --check solo comprueba, no arranca nada
# ./dev.sh --seed siembra datos de ejemplo antes de arrancar
set -euo pipefail
cd "$(dirname "$0")"
VERDE=$'\033[32m'; ROJO=$'\033[31m'; AMBAR=$'\033[33m'; FIN=$'\033[0m'
ok() { echo " ${VERDE}ok${FIN} $1"; }
aviso() { echo " ${AMBAR}aviso${FIN} $1"; }
error() { echo " ${ROJO}error${FIN} $1"; }
SOLO_CHECK=false
SEMBRAR=false
for arg in "$@"; do
case "$arg" in
--check) SOLO_CHECK=true ;;
--seed) SEMBRAR=true ;;
-h|--help) sed -n '3,15p' "$0" | sed 's/^# \?//'; exit 0 ;;
*) error "opción desconocida: $arg"; exit 2 ;;
esac
done
echo "── credenciales ──────────────────────────────────────────────"
# Un solo fichero de credenciales, en la raíz: lo lee load_env() del lado Python y,
# a través de frontend/next.config.ts, también el front. Dos copias se desincronizan
# solas, y ya pasó una vez.
falta_env=false
if [[ ! -f .env ]]; then
error "falta .env"
falta_env=true
else
for clave in SUPABASE_URL SUPABASE_ANON_KEY SUPABASE_SERVICE_KEY; do
if grep -qE "^${clave}=[^[:space:]]" .env; then
ok ".env: $clave"
else
error ".env: $clave sin valor"
falta_env=true
fi
done
fi
if [[ -f frontend/.env.local ]]; then
aviso "frontend/.env.local existe y ya no hace falta; sus valores ganarían al .env"
fi
if $falta_env; then
echo
echo " Copia .env.example a .env y rellena los valores desde Supabase:"
echo " Project Settings -> Data API -> Project URL y API Keys."
exit 1
fi
echo "── dependencias ──────────────────────────────────────────────"
# El SDK de Python solo hace falta para sembrar, subir episodios o correr los tests;
# el front no lo necesita. Si no hay venv se dice y se sigue.
if [[ ! -d .venv ]]; then
aviso "sin .venv (solo hace falta para backend/tests y los guiones de datos)"
echo " python3 -m venv .venv && .venv/bin/pip install -e './backend[dev]'"
else
if .venv/bin/python -c "import theker_telemetry" 2>/dev/null; then
ok "theker_telemetry instalado"
else
aviso "theker_telemetry no instalado; instalando"
.venv/bin/pip install -q -e './backend[dev]'
ok "instalado"
fi
fi
# package-lock manda: si node_modules va por detrás, npm ci lo deja exacto. Pasa cada
# vez que alguien fusiona una rama que añade una dependencia.
if [[ ! -d frontend/node_modules ]] \
|| [[ frontend/package-lock.json -nt frontend/node_modules ]]; then
aviso "dependencias del front desactualizadas; npm ci"
(cd frontend && npm ci --silent)
fi
ok "node_modules al día"
echo "── esquema en Supabase ───────────────────────────────────────"
# Se comprueba lo que de verdad rompe la interfaz, no que "haya conexión": una columna
# que el front consulta y la vista no proyecta devuelve 400 y deja la pantalla vacía.
if [[ -d .venv ]]; then
.venv/bin/python - <<'PY' || exit 1
import sys
sys.path.insert(0, "backend")
from pathlib import Path
from theker_telemetry import Supabase
VERDE, ROJO, FIN = "\033[32m", "\033[31m", "\033[0m"
cliente = Supabase.from_env(Path("."))
if cliente is None:
print(f" {ROJO}error{FIN} .env sin SUPABASE_URL o SUPABASE_SERVICE_KEY")
raise SystemExit(1)
# Cada entrada es (relación, columna que el front necesita, fichero que la trae). Si
# falla alguna, ese .sql está sin pegar en el editor de Supabase.
ESPERADO = [
("v_episode_summary", "started_at", "002_design.sql"),
("v_episode_summary", "config", "002_design.sql"),
("v_run_summary", "config", "002_design.sql"),
("snapshots", "url", "003_snapshots.sql"),
]
faltan = set()
for relacion, columna, fichero in ESPERADO:
try:
cliente.get(relacion, select=columna, limit=1)
except RuntimeError as err:
print(f" {ROJO}error{FIN} {relacion}.{columna}: {str(err)[:90]}")
faltan.add(fichero)
else:
print(f" {VERDE}ok{FIN} {relacion}.{columna}")
if faltan:
print()
print(" Pega en el SQL editor de Supabase, en orden:")
for fichero in sorted(faltan):
print(f" backend/sql/{fichero}")
raise SystemExit(1)
runs = cliente.get("v_run_summary", select="task,synthetic,episodes")
medidos = sum(1 for r in runs if not r["synthetic"])
print(f" {VERDE}ok{FIN} {len(runs)} ejecuciones "
f"({medidos} medidas, {len(runs) - medidos} sembradas), "
f"{sum(r['episodes'] for r in runs)} episodios")
if not runs:
print(" sin datos: ./dev.sh --seed los genera")
PY
else
aviso "sin .venv: no puedo comprobar el esquema"
fi
if $SEMBRAR; then
echo "── datos de ejemplo ──────────────────────────────────────────"
.venv/bin/python backend/seed/ejemplo_contrato.py
fi
if $SOLO_CHECK; then
echo
ok "todo listo (no se arranca nada con --check)"
exit 0
fi
echo "── front ─────────────────────────────────────────────────────"
echo " http://localhost:3000 (Ctrl+C para parar)"
echo
exec npm --prefix frontend run dev