137 lines
5.6 KiB
Bash
Executable file
137 lines
5.6 KiB
Bash
Executable file
#!/bin/bash
|
|
# actualizar_app.sh — Trae del servidor git la última versión APROBADA (rama main).
|
|
#
|
|
# bash actualizar_app.sh ← buscar, probar y aplicar actualizaciones
|
|
# bash actualizar_app.sh --volver ← volver a la versión anterior
|
|
#
|
|
# Nunca toca tus datos, las copias de seguridad ni wheels/ (no están en el
|
|
# repositorio). Antes de aplicar prueba la versión nueva en una copia aparte y
|
|
# comprueba que lee tus datos; si algo falla, no cambia nada.
|
|
|
|
set -u
|
|
cd "$(dirname "$0")" || exit 1
|
|
export PYTHONDONTWRITEBYTECODE=1
|
|
pausa() { read -r -p "Pulsa Enter para cerrar..."; }
|
|
|
|
elegir_python() {
|
|
PY=python3
|
|
if [ -x /tmp/.cartera-venv/bin/python ]; then PY=/tmp/.cartera-venv/bin/python; fi
|
|
}
|
|
elegir_python
|
|
|
|
# Dónde está el programa ahora mismo
|
|
if [ -d programa/cartera ]; then CODIGO=programa; else CODIGO=.; fi
|
|
|
|
# El entorno vive en /tmp y desaparece al reiniciar el equipo: se recrea, para
|
|
# que las pruebas no fallen por dependencias que no están
|
|
if ! "$PY" -c "import requests, openpyxl" 2>/dev/null && [ -f "$CODIGO/entorno_python.sh" ]; then
|
|
echo "Preparando el entorno de Python (tras reiniciar el equipo, unos segundos)…"
|
|
bash "$CODIGO/entorno_python.sh"
|
|
elegir_python
|
|
fi
|
|
DATOS="$CODIGO/datos"
|
|
COPIAS="$CODIGO/backups"
|
|
|
|
command -v git >/dev/null || { echo "Falta git: sudo apt install git"; pausa; exit 1; }
|
|
[ -d .git ] || { echo "Esta carpeta aún no está enlazada con el servidor git."; pausa; exit 1; }
|
|
|
|
if [ -f "$DATOS/.cerrojo" ] && ! "$PY" -c "import fcntl, sys; fcntl.flock(open(sys.argv[1], 'a'), fcntl.LOCK_EX | fcntl.LOCK_NB)" "$DATOS/.cerrojo" 2>/dev/null; then
|
|
echo "✗ La cartera está abierta. Pulsa «Salir» en la aplicación y vuelve a ejecutar esto."
|
|
pausa; exit 1
|
|
fi
|
|
|
|
if [ "${1:-}" = "--volver" ]; then
|
|
guardada="$COPIAS/app_version_anterior"
|
|
[ -f "$guardada" ] || guardada=backups/app_version_anterior
|
|
[ -f "$guardada" ] || { echo "No hay versión anterior guardada."; pausa; exit 1; }
|
|
anterior=$(cat "$guardada")
|
|
if [ "$CODIGO" = "programa" ] && ! git cat-file -e "$anterior:programa/cartera/__init__.py" 2>/dev/null; then
|
|
echo "✗ La versión anterior es de antes de reorganizar la carpeta; no se puede volver automáticamente."
|
|
pausa; exit 1
|
|
fi
|
|
git reset --hard --quiet "$anterior" && echo "✓ Vuelto a la versión $(git log -1 --format='%h del %ad' --date=short). Tus datos no se tocan."
|
|
pausa; exit 0
|
|
fi
|
|
|
|
if [ -n "$(git status --porcelain --untracked-files=no)" ]; then
|
|
echo "⚠ Hay cambios locales en ficheros del programa; no se actualiza para no perderlos:"
|
|
git status --short --untracked-files=no
|
|
pausa; exit 1
|
|
fi
|
|
|
|
# Con doble clic desde el gestor de archivos se hereda el agente SSH del
|
|
# escritorio (llavero), no el de la terminal: si el agente de GPG tiene claves
|
|
# (la SSH vive en la llave de seguridad), se usa ese.
|
|
if command -v gpgconf >/dev/null; then
|
|
socket=$(gpgconf --list-dirs agent-ssh-socket 2>/dev/null)
|
|
if [ -n "$socket" ] && SSH_AUTH_SOCK="$socket" ssh-add -L >/dev/null 2>&1; then
|
|
export SSH_AUTH_SOCK="$socket"
|
|
fi
|
|
fi
|
|
if command -v gpg-connect-agent >/dev/null; then
|
|
gpg-connect-agent updatestartuptty /bye >/dev/null 2>&1 # el PIN se pide en esta ventana
|
|
fi
|
|
|
|
echo "Buscando actualizaciones en el servidor git… (si la llave de seguridad parpadea, tócala)"
|
|
if ! git fetch --quiet origin main; then
|
|
echo "✗ No se pudo conectar con el servidor git (¿estás en casa o con el túnel? ¿la llave de seguridad puesta?)."
|
|
pausa; exit 1
|
|
fi
|
|
if [ "$(git rev-parse HEAD)" = "$(git rev-parse origin/main)" ]; then
|
|
echo "✓ Ya tienes la última versión ($(git log -1 --format='%h del %ad' --date=short))."
|
|
pausa; exit 0
|
|
fi
|
|
if ! git merge-base --is-ancestor HEAD origin/main; then
|
|
echo "✗ La versión del servidor git no continúa la tuya; no se aplica automáticamente."
|
|
pausa; exit 1
|
|
fi
|
|
|
|
echo
|
|
echo "Novedades:"
|
|
git log --reverse --format=' • %s (%ad)' --date=short HEAD..origin/main
|
|
echo
|
|
echo "Ficheros que cambian:"
|
|
git diff --stat HEAD origin/main | tail -20
|
|
|
|
prueba=$(mktemp -d /tmp/cartera-prueba.XXXXXX)
|
|
trap 'rm -rf "$prueba"' EXIT
|
|
git archive origin/main | tar -x -C "$prueba"
|
|
if [ -d "$prueba/programa/cartera" ]; then codigo_nuevo="$prueba/programa"; else codigo_nuevo="$prueba"; fi
|
|
echo
|
|
echo "Probando la versión nueva en una copia aparte…"
|
|
if ! (cd "$codigo_nuevo" && "$PY" -m unittest discover -s pruebas >"$prueba/pruebas.log" 2>&1); then
|
|
echo "✗ Las pruebas de la versión nueva fallan: no se aplica nada."
|
|
tail -25 "$prueba/pruebas.log"
|
|
pausa; exit 1
|
|
fi
|
|
if [ -f "$DATOS/activos.jsonl" ]; then
|
|
if ! "$PY" -c "
|
|
import datetime as dt, sys
|
|
sys.path.insert(0, sys.argv[1])
|
|
from cartera.datos import leer
|
|
from cartera.vista import resumen
|
|
resumen(leer(sys.argv[2]), dt.date.today())" "$codigo_nuevo" "$PWD/$DATOS"; then
|
|
echo "✗ La versión nueva no puede leer tus datos: no se aplica nada."
|
|
pausa; exit 1
|
|
fi
|
|
fi
|
|
echo "✓ Pruebas superadas y tus datos se leen bien con la versión nueva."
|
|
echo
|
|
read -r -p "¿Aplicar la actualización? (s/N) " respuesta
|
|
case "$respuesta" in
|
|
s|S|si|sí|Si|Sí|SI) ;;
|
|
*) echo "No se ha cambiado nada."; pausa; exit 0 ;;
|
|
esac
|
|
|
|
mkdir -p "$COPIAS"
|
|
git rev-parse HEAD > "$COPIAS/app_version_anterior"
|
|
if [ -d "$DATOS" ]; then
|
|
tar -czf "$COPIAS/datos-$(date +%Y%m%d-%H%M%S).tar.gz" --exclude=.cerrojo --exclude=.ultima_sesion.json --exclude=./adjuntos -C "$DATOS" . 2>/dev/null
|
|
fi
|
|
if git merge --ff-only --quiet origin/main; then
|
|
echo "✓ Actualizada a: $(git log -1 --format='%h %s')"
|
|
echo " Si algo va mal: bash actualizar_app.sh --volver"
|
|
else
|
|
echo "✗ No se pudo aplicar."
|
|
fi
|
|
pausa
|