2026-01-08 04:00:41 +00:00
|
|
|
#!/bin/bash
|
2026-01-09 13:18:58 +00:00
|
|
|
# K3s Deployment Script con Tests y Smoke Tests
|
|
|
|
|
# Uso: ./deploy.sh [all|test|build|deploy|smoke|status|clean|rollback]
|
2026-01-08 18:34:38 +00:00
|
|
|
set -euo pipefail
|
2026-01-08 04:00:41 +00:00
|
|
|
|
2026-01-08 15:49:32 +00:00
|
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
|
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
2026-01-08 04:00:41 +00:00
|
|
|
|
2026-01-08 18:34:38 +00:00
|
|
|
# Colores
|
|
|
|
|
RED='\033[0;31m'
|
|
|
|
|
GREEN='\033[0;32m'
|
|
|
|
|
YELLOW='\033[1;33m'
|
|
|
|
|
NC='\033[0m'
|
2026-01-08 04:00:41 +00:00
|
|
|
|
2026-01-08 18:34:38 +00:00
|
|
|
# Configuración
|
2026-01-09 13:18:58 +00:00
|
|
|
NAMESPACE="academia"
|
|
|
|
|
DOMAIN="academia.ingeniumcodex.com"
|
|
|
|
|
API_IMAGE="student-api:latest"
|
|
|
|
|
FRONTEND_IMAGE="student-frontend:latest"
|
2026-01-08 04:00:41 +00:00
|
|
|
|
2026-01-08 18:34:38 +00:00
|
|
|
log() { echo -e "${GREEN}[$(date +%T)]${NC} $1"; }
|
|
|
|
|
warn() { echo -e "${YELLOW}[$(date +%T)]${NC} $1"; }
|
2026-01-09 13:18:58 +00:00
|
|
|
err() { echo -e "${RED}[$(date +%T)]${NC} $1" >&2; exit 1; }
|
2026-01-08 04:00:41 +00:00
|
|
|
|
2026-01-09 13:18:58 +00:00
|
|
|
pull_code() {
|
|
|
|
|
log "=== Actualizando código ==="
|
2026-01-08 18:34:38 +00:00
|
|
|
cd "$PROJECT_ROOT"
|
2026-01-09 13:18:58 +00:00
|
|
|
git fetch origin main
|
|
|
|
|
git reset --hard origin/main
|
|
|
|
|
log "✓ Código actualizado"
|
|
|
|
|
}
|
2026-01-08 04:00:41 +00:00
|
|
|
|
2026-01-09 13:18:58 +00:00
|
|
|
run_tests() {
|
|
|
|
|
log "=== Ejecutando tests ==="
|
|
|
|
|
cd "$PROJECT_ROOT"
|
|
|
|
|
dotnet test tests/Domain.Tests --verbosity minimal || err "Domain tests fallaron"
|
|
|
|
|
dotnet test tests/Application.Tests --verbosity minimal || err "Application tests fallaron"
|
|
|
|
|
log "✓ Todos los tests pasaron"
|
2026-01-08 18:34:38 +00:00
|
|
|
}
|
|
|
|
|
|
2026-01-09 13:18:58 +00:00
|
|
|
build_images() {
|
|
|
|
|
log "=== Construyendo imágenes Docker (paralelo) ==="
|
|
|
|
|
cd "$PROJECT_ROOT"
|
2026-01-08 18:34:38 +00:00
|
|
|
|
2026-01-09 13:18:58 +00:00
|
|
|
sudo docker build -t "$API_IMAGE" -f deploy/docker/Dockerfile.api . &
|
2026-01-08 18:34:38 +00:00
|
|
|
PID_API=$!
|
2026-01-09 13:18:58 +00:00
|
|
|
sudo docker build -t "$FRONTEND_IMAGE" -f deploy/docker/Dockerfile.frontend . &
|
|
|
|
|
PID_FE=$!
|
2026-01-08 18:34:38 +00:00
|
|
|
|
2026-01-09 13:18:58 +00:00
|
|
|
wait $PID_API && log "✓ API imagen construida" || err "Error construyendo API"
|
|
|
|
|
wait $PID_FE && log "✓ Frontend imagen construida" || err "Error construyendo Frontend"
|
2026-01-08 18:34:38 +00:00
|
|
|
}
|
|
|
|
|
|
2026-01-09 13:18:58 +00:00
|
|
|
import_images() {
|
|
|
|
|
log "=== Importando imágenes a K3s ==="
|
|
|
|
|
sudo sh -c "docker save $API_IMAGE | k3s ctr images import -"
|
|
|
|
|
sudo sh -c "docker save $FRONTEND_IMAGE | k3s ctr images import -"
|
|
|
|
|
log "✓ Imágenes importadas"
|
|
|
|
|
}
|
2026-01-08 18:34:38 +00:00
|
|
|
|
2026-01-09 13:18:58 +00:00
|
|
|
deploy_k8s() {
|
|
|
|
|
log "=== Desplegando en K3s ==="
|
|
|
|
|
cd "$SCRIPT_DIR"
|
|
|
|
|
sudo kubectl apply -k .
|
|
|
|
|
sudo kubectl rollout restart deployment/student-api deployment/student-frontend -n $NAMESPACE
|
2026-01-08 18:34:38 +00:00
|
|
|
|
2026-01-09 13:18:58 +00:00
|
|
|
log "=== Esperando rollout ==="
|
|
|
|
|
sudo kubectl rollout status deployment/student-api -n $NAMESPACE --timeout=180s
|
|
|
|
|
sudo kubectl rollout status deployment/student-frontend -n $NAMESPACE --timeout=60s
|
|
|
|
|
log "✓ Deploy completado"
|
|
|
|
|
}
|
2026-01-08 18:34:38 +00:00
|
|
|
|
2026-01-09 13:18:58 +00:00
|
|
|
smoke_tests() {
|
|
|
|
|
log "=== Ejecutando smoke tests ==="
|
|
|
|
|
sleep 10
|
|
|
|
|
|
|
|
|
|
# Health check
|
|
|
|
|
if curl -sf https://$DOMAIN/health | grep -q '"status":"Healthy"'; then
|
|
|
|
|
log "✓ Health check API"
|
|
|
|
|
else
|
|
|
|
|
err "Health check falló"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Frontend
|
|
|
|
|
if curl -sf https://$DOMAIN/ | grep -q 'Sistema de Estudiantes'; then
|
|
|
|
|
log "✓ Frontend check"
|
|
|
|
|
else
|
|
|
|
|
err "Frontend check falló"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# GraphQL
|
|
|
|
|
if curl -sf -X POST https://$DOMAIN/graphql \
|
|
|
|
|
-H "Content-Type: application/json" \
|
|
|
|
|
-d '{"query":"{ subjects { id name } }"}' | grep -q '"subjects"'; then
|
|
|
|
|
log "✓ GraphQL check"
|
|
|
|
|
else
|
|
|
|
|
err "GraphQL check falló"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Database
|
|
|
|
|
if curl -sf https://$DOMAIN/health | grep -q '"name":"database","status":"Healthy"'; then
|
|
|
|
|
log "✓ Database check"
|
|
|
|
|
else
|
|
|
|
|
err "Database check falló"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
log "✓ Todos los smoke tests pasaron"
|
2026-01-08 18:34:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
show_status() {
|
2026-01-09 13:18:58 +00:00
|
|
|
log "=== Estado del cluster ==="
|
|
|
|
|
sudo kubectl get pods -n $NAMESPACE -o wide
|
2026-01-08 18:34:38 +00:00
|
|
|
echo ""
|
2026-01-09 13:18:58 +00:00
|
|
|
sudo kubectl get svc -n $NAMESPACE
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rollback() {
|
|
|
|
|
warn "=== Rollback ==="
|
|
|
|
|
sudo kubectl rollout undo deployment/student-api deployment/student-frontend -n $NAMESPACE
|
|
|
|
|
log "✓ Rollback completado"
|
2026-01-08 18:34:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
clean() {
|
|
|
|
|
warn "=== Limpiando namespace $NAMESPACE ==="
|
2026-01-09 13:18:58 +00:00
|
|
|
sudo kubectl delete namespace $NAMESPACE --ignore-not-found
|
2026-01-08 18:34:38 +00:00
|
|
|
log "✓ Namespace eliminado"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Main
|
2026-01-09 13:18:58 +00:00
|
|
|
case "${1:-help}" in
|
|
|
|
|
all)
|
|
|
|
|
pull_code
|
|
|
|
|
run_tests
|
2026-01-08 18:34:38 +00:00
|
|
|
build_images
|
2026-01-09 13:18:58 +00:00
|
|
|
import_images
|
|
|
|
|
deploy_k8s
|
|
|
|
|
smoke_tests
|
|
|
|
|
show_status
|
2026-01-08 18:34:38 +00:00
|
|
|
;;
|
2026-01-09 13:18:58 +00:00
|
|
|
test)
|
|
|
|
|
run_tests
|
|
|
|
|
;;
|
|
|
|
|
build)
|
|
|
|
|
build_images
|
|
|
|
|
import_images
|
2026-01-08 18:34:38 +00:00
|
|
|
;;
|
|
|
|
|
deploy)
|
2026-01-09 13:18:58 +00:00
|
|
|
deploy_k8s
|
2026-01-08 18:34:38 +00:00
|
|
|
;;
|
2026-01-09 13:18:58 +00:00
|
|
|
smoke)
|
|
|
|
|
smoke_tests
|
2026-01-08 18:34:38 +00:00
|
|
|
;;
|
|
|
|
|
status)
|
|
|
|
|
show_status
|
|
|
|
|
;;
|
2026-01-09 13:18:58 +00:00
|
|
|
rollback)
|
|
|
|
|
rollback
|
|
|
|
|
;;
|
2026-01-08 18:34:38 +00:00
|
|
|
clean)
|
|
|
|
|
clean
|
|
|
|
|
;;
|
|
|
|
|
*)
|
2026-01-09 13:18:58 +00:00
|
|
|
echo "Uso: $0 [all|test|build|deploy|smoke|status|rollback|clean]"
|
|
|
|
|
echo ""
|
|
|
|
|
echo " all - Pull, test, build, deploy y smoke tests"
|
|
|
|
|
echo " test - Solo ejecutar tests"
|
|
|
|
|
echo " build - Construir e importar imágenes"
|
|
|
|
|
echo " deploy - Solo desplegar a K8s"
|
|
|
|
|
echo " smoke - Solo ejecutar smoke tests"
|
|
|
|
|
echo " status - Ver estado del cluster"
|
|
|
|
|
echo " rollback - Revertir último deploy"
|
|
|
|
|
echo " clean - Eliminar namespace"
|
|
|
|
|
exit 0
|
2026-01-08 18:34:38 +00:00
|
|
|
;;
|
|
|
|
|
esac
|
|
|
|
|
|
|
|
|
|
log "=== Completado ==="
|