feat: Initial commit - Train tracking system
Some checks failed
Auto Tag on Merge to Main / auto-tag (push) Successful in 27s
CI - Lint and Build / lint-backend (push) Failing after 30s
CI - Lint and Build / lint-frontend (push) Failing after 2s
CI - Lint and Build / build-frontend (push) Has been skipped
CI - Lint and Build / docker-build-test (push) Has been skipped

Complete real-time train tracking system for Spanish railways (Renfe/Cercanías):

- Backend API (Node.js/Express) with GTFS-RT polling workers
- Frontend dashboard (React/Vite) with Leaflet maps
- Real-time updates via Socket.io WebSocket
- PostgreSQL/PostGIS database with Flyway migrations
- Redis caching layer
- Docker Compose configuration for development and production
- Gitea CI/CD workflows (lint, auto-tag, release)
- Production deployment with nginx + Let's Encrypt SSL

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Millaguie
2025-11-28 00:21:15 +01:00
commit 34c0cb50c7
64 changed files with 15577 additions and 0 deletions

263
Makefile Normal file
View File

@@ -0,0 +1,263 @@
# ============================================
# Makefile para Sistema de Tracking de Trenes
# ============================================
.PHONY: help start stop restart logs clean reset migrate status psql redis-cli \
test-start test-stop test-restart test-logs test-clean test-reset test-migrate \
build dev-start debug-start
# Variables
DOCKER_COMPOSE := docker-compose
ENV_FILE := .env
ENV_TEST_FILE := .env.testing
# Colores para output
COLOR_RESET := \033[0m
COLOR_INFO := \033[0;36m
COLOR_SUCCESS := \033[0;32m
COLOR_WARNING := \033[0;33m
COLOR_ERROR := \033[0;31m
# ============================================
# Ayuda por defecto
# ============================================
help: ## Mostrar esta ayuda
@echo "$(COLOR_INFO)Sistema de Tracking de Trenes - Comandos disponibles:$(COLOR_RESET)"
@echo ""
@echo "$(COLOR_SUCCESS)Entorno de Producción:$(COLOR_RESET)"
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \
grep -v "test-" | \
awk 'BEGIN {FS = ":.*?## "}; {printf " $(COLOR_INFO)%-20s$(COLOR_RESET) %s\n", $$1, $$2}'
@echo ""
@echo "$(COLOR_WARNING)Entorno de Testing:$(COLOR_RESET)"
@grep -E '^test-[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \
awk 'BEGIN {FS = ":.*?## "}; {printf " $(COLOR_INFO)%-20s$(COLOR_RESET) %s\n", $$1, $$2}'
@echo ""
# ============================================
# Comandos de Producción
# ============================================
start: ## Iniciar servicios en producción
@echo "$(COLOR_INFO)Iniciando servicios en modo producción...$(COLOR_RESET)"
@if [ ! -f $(ENV_FILE) ]; then \
echo "$(COLOR_WARNING)Archivo $(ENV_FILE) no encontrado, copiando desde .env.example$(COLOR_RESET)"; \
cp .env.example $(ENV_FILE); \
echo "$(COLOR_WARNING)Por favor, edita $(ENV_FILE) con tus credenciales$(COLOR_RESET)"; \
exit 1; \
fi
$(DOCKER_COMPOSE) --env-file $(ENV_FILE) up -d
@echo "$(COLOR_SUCCESS)✓ Servicios iniciados$(COLOR_RESET)"
@echo ""
@echo "$(COLOR_INFO)Acceso a servicios:$(COLOR_RESET)"
@echo " - Aplicación Web: http://localhost"
@echo " - API: http://localhost/api"
@echo ""
@echo "$(COLOR_INFO)Para ver logs: make logs$(COLOR_RESET)"
stop: ## Detener servicios
@echo "$(COLOR_INFO)Deteniendo servicios...$(COLOR_RESET)"
$(DOCKER_COMPOSE) --env-file $(ENV_FILE) down
@echo "$(COLOR_SUCCESS)✓ Servicios detenidos$(COLOR_RESET)"
restart: ## Reiniciar servicios
@echo "$(COLOR_INFO)Reiniciando servicios...$(COLOR_RESET)"
$(DOCKER_COMPOSE) --env-file $(ENV_FILE) restart
@echo "$(COLOR_SUCCESS)✓ Servicios reiniciados$(COLOR_RESET)"
logs: ## Ver logs de todos los servicios
$(DOCKER_COMPOSE) --env-file $(ENV_FILE) logs -f
logs-api: ## Ver logs del API
$(DOCKER_COMPOSE) --env-file $(ENV_FILE) logs -f api
logs-worker: ## Ver logs del worker
$(DOCKER_COMPOSE) --env-file $(ENV_FILE) logs -f worker
logs-db: ## Ver logs de PostgreSQL
$(DOCKER_COMPOSE) --env-file $(ENV_FILE) logs -f postgres
status: ## Ver estado de los servicios
$(DOCKER_COMPOSE) --env-file $(ENV_FILE) ps
clean: ## Detener y eliminar volúmenes (¡CUIDADO! Elimina datos)
@echo "$(COLOR_WARNING)¡ADVERTENCIA! Esto eliminará todos los datos.$(COLOR_RESET)"
@read -p "¿Continuar? [y/N]: " confirm; \
if [ "$$confirm" = "y" ] || [ "$$confirm" = "Y" ]; then \
echo "$(COLOR_INFO)Limpiando servicios y volúmenes...$(COLOR_RESET)"; \
$(DOCKER_COMPOSE) --env-file $(ENV_FILE) down -v; \
echo "$(COLOR_SUCCESS)✓ Limpieza completada$(COLOR_RESET)"; \
else \
echo "$(COLOR_INFO)Operación cancelada$(COLOR_RESET)"; \
fi
reset: clean start ## Reset completo (clean + start)
build: ## Construir imágenes Docker
@echo "$(COLOR_INFO)Construyendo imágenes Docker...$(COLOR_RESET)"
$(DOCKER_COMPOSE) --env-file $(ENV_FILE) build
@echo "$(COLOR_SUCCESS)✓ Imágenes construidas$(COLOR_RESET)"
migrate: ## Ejecutar migraciones de base de datos
@echo "$(COLOR_INFO)Ejecutando migraciones...$(COLOR_RESET)"
$(DOCKER_COMPOSE) --env-file $(ENV_FILE) --profile migration up flyway
@echo "$(COLOR_SUCCESS)✓ Migraciones completadas$(COLOR_RESET)"
migrate-info: ## Ver información de migraciones
@echo "$(COLOR_INFO)Información de migraciones:$(COLOR_RESET)"
$(DOCKER_COMPOSE) --env-file $(ENV_FILE) --profile migration run --rm flyway info
migrate-validate: ## Validar migraciones
@echo "$(COLOR_INFO)Validando migraciones...$(COLOR_RESET)"
$(DOCKER_COMPOSE) --env-file $(ENV_FILE) --profile migration run --rm flyway validate
@echo "$(COLOR_SUCCESS)✓ Migraciones válidas$(COLOR_RESET)"
psql: ## Conectar a PostgreSQL
@echo "$(COLOR_INFO)Conectando a PostgreSQL...$(COLOR_RESET)"
$(DOCKER_COMPOSE) --env-file $(ENV_FILE) exec postgres psql -U trenes_user -d trenes_db
redis-cli: ## Conectar a Redis
@echo "$(COLOR_INFO)Conectando a Redis...$(COLOR_RESET)"
$(DOCKER_COMPOSE) --env-file $(ENV_FILE) exec redis redis-cli
debug-start: ## Iniciar con herramientas de debug (Adminer, Redis Commander)
@echo "$(COLOR_INFO)Iniciando con herramientas de debug...$(COLOR_RESET)"
$(DOCKER_COMPOSE) --env-file $(ENV_FILE) --profile debug up -d
@echo "$(COLOR_SUCCESS)✓ Servicios iniciados con debug$(COLOR_RESET)"
@echo ""
@echo "$(COLOR_INFO)Herramientas de debug:$(COLOR_RESET)"
@echo " - Adminer (PostgreSQL): http://localhost:8080"
@echo " - Redis Commander: http://localhost:8081"
# ============================================
# Comandos de Testing
# ============================================
test-start: ## Iniciar servicios en modo testing
@echo "$(COLOR_WARNING)Iniciando servicios en modo TESTING...$(COLOR_RESET)"
@if [ ! -f $(ENV_TEST_FILE) ]; then \
echo "$(COLOR_ERROR)Archivo $(ENV_TEST_FILE) no encontrado$(COLOR_RESET)"; \
exit 1; \
fi
$(DOCKER_COMPOSE) --env-file $(ENV_TEST_FILE) --profile debug up -d
@echo "$(COLOR_SUCCESS)✓ Servicios de testing iniciados$(COLOR_RESET)"
@echo ""
@echo "$(COLOR_INFO)Acceso a servicios de testing:$(COLOR_RESET)"
@echo " - Aplicación Web: http://localhost"
@echo " - API: http://localhost/api"
@echo " - Adminer (PostgreSQL):http://localhost:8080"
@echo " - Redis Commander: http://localhost:8081"
@echo ""
@echo "$(COLOR_INFO)Para ver logs: make test-logs$(COLOR_RESET)"
test-stop: ## Detener servicios de testing
@echo "$(COLOR_INFO)Deteniendo servicios de testing...$(COLOR_RESET)"
$(DOCKER_COMPOSE) --env-file $(ENV_TEST_FILE) down
@echo "$(COLOR_SUCCESS)✓ Servicios de testing detenidos$(COLOR_RESET)"
test-restart: ## Reiniciar servicios de testing
@echo "$(COLOR_INFO)Reiniciando servicios de testing...$(COLOR_RESET)"
$(DOCKER_COMPOSE) --env-file $(ENV_TEST_FILE) restart
@echo "$(COLOR_SUCCESS)✓ Servicios de testing reiniciados$(COLOR_RESET)"
test-logs: ## Ver logs de testing
$(DOCKER_COMPOSE) --env-file $(ENV_TEST_FILE) logs -f
test-logs-api: ## Ver logs del API (testing)
$(DOCKER_COMPOSE) --env-file $(ENV_TEST_FILE) logs -f api
test-logs-worker: ## Ver logs del worker (testing)
$(DOCKER_COMPOSE) --env-file $(ENV_TEST_FILE) logs -f worker
test-status: ## Ver estado de servicios de testing
$(DOCKER_COMPOSE) --env-file $(ENV_TEST_FILE) ps
test-clean: ## Limpiar entorno de testing
@echo "$(COLOR_WARNING)Limpiando entorno de testing...$(COLOR_RESET)"
$(DOCKER_COMPOSE) --env-file $(ENV_TEST_FILE) down -v
@echo "$(COLOR_SUCCESS)✓ Entorno de testing limpiado$(COLOR_RESET)"
test-reset: test-clean test-start ## Reset completo de testing
test-migrate: ## Ejecutar migraciones en testing
@echo "$(COLOR_INFO)Ejecutando migraciones en testing...$(COLOR_RESET)"
$(DOCKER_COMPOSE) --env-file $(ENV_TEST_FILE) --profile migration up flyway
@echo "$(COLOR_SUCCESS)✓ Migraciones de testing completadas$(COLOR_RESET)"
test-psql: ## Conectar a PostgreSQL (testing)
@echo "$(COLOR_INFO)Conectando a PostgreSQL (testing)...$(COLOR_RESET)"
$(DOCKER_COMPOSE) --env-file $(ENV_TEST_FILE) exec postgres psql -U trenes_user -d trenes_db
test-redis-cli: ## Conectar a Redis (testing)
@echo "$(COLOR_INFO)Conectando a Redis (testing)...$(COLOR_RESET)"
$(DOCKER_COMPOSE) --env-file $(ENV_TEST_FILE) exec redis redis-cli
# ============================================
# Comandos de Desarrollo
# ============================================
dev-start: ## Iniciar en modo desarrollo (con hot-reload)
@echo "$(COLOR_INFO)Iniciando en modo desarrollo...$(COLOR_RESET)"
@echo "$(COLOR_WARNING)Asegúrate de tener node_modules instalados localmente$(COLOR_RESET)"
@echo ""
@echo "$(COLOR_INFO)Backend:$(COLOR_RESET) cd backend && npm install && npm run dev"
@echo "$(COLOR_INFO)Frontend:$(COLOR_RESET) cd frontend && npm install && npm run dev"
# ============================================
# Comandos de Utilidad
# ============================================
check-env: ## Verificar configuración de .env
@echo "$(COLOR_INFO)Verificando archivo .env...$(COLOR_RESET)"
@if [ -f $(ENV_FILE) ]; then \
echo "$(COLOR_SUCCESS)✓ Archivo $(ENV_FILE) existe$(COLOR_RESET)"; \
echo ""; \
echo "$(COLOR_INFO)Variables configuradas:$(COLOR_RESET)"; \
grep -v '^#' $(ENV_FILE) | grep -v '^$$' | sed 's/=.*/=***/' ; \
else \
echo "$(COLOR_ERROR)✗ Archivo $(ENV_FILE) no encontrado$(COLOR_RESET)"; \
echo "$(COLOR_WARNING)Ejecuta: cp .env.example .env$(COLOR_RESET)"; \
fi
check-test-env: ## Verificar configuración de .env.testing
@echo "$(COLOR_INFO)Verificando archivo .env.testing...$(COLOR_RESET)"
@if [ -f $(ENV_TEST_FILE) ]; then \
echo "$(COLOR_SUCCESS)✓ Archivo $(ENV_TEST_FILE) existe$(COLOR_RESET)"; \
else \
echo "$(COLOR_ERROR)✗ Archivo $(ENV_TEST_FILE) no encontrado$(COLOR_RESET)"; \
fi
backup-db: ## Crear backup de la base de datos
@echo "$(COLOR_INFO)Creando backup de la base de datos...$(COLOR_RESET)"
@mkdir -p backups
$(DOCKER_COMPOSE) --env-file $(ENV_FILE) exec -T postgres \
pg_dump -U trenes_user trenes_db > backups/backup_$$(date +%Y%m%d_%H%M%S).sql
@echo "$(COLOR_SUCCESS)✓ Backup creado en backups/$(COLOR_RESET)"
restore-db: ## Restaurar base de datos desde backup (usar: make restore-db FILE=backup.sql)
@if [ -z "$(FILE)" ]; then \
echo "$(COLOR_ERROR)Error: Debes especificar el archivo$(COLOR_RESET)"; \
echo "$(COLOR_INFO)Uso: make restore-db FILE=backups/backup_20250127.sql$(COLOR_RESET)"; \
exit 1; \
fi
@echo "$(COLOR_WARNING)Restaurando base de datos desde $(FILE)...$(COLOR_RESET)"
$(DOCKER_COMPOSE) --env-file $(ENV_FILE) exec -T postgres \
psql -U trenes_user trenes_db < $(FILE)
@echo "$(COLOR_SUCCESS)✓ Base de datos restaurada$(COLOR_RESET)"
cleanup-old-data: ## Limpiar datos antiguos (>90 días)
@echo "$(COLOR_INFO)Limpiando datos antiguos...$(COLOR_RESET)"
$(DOCKER_COMPOSE) --env-file $(ENV_FILE) exec postgres \
psql -U trenes_user -d trenes_db -c "SELECT cleanup_old_positions(90);"
@echo "$(COLOR_SUCCESS)✓ Datos antiguos eliminados$(COLOR_RESET)"
create-partition: ## Crear siguiente partición mensual
@echo "$(COLOR_INFO)Creando siguiente partición...$(COLOR_RESET)"
$(DOCKER_COMPOSE) --env-file $(ENV_FILE) exec postgres \
psql -U trenes_user -d trenes_db -c "SELECT create_next_partition();"
@echo "$(COLOR_SUCCESS)✓ Partición creada$(COLOR_RESET)"
# ============================================
# Target por defecto
# ============================================
.DEFAULT_GOAL := help