
Desplegar un Odoo nuevo para un cliente debería ser aburrido: un botón, y en unos minutos hay una instancia en marcha, con su base de datos, su proxy y su SSL. Ese botón es oci_management, nuestro módulo interno. Estas semanas le hemos añadido tres cosas que le faltaban.
oci_management es un módulo Odoo que orquesta despliegues de instancias Odoo sobre Docker (directamente o dentro de un contenedor LXC de Proxmox). Registra el proyecto y sus servidores, genera el docker-compose.yml, el repos.yml de git-aggregator y la configuración de nginx a partir de plantillas, y ejecuta el despliegue por SSH. Lo que sigue está hoy en pruebas en nuestro entorno de pre-desarrollo (la rama task718-dev), no en producción.
1. Dependencias de sistema que las manda el manifest
Muchos módulos necesitan software del sistema, no solo librerías de Python. Un ejemplo real: nuestro módulo legal necesita LibreOffice (para generar documentos con report_py3o), y además ocrmypdf y tesseract para el OCR. Hasta ahora, meter todo eso en la imagen significaba editar el Dockerfile a mano para cada cliente. Frágil, y distinto en cada despliegue.
Ahora lo lee el manifest. Un escáner recorre el external_dependencies de cada módulo instalado: la clave bin (los ejecutables que el módulo espera en el PATH) se traduce a paquetes apt con un mapa conocido (soffice a LibreOffice, tesseract a tesseract-ocr más el idioma español, ocrmypdf a ocrmypdf más ghostscript...), y la clave deb, si el módulo la trae, se toma tal cual. De ahí sale un system_requirements.txt que la imagen instala al construirse. El Dockerfile ya no se toca; el manifest decide.
Este mecanismo, el external_dependencies del manifest, es justamente el que pusimos a prueba preguntando a nueve modelos de IA en otra entrada de este blog. Aviso: no todos lo tienen claro.
2. Actualizar el código sin sorpresas
La función "Update Code" trae los últimos cambios del repositorio del cliente y actualiza los módulos afectados. El problema estaba en el "afectados": si no sabía detectar bien qué había cambiado, acababa lanzando un -u de todo el repositorio. Con un custom montado como monorepo, eso es intentar actualizar decenas de módulos a la vez, y reventar.
Lo hemos apretado en dos sitios. Si el commit de antes y el de después son el mismo, no hay nada que actualizar y se dice claramente (antes caía a un "actualízalo todo por si acaso"). Y cuando sí hay cambios, solo se actualizan los módulos que están realmente instalados en esa base de datos. Una actualización sin cambios ahora es un no-op limpio, no una ruleta rusa.
3. Entornos de staging, y promoción por merge request
Antes de tocar producción conviene probar en un clon aislado. "Create Staging" levanta ese clon con su propia base de datos y sus propios puertos. Tenía un fallo sutil muy de Odoo: los campos One2many no se copian por defecto, así que el staging nacía sin repositorios y no había manera de que desplegara.
Ahora, al crear el staging, copiamos los repositorios explícitamente y apuntamos el custom a una rama staging-N. A partir de ahí el flujo es el natural: "Clone from Production" trae los datos reales (neutralizados: sin correo saliente ni crons), pruebas lo que tengas que probar, y "Promote" abre un merge request de staging-N a la rama de producción. Nada llega a producción sin pasar por esa revisión.
Lo que aún falta
Probando en real (lo contamos en la siguiente entrada) también encontramos lo que no está: el módulo todavía no sabe desmontar un staging por completo (contenedores, volúmenes, rama, base de datos, vhost y certificado), y el despliegue de un staging exige DNS y SSL público para arrancar cuando no debería. Están anotados como deuda, con nombre y apellidos. Preferimos una lista honesta de pendientes a un "ya funciona" que no aguante el primer uso real.
-- Fer & Claude, LTC Labs