Skip to content

Planing - #460

Merged
luisza merged 920 commits into
masterfrom
planing
Sep 13, 2026
Merged

luisza merged 920 commits into
masterfrom
planing

Conversation

@luisza

@luisza luisza commented Sep 13, 2026

Copy link
Copy Markdown
Collaborator

No description provided.

Kejebo and others added 26 commits September 2, 2026 14:22
…n churn

Dos problemas que el crash-loop de organilab en vps1 dejó a la vista, uno por
cada arranque repetido.

init_checks recargaba sga_components.json siempre. El check leía el nombre de
la tabla de caché de OPTIONS.TABLE_NAME, pero DatabaseCache lo guarda en
LOCATION: la lectura caía en el default "django_cache", que no existe, así que
la condición era verdadera en todo arranque y con ella entraba el loaddata,
pisando cualquier edición de esos 379 componentes SGA. Las dos
responsabilidades se separan: la tabla de caché se crea si falta, y el fixture
se carga sólo si no hay ningún componente SGA. --force-fixtures queda para
recargar a propósito.

Profile.language y TaskReport.language llevaban default=settings.LANGUAGE_CODE,
que congela el idioma del entorno donde se corrió makemigrations. La suite usa
test_settings ("en") y producción usa settings ("es"), así que auth_and_perms/
0034 y report/0009 quedaron con default='en': verdes bajo la suite y pendientes
en el contenedor para siempre. Generarlas otra vez sólo habría movido el
problema al otro lado, de modo que los defaults pasan a ser callables y el
estado se serializa por referencia. makemigrations --check ya da limpio con
ambos settings, que es lo que no podía cumplirse a la vez.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0195Dhh1U6MFkaSDtaax5DnK
Cuatro cosas que el entorno de un solo contenedor no obligaba a resolver.

Las migraciones y la siembra corrian en el entrypoint, antes del selector de
SERVICE_TYPE, o sea en los tres roles y en cada replica: con mas de una son
migraciones en paralelo sobre la misma base. Se recogen en `organilab_install`,
un comando idempotente con modo --upgrade, y el arranque las omite con
ORGANILAB_BOOT_INSTALL=false. El default sigue siendo `true`, asi que
docker-compose y los roles dev/all no cambian. /run/install.sh lo envuelve para
el job del orquestador, que corre como root: sin reentrar como `organilab` los
pictogramas quedarian con dueno root dentro de un media que la aplicacion monta
como uid 1000.

Al reunirlos aparecio que dos de esos comandos NO eran idempotentes, y no
fallaban: ni Catalog ni Pictogram tienen restriccion de unicidad, asi que no
habia conflicto que detectar. create_catalog hacia bulk_create y
upload_pictograms un create() a secas, de modo que cada corrida duplicaba el
catalogo entero y los pictogramas -- reescribiendo ademas sus SVG en MEDIA. Los
tests nuevos fallan contra el codigo anterior. Por lo mismo quedan FUERA del
instalador update_roles, update_roles_permissions y add_static_rol: los dos
primeros actualizan roles que en una base nueva no existen (el segundo revienta
buscando "Estudiante"), y el tercero concede permisos por PK numerico fijo, que
en otra base apuntan a otros permisos. Siguen disponibles con --with-roles.

La cache pasa a elegirse por CACHE_URL, con DatabaseCache de default para que el
repo siga arrancando sin infraestructura. En el cluster va contra Redis con el
usuario ACL del tenant, y CACHE_KEY_PREFIX no es cosmetico: django-redis compone
<KEY_PREFIX>:<version>:<clave>, que es lo que hace que las claves caigan dentro
del patron que el ACL concede. Eso rompia init_checks, que deducia el nombre de
la tabla de cache de LOCATION: con Redis es una URL. Ahora mira el BACKEND, que
es lo unico que los distingue.

Y las colas pasan a ser quorum. Una cola clasica vive en el nodo donde se
declaro y muere con el, asi que en un RabbitMQ en cluster se lleva por delante
las tareas encoladas. Van con los nombres HEREDADOS (CELERY_QUEUES,
CELERY_DEFAULT_QUEUE, BROKER_TRANSPORT_OPTIONS) porque celery.py llama a
config_from_object sin namespace: los CELERY_TASK_* no se reconocen y en
minuscula Django ni los copia. Equivocarse ahi no da error -- deja la
configuracion sin aplicar, que es el tropiezo que test_settings.py ya
documentaba con CELERY_ALWAYS_EAGER. Verificado que Celery los recoge.

De paso, `compilemessages` se hornea en la imagen: se recompilaban las dos
locales en cada arranque de cada replica para producir los mismos .mo.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01516vynKxDh2uLL4gdTzZyx
nginx_personalize.py arma un `map $host` desde ALLOWED_HOSTS para devolver 404
a cualquier otro host. Con un bucket de 64 bytes -- el default -- un nombre
largo no cabe y nginx aborta el arranque con "could not build map_hash".

Lo que lo hace difícil de ver es que aborta SOLO nginx: supervisord levanta
gunicorn WSGI y ASGI, los dos entran en RUNNING, y el contenedor parece
arrancado mientras nginx se reintenta tres veces y queda en FATAL. Nada escucha
en el puerto 80, así que el healthcheck tumba la tarea y Swarm la reprograma en
bucle; el error real queda enterrado entre líneas de arranque normales.

Medido con organilab.solvomanager.devautodeploy.solvosoft.com (49 caracteres):
`nginx -t` falla con el fichero anterior y pasa con este. Con los dominios de un
solo nivel que se venían usando nunca se manifestó.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01516vynKxDh2uLL4gdTzZyx
…vieja

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RzyBkTejrD1T6RxXqzPmrx
…a atascada

El webhook de abeb429 llego y se descarto en silencio -- el job 53 llevaba
cuatro dias en `rolling_out` reteniendo one_active_build_per_branch. Liberado
en el panel y cerrado el hueco en sweep_stale_build_jobs; esto solo vuelve a
pedir el build de ese mismo arbol.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RzyBkTejrD1T6RxXqzPmrx
`net/http: timeout awaiting response headers` empujando un blob. El push sale
del cluster al hub y vuelve por el tunel wg, y el nginx del hub corta a los
300s (proxy_read_timeout). Las capas ya subidas quedan cacheadas, asi que el
reintento es mas corto.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RzyBkTejrD1T6RxXqzPmrx
docs/ pasa a Solvosoft/organilab_docs, extraido con git filter-repo
conservando los 186 commits que lo tocaban. Motivo: 636 de los 640 ficheros
versionados bajo docs/ eran GIF y PNG de documentacion, y clonar este repo
para tocar codigo costaba medio giga.

Puntos de union que quedan:

- DOCS_SOURCE_DIR (env DOCS_STATIC_DIR) apunta ahora al repo hermano
  organilab_docs/source. La suite Selenium sigue viviendo aca y sigue
  escribiendo ahi sus PNG/GIF sin cambios en organilab_test/tests/base.py.
- `make docs` delega en el Makefile del repo de documentacion y le pasa
  ORGANILAB_SRC para que autodoc encuentre el codigo. Se agrega
  `make docs-screenshots` para regenerar las imagenes.
- La capacitacion deja de empaquetarse en la imagen: se borran el COPY del
  Dockerfile, el ADD de docker/Dockerfile y el location de nginx. La app la
  enlaza por CAPACITATION_URL, cuyo default pasa a apuntar al sitio publicado
  (se sobreescribe por env var en despliegue).
- build_docker ya no depende de `make docs`.

Se borran ademas .readthedocs.yml (se movio al otro repo) y el env [testenv:docs]
de tox, que nunca corrio por no estar en envlist.

Este commit arrastra tambien el trabajo que estaba sin commitear en el
Makefile: auto-activacion del .venv y los targets del registro privado.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P6Da4vzZFBP4EbKFGUsS2V
La capacitacion referenciaba create_object_features.gif y la imagen no existia.
El test que lo genera (test_add_object_features) ya estaba escrito y pasa: el
GIF simplemente nunca se habia commiteado.

Alrededor habia dos fallos reales:

1. test_edit_object_features y test_delete_object_features pasaban ambos
   "view_object_features" como folder_name, asi que los tres tests escribian el
   mismo fichero y el ultimo en correr ganaba: el GIF del listado terminaba
   siendo el del borrado. Ahora cada uno usa el suyo (view/create/update/delete)
   y los docstrings citan el GIF que de verdad generan.

2. create_directory_path no limpiaba el directorio temporal. Los frames se
   numeran desde 1 en cada corrida pero el tmp sobrevive entre ejecuciones, y
   get_gif_images hace glob de todo el directorio: una corrida corta dejaba los
   PNG altos de la anterior y el GIF salia mezclando pasos de dos versiones del
   test. Medido en view_object_features: 13 frames para un test de un solo paso,
   2 despues de limpiar.

test_view_object_features asertaba //body, que tambien existe en la pagina de
error 403 (ver el comentario de los marcadores PAGE_* en selenium_xpaths.py).
Pasa a usar PAGE_OBJECT_FEATURES, el wrapper que DataTables crea al inicializar.

Los 5 tests de ObjectFeaturesSeleniumTest pasan y el sitio construido queda con
856 referencias locales y ninguna rota.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P6Da4vzZFBP4EbKFGUsS2V
luisza and others added 2 commits September 12, 2026 19:36
# Conflicts:
#	roadmap/inventario_urls.csv
check-v3 agrega 14 rutas (desvincular laboratorios de una organizacion,
duplicar IPER, hojas de seguridad) y reordena la lista de APIs, asi que el
inventario commiteado quedaba desactualizado y roadmap/inventario_urls.csv fue
el unico conflicto de la mezcla. Se resuelve como corresponde a un fichero
generado: regenerandolo con `make url-inventory`.

Total: 1681 -> 1695 rutas. Paginas sin ninguna prueba: 57 -> 60.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P6Da4vzZFBP4EbKFGUsS2V
@luisza
luisza merged commit 85a53ea into master Sep 13, 2026
1 check failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants