Skip to content

chore(ti/licenciamiento): carga de produccion automatica y autolimitada en deploy_prod

Rafael Bautista requested to merge ti into qa

chore(ti/licenciamiento): la carga de produccion pasa de boton manual a paso autolimitado dentro de deploy_prod

CORRIGE UN ERROR DE DISEÑO DEL COMMIT ANTERIOR

833dc435 traslado a produccion el mismo patron que funciono en QA: dos jobs when: manual que alguien aprieta despues del deploy. Calcar el patron fue el error — no se ajusto a QUIEN iba a apretar el boton del otro lado.

GitLab exige permiso de MERGE sobre la rama para disparar un job manual. En qa eso no fue obstaculo porque la rama no esta protegida y el operador es Developer. En main solo mergea Diego, asi que el le habria salido en gris a quien opero la carga de QA. El mecanismo quedaba fuera del alcance de quien lo necesita.

QUE SE HACE EN SU LUGAR

Los dos jobs (licencias_import_prod_dryrun / _apply) y la etapa oneshot desaparecen. En su lugar, un paso dentro del script de deploy_prod, ubicado despues de backfill_canonicals.py — o sea despues de docker compose up -d --build, que es lo que garantiza que el backend ya arranco y que create_all ya creo la tabla destino.

Corre con los permisos del PIPELINE, no con los de una persona. Nadie aprieta nada, nadie tiene que acordarse de nada, y no depende del rol de quien mergee.

LA GUARDA ES LO QUE IMPIDE QUE ESTO DEGENERE EN UN SYNC

El riesgo obvio de colgar la carga del deploy es convertirla en una lectura recurrente de Google en cada despliegue, que es exactamente lo contrario de lo que decidio 375ec704 al abandonar la hoja. Por eso la condicion no es "corre siempre" sino "corre solo si ti_licencias esta vacia":

· Si la tabla YA tiene filas, no se abre la hoja. Ni una peticion a Google. · Si esta vacia, se carga una vez. En el siguiente deploy ya tiene filas y la guarda la salta para siempre.

Es la misma semantica que tenia el boton, sin el boton.

ESPERA ACTIVA POR LA TABLA — NO ES PARANOIA, ES UNA CARRERA REAL

docker compose up -d --build regresa cuando el container ARRANCA, no cuando FastAPI termino de bootear, y create_all corre durante ese boot. Sin esperar, el paso podria leer ti_licencias antes de que exista, interpretar el error como "cero filas" e intentar una carga contra una tabla inexistente. Se resuelve con un poll de hasta 60s a to_regclass('public.ti_licencias'). Si se agota, no carga nada y lo dice — y como la guarda sigue viendo la tabla vacia, el siguiente deploy lo reintenta solo.

EL UNICO PRERREQUISITO QUE EL PIPELINE NO PUEDE RESOLVER

backend/service_account.json tiene que existir en el host de PRD. deploy_prod lo preserva con git clean -e, pero preservar no es tener: el comentario de ese mismo job dice "copiar UNA VEZ al server tras este merge", o sea que el archivo pudo nunca haberse copiado. En QA si estaba y la lectura funciono a la primera.

El paso verifica su existencia ANTES de intentar leer la hoja y, si falta, imprime que archivo copiar y a donde, sin romper el deploy. Copiarlo requiere acceso al servidor; reintentarlo no requiere nada, porque la guarda sigue viendo la tabla vacia y el siguiente deploy vuelve a intentar.

REPORTE ANTES DE ESCRIBIR El paso corre --dry-run y DESPUES la carga, ambos al log del job. Se pierde el gate humano entre reporte y escritura, pero ese gate ya cumplio: el mismo script contra la misma hoja se valido en QA — 1252 altas, 1213 cruces al catalogo, cero filas pisadas, cero actualizaciones. La evidencia queda igual en el log, solo que sin nadie esperando en medio.

Cierra con el conteo por origen, para que el log no termine mudo.

ALCANCE Un solo archivo, .gitlab-ci.yml. Se elimina la etapa oneshot (ya no la usa nadie). Cero DDL, cero migraciones, cero cambios de modelo, router o frontend. backend/scripts/import_licencias_sheet.py sigue en el arbol: produccion todavia lo necesita. Se borra, junto con este bloque, en el commit siguiente a que PRD quede cargado.

Co-Authored-By: Claude Opus 5 noreply@anthropic.com

Merge request reports

Loading