Introducción
Un proyecto de ingeniería de datos puede empezar con una necesidad concreta y pocas herramientas: obtener datos públicos, transformarlos de forma reproducible y facilitar su consulta. Para este proyecto individual elegí comparar el clima de Lima, Arequipa y Cusco mediante una ventana de 30 días.
El código está en el repositorio público data-engineering-pipeline y el reporte puede consultarse en GitHub Pages. Ambos enlaces fueron comprobados después del primer despliegue.
Video de presentación
En este video muestro la funcionalidad de la solución: la consulta del reporte, la comparación entre ciudades, la descarga de datos y la actualización automatizada.
Ver la demostración funcional en YouTube.
El problema
Las respuestas de una API son útiles, pero no bastan para analizar datos de forma repetible. Pueden faltar fechas, aparecer nulos o acumularse duplicados si cargamos varias veces el mismo período. Además, una comparación entre ciudades necesita unidades, fechas y reglas de cálculo consistentes.
Mi objetivo fue construir un flujo pequeño que convierta respuestas meteorológicas en dos productos: una tabla diaria limpia y un resumen por ciudad. El resultado se exporta a un reporte HTML y archivos CSV.
Arquitectura y herramientas
Open-Meteo → Python → JSON crudo + DuckDB raw.weather
↓
dbt stg_weather
↓
dbt city_summary
↓
pruebas de calidad
↓
HTML + CSV + metadatos
↓
GitHub Pages, tras CD
- Python 3.12 extrae respuestas HTTP, valida los datos y exporta los resultados.
- DuckDB almacena tablas analíticas en un archivo, sin administrar un servidor.
- dbt Core y dbt-duckdb gestionan las transformaciones SQL, sus dependencias y las pruebas.
- GitHub Actions ejecuta CI, la actualización diaria y el despliegue.
- GitHub Pages es el destino configurado para alojar el reporte estático públicamente.
No se utilizan servicios ni credenciales de AWS. La arquitectura usa GitHub como plataforma SaaS y no necesita un proceso Python funcionando permanentemente. Para esta escala, dbt permite demostrar transformación y calidad sin desplegar un orquestador de larga duración.
Implementación
1. Extraer una ventana consistente
La fuente es la API histórica de Open-Meteo. Para cada ciudad se solicitan temperatura máxima, mínima y precipitación diaria. La ventana termina siete días antes de la fecha actual en Lima para dejar margen a la disponibilidad del histórico.
Antes de cargar, Python comprueba las 30 fechas esperadas, las longitudes de las listas, valores numéricos finitos, coherencia entre mínima y máxima y precipitación no negativa. Cada petición tiene un timeout y hasta tres intentos. Si falla, la ejecución termina con error: no reemplaza los datos reales por datos sintéticos.
2. Cargar sin duplicar
Después de validar las tres ciudades, una transacción reemplaza raw.weather en DuckDB. Es una reconstrucción completa de una ventana pequeña. Repetir una ejecución no debe multiplicar registros.
Se conservan también las respuestas JSON para inspeccionar la fuente. Este diseño no pretende guardar un histórico incremental ilimitado: prioriza que el proyecto pueda entenderse, ejecutarse y evaluarse con facilidad.
3. Transformar con dbt
stg_weather tipifica los campos. city_summary utiliza ref('stg_weather'), por lo que dbt conoce el orden de construcción:
select city, min(date) as start_date, max(date) as end_date,
count(*) as days,
round(avg((temperature_max + temperature_min) / 2), 2) as mean_midpoint_c,
round(max(temperature_max), 2) as highest_c,
round(min(temperature_min), 2) as lowest_c,
round(sum(precipitation_mm), 2) as total_precipitation_mm
from {{ ref('stg_weather') }}
group by city
El indicador mean_midpoint_c es el promedio del punto medio entre mínima y máxima diaria. Lo etiqueté así porque no equivale a calcular una media de temperaturas horarias. La fuente contiene reanálisis; tampoco debe presentarse como medición de una estación local.
4. Probar y generar la salida
dbt build construye dos modelos y ejecuta nueve pruebas de datos: campos obligatorios, unicidad, duplicados, rangos y continuidad de la ventana. Solo después se exportan el reporte y los CSV.
Las pruebas unitarias de Python cubren respuestas válidas, mediciones inválidas, fechas incorrectas y fallos de red. El modo --offline usa una fixture sintética identificada como TEST y escribe en otra carpeta. CI lo ejecuta dos veces para comprobar idempotencia y agregados conocidos.
Para reproducirlo en Linux o macOS con Python 3.12:
python3.12 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
python -m unittest discover -s tests -v
python -m pipeline.run --offline --end-date 2026-01-30
python -m pipeline.run
El README incluye los comandos equivalentes para PowerShell. El reporte real queda en site/public/index.html.
Despliegue y automatización
El workflow versionado separa tres trabajos. test ejecuta pruebas y datos sintéticos. build depende de las pruebas y utiliza la API real. deploy publica exclusivamente site/public en Pages y comprueba el endpoint público por HTTP.
Las PR solo ejecutan pruebas. Un push a main, una ejecución manual o la programación diaria producen una nueva actualización real. La programación está configurada a las 06:17 de Lima; GitHub puede retrasar ejecuciones programadas.
Para activar la publicación hay que seleccionar Settings → Pages → Source → GitHub Actions en el repositorio y ejecutar el workflow. No se necesita guardar un token personal: Actions usa sus credenciales automáticas con los permisos específicos de Pages. Open-Meteo no necesita una clave para este uso no comercial.
Pages está disponible en repositorios públicos gratuitos; la API tiene condiciones y límites de uso. El diseño requiere normalmente tres peticiones diarias y runners estándar. Las condiciones deben revisarse antes de ampliar el alcance: Pages, Actions y Open-Meteo.
Solución publicada: verificada con HTTP 200, descarga del CSV y consulta de metadata.json. Los metadatos del primer despliegue identificaron el commit 27263e7db878d735305ba78006d770919a249847, 90 filas y origen real Open-Meteo.
Ejecución exitosa de CI/CD: los jobs test, build y deploy terminaron correctamente. El workflow también comprueba por HTTP que el sitio sirve metadatos del commit que acaba de desplegarse.
Resultados comprobados
En la ejecución local del 1 de noviembre de 2026, el pipeline recuperó 90 registros reales para el período del 26 de septiembre al 25 de octubre de 2026: 30 por ciudad. Construyó los dos modelos y superó las nueve pruebas dbt. También pasaron cuatro pruebas unitarias y la comprobación de idempotencia con agregados sintéticos conocidos.
La ejecución remota también completó las pruebas y publicó el mismo período. La consulta directa del CSV público devolvió estos resultados:
| Ciudad | Días | Promedio del punto medio diario (°C) | Precipitación acumulada (mm) |
|---|---|---|---|
| Arequipa | 30 | 17.48 | 1.1 |
| Cusco | 30 | 14.30 | 17.7 |
| Lima | 30 | 22.74 | 7.7 |
Son una instantánea del período 2026-09-26 a 2026-10-25, no valores permanentes. El reporte permite descargar el detalle y el resumen; sus metadatos indican el origen, las fechas, el momento de generación y el commit. Las pruebas locales y la comprobación HTTP del despliegue aportan evidencias separadas del funcionamiento.
Conclusión
El proyecto recorre el ciclo de un pipeline ELT: extracción, almacenamiento, transformación, validación, exportación y despliegue automatizado comprobado. Su tamaño permite explicar cada decisión y repetir el proceso sin administrar servidores.
La solución ya puede consultarse públicamente y actualizarse con cada ejecución exitosa del workflow. Como mejoras futuras quedan un histórico incremental, alertas ante fallos y pruebas sobre cambios de esquema en la API.
Datos de Open-Meteo, con atribución bajo CC BY 4.0.
Top comments (0)