Agrego carpeta del source sql de la Base de Datos

This commit is contained in:
Pablo
2026-08-22 19:10:49 -03:00
parent 11e36bd6c2
commit 88d724fbcf
94 changed files with 7820 additions and 0 deletions
+56
View File
@@ -0,0 +1,56 @@
#!/usr/bin/env bash
set -euo pipefail
# database/backup/dump.sh
#
# Dump + comprimir + cifrar + subir a Drive. Implementa US-B04 de
# Documentation/Backlog/Backups.md.
#
# Falla ruidoso a propósito (invariante 3 del backlog): `set -e` corta el
# script ante el primer error, así el job de GitHub Actions que lo llama
# queda en rojo y GitHub avisa por mail. No hay try/catch que trague nada.
#
# Variables de entorno requeridas:
# DATABASE_URL connection string del SESSION POOLER de Supabase.
# El transaction pooler rompe pg_dump (ver US-B03).
# BACKUP_PASSPHRASE passphrase simétrica de cifrado (gpg).
# RCLONE_REMOTE_NAME nombre del remote configurado en rclone.conf
# (ej: "gdrive").
# GDRIVE_FOLDER_ID ID de la carpeta de Drive destino (no el nombre).
#
# Alcance del dump (invariante 6): esquemas public + internal únicamente.
# NUNCA auth ni el resto de los esquemas internos de Supabase — por eso se
# usa --schema explícito en vez de un dump completo.
: "${DATABASE_URL:?Falta DATABASE_URL (session pooler de Supabase)}"
: "${BACKUP_PASSPHRASE:?Falta BACKUP_PASSPHRASE}"
: "${RCLONE_REMOTE_NAME:?Falta RCLONE_REMOTE_NAME (ej: gdrive)}"
: "${GDRIVE_FOLDER_ID:?Falta GDRIVE_FOLDER_ID}"
FECHA="$(date -u +%Y-%m-%d)"
BASE="soma-backup-${FECHA}"
SQL="${BASE}.sql"
GZ="${SQL}.gz"
ENC="${GZ}.gpg"
cleanup() {
rm -f "$SQL" "$GZ" "$ENC"
}
trap cleanup EXIT
echo "== Dump de public + internal (sin auth) -> ${SQL} =="
pg_dump "$DATABASE_URL" --schema=public --schema=internal --file="$SQL"
echo "== Comprimiendo -> ${GZ} =="
gzip -f "$SQL"
echo "== Cifrando (AES256 simétrico) -> ${ENC} =="
gpg --batch --yes --pinentry-mode loopback \
--passphrase "$BACKUP_PASSPHRASE" \
--symmetric --cipher-algo AES256 \
--output "$ENC" "$GZ"
echo "== Subiendo ${ENC} a ${RCLONE_REMOTE_NAME}: (carpeta ${GDRIVE_FOLDER_ID}) =="
rclone --drive-root-folder-id="$GDRIVE_FOLDER_ID" copy "$ENC" "${RCLONE_REMOTE_NAME}:"
echo "OK: ${ENC} subido y verificado."
+86
View File
@@ -0,0 +1,86 @@
#!/usr/bin/env bash
set -euo pipefail
# database/backup/rotate.sh
#
# Rotación sin estado de los backups en Drive. Implementa US-B05 de
# Documentation/Backlog/Backups.md §3.
#
# Esquema de retención (recalculado desde cero en cada corrida, sin leer
# ni escribir ningún registro de "qué es ancla" — invariante 5):
# - Los 3 backups más recientes, sin importar la fecha.
# - Un ancla mensual por cada uno de los últimos 6 meses cerrados (el
# backup más nuevo de ese mes).
# Todo lo que no entra en ese conjunto se borra.
#
# Invariante 4: solo se tocan archivos que matchean exactamente el patrón
# soma-backup-AAAA-MM-DD.sql.gz.gpg dentro de la carpeta indicada. Nunca
# se borra nada más.
#
# Variables de entorno requeridas:
# RCLONE_REMOTE_NAME nombre del remote configurado en rclone.conf.
# GDRIVE_FOLDER_ID ID de la carpeta de Drive a rotar.
: "${RCLONE_REMOTE_NAME:?Falta RCLONE_REMOTE_NAME (ej: gdrive)}"
: "${GDRIVE_FOLDER_ID:?Falta GDRIVE_FOLDER_ID}"
REMOTE="${RCLONE_REMOTE_NAME}:"
PATTERN='^soma-backup-([0-9]{4}-[0-9]{2}-[0-9]{2})\.sql\.gz\.gpg$'
mapfile -t files < <(rclone --drive-root-folder-id="$GDRIVE_FOLDER_ID" lsf "$REMOTE" --files-only)
declare -A file_by_date=()
dates=()
for f in "${files[@]}"; do
if [[ "$f" =~ $PATTERN ]]; then
d="${BASH_REMATCH[1]}"
file_by_date["$d"]="$f"
dates+=("$d")
fi
done
if [ "${#dates[@]}" -eq 0 ]; then
echo "No hay backups con el patrón esperado en ${REMOTE} (carpeta ${GDRIVE_FOLDER_ID}). Nada que rotar."
exit 0
fi
# Fechas ordenadas descendente (más nueva primero).
IFS=$'\n' sorted=($(printf '%s\n' "${dates[@]}" | sort -r)); unset IFS
declare -A keep=()
# Los 3 backups más recientes.
for i in 0 1 2; do
d="${sorted[$i]:-}"
[ -n "$d" ] && keep["$d"]=1
done
# Ancla mensual de cada uno de los últimos 6 meses cerrados (el actual no
# cuenta: todavía no cerró).
hoy_mes_uno="$(date -u +%Y-%m-01)"
for i in 1 2 3 4 5 6; do
ym="$(date -u -d "${hoy_mes_uno} -${i} month" +%Y-%m)"
for d in "${sorted[@]}"; do
if [[ "$d" == "${ym}"* ]]; then
keep["$d"]=1 # sorted desc: el primer match del mes es el más nuevo
break
fi
done
done
echo "== Conservar (${#keep[@]} de ${#sorted[@]}) =="
for d in "${sorted[@]}"; do
[ -n "${keep[$d]:-}" ] && echo " ${file_by_date[$d]}"
done
echo "== Borrar =="
borrados=0
for d in "${sorted[@]}"; do
if [ -z "${keep[$d]:-}" ]; then
echo " ${file_by_date[$d]}"
rclone --drive-root-folder-id="$GDRIVE_FOLDER_ID" deletefile "${REMOTE}${file_by_date[$d]}"
borrados=$((borrados + 1))
fi
done
echo "OK: ${borrados} archivo(s) borrado(s), ${#keep[@]} conservado(s)."