Saltar a contenido

Los trabajos pesados de CI siguen este orden: backend, frontend y Docker. El Mac y la MV Linux comparten recursos físicos; el frontend utiliza un solo proceso de pruebas. Un fallo anterior no omite las comprobaciones siguientes, pero se mantienen la cancelación y las restricciones de los forks. Las suites aisladas de dibujos y citas disponen de cinco minutos por proceso, incluidas las importaciones iniciales y todas las aserciones. Las pruebas integradas de herramientas generadas utilizan el límite de producción sin modificarlo; una regresión separada verifica el límite explícito.

Todas las ejecuciones de CI utilizan máquinas locales: Linux ARM64 para backend, native smoke y Docker; macOS ARM64 para frontend; macOS X64 para documentación. Si falta un ejecutor compatible, los trabajos quedan en cola. Ninguna PR, subida ni validación de versiones recurre a ejecutores de GitHub. Se mantienen los permisos de solo lectura, las dependencias y las restricciones al mismo repositorio; los forks no pueden ejecutarse en las máquinas del propietario.

Los grupos de concurrency del flujo de trabajo utilizan un prefijo específico de CI, el nombre del flujo y el número de PR. Un commit nuevo cancela los trabajos anteriores en ejecución y en cola solo de esa PR. La cancelación se activa únicamente para eventos pull_request; los demás utilizan el github.run_id único, de modo que las subidas y las comprobaciones reutilizables de versiones no se cancelan entre sí ni entran en conflicto con el bloqueo de versiones del flujo que las invoca. Los nombres de las comprobaciones obligatorias, los ámbitos completos de pruebas, los permisos de solo lectura y las restricciones de forks se mantienen. Añadir capacidad no elimina las dependencias existentes entre trabajos.

El trabajo de frontend desactiva la caché remota de dependencias en setup-node: omite cache y establece explícitamente package-manager-cache: false. Esto evita esperar restauraciones opcionales atascadas y omite las subidas de caché remota, conservando el almacén local de pnpm. pnpm install --frozen-lockfile sigue instalando y verificando las dependencias, y todas las comprobaciones de frontend y escritorio siguen siendo obligatorias. Esto no elimina el acceso a la red necesario para obtener las dependencias que falten.

El trabajo de frontend nativo solicita explícitamente Python 3.11 gestionado para macOS ARM64 con UV_PYTHON=cpython-3.11-macos-aarch64-none y verifica platform.machine() antes de instalar dependencias. Un intérprete Intel instalado no debe seleccionar silenciosamente las dependencias x86_64 mediante Rosetta. El flujo compartido de CI establece un límite de lectura HTTP de 120 segundos, tres reintentos HTTP, un máximo de cuatro descargas simultáneas y dos hilos de instalación para todas las instalaciones Python directas: frontend, backend, smoke nativo y documentación. Los trabajos y pasos deben heredar estos valores sin sobrescribirlos. La comprobación previa del intérprete del frontend tiene cinco minutos. Las instalaciones completas uv sync --frozen, incluido el smoke nativo, tienen cuarenta y cinco minutos; la instalación congelada de docs-ci tiene quince. Esto admite descargas sin caché en los ejecutores locales. Estos límites conservan los entornos nuevos por trabajo, el aislamiento de la caché y todas las pruebas; no ocultan errores de instalación ni garantizan la disponibilidad de la red. Las asignaciones de ejecutores, el empaquetado de versiones y las pruebas no cambian.

El CI compartido fija uv en 0.10.0 para que el límite de reintentos existente también cubra los tiempos de espera tras recibir parte de un paquete. Con 0.9.15, ese fallo durante la transferencia podía detener la instalación sin reintentarla, pese a los reintentos HTTP configurados. Se utiliza la corrección original de tiempos de espera en transferencias, no un envoltorio de reintentos ni un plazo más largo. Las descargas completadas permanecen en la caché del mismo trabajo; una instalación fallida sigue haciendo fallar el trabajo. Las dependencias congeladas de la app y las versiones del instalador de Pages y del empaquetado de versiones no cambian.

Estrategia de pruebas

Capas de calidad

flowchart TB
    Static["Comprobaciones estáticas\nSintaxis de Python, ESLint, i18n"] --> Unit["Pruebas unitarias\nnormalizadores, políticas, algoritmos"]
    Unit --> Integration["Pruebas de integración\nrutas, almacenamiento, adaptadores"]
    Integration --> E2E["Playwright\nnavegador real y servicios en ejecución"]
    E2E --> Visual["Inspecciones visuales y instantáneas de regresión"]
    Integration --> Deploy["Pruebas básicas de Docker y paquetes"]

Ninguna capa es suficiente por sí sola. La compilación del frontend detecta errores de importación y sintaxis, pero no una interacción rota. Una prueba unitaria de ruta no demuestra la integración con el navegador. Una captura de pantalla no demuestra persistencia ni autorización.

Validación unificada antes de una PR

Preparad primero las dependencias congeladas de JavaScript, ejecución y documentación:

pnpm install --frozen-lockfile
uv sync --frozen --group docs-ci
uv run --frozen --no-sync python scripts/ci/pre_pr.py --base-ref origin/main

En macOS, usad --resource-profile mac-idle para la validación local acotada. Sustituye el heap predeterminado por 1536 MiB, ejecuta con prioridad 10, un worker y un hilo de cálculo, y supervisa un presupuesto RSS de 2 GiB para el comando y sus descendientes. Cada fase comienza solo después de 30 segundos de presión de memoria normal. Las comprobaciones estáticas, compilaciones y suites tienen límites de 5, 10 y 15 minutos respectivamente.

El aviso sostenido durante 2 segundos, la presión crítica, el timeout, el exceso de RSS o un fallo de supervisión detienen los procesos propios y dejan la validación incompleta. No hay reintento automático ni aumento del límite. Mantened detenidos otros jobs de validación; no cerréis aplicaciones del usuario ni carguéis modelos locales durante esta auditoría. Las suites Node de contratos y escritorio usan explícitamente --test-concurrency=1.

uv run --frozen --no-sync python scripts/ci/pre_pr.py --base-ref origin/main --resource-profile mac-idle

El entorno Python congelado se comprueba sin instalar paquetes ni eliminar los adicionales.

La entrada directa de Python evita la comprobación automática externa de dependencias de pnpm. El alias de paquete check:pre-pr también está disponible tras instalarlas. Usad --quick para comprobaciones estáticas y contratos de CI, o --list para inspeccionar el plan sin ejecutarlo. Ninguno acredita toda la PR. El plan completo predeterminado también ejecuta compatibilidad de API, todas las comprobaciones de tipos del backend y pipeline, la política de recursos congelados, las suites completas de Python, frontend y escritorio, el build de producción del frontend y la validación completa de documentación con actualización.

La base indicada mediante --base-ref se resuelve una vez a un commit inmutable; la orden no descarga referencias ni cambia de rama. Informa de HEAD y valida el árbol de trabajo actual, incluidos los cambios seguidos preparados y no preparados. Resolved conflictos y revisad/preparad o ignorad los archivos no seguidos antes de empezar, para que las comprobaciones del índice no omitan código nuevo. Python 3.11 y Node deben tener arquitecturas coincidentes.

Las fases se ejecutan consecutivamente con el heap revisado de Node de 4 GiB y un solo proceso de pruebas de frontend. El primer error detiene la validación, conserva el código de salida e identifica la fase fallida; no se reintenta ni se convierte en éxito. Las herramientas ausentes y las interrupciones siguen siendo errores. Leed el registro de la primera fase fallida antes de decidir si la causa es el código, las dependencias o la infraestructura.

El entorno hijo utiliza GNOSI_VALIDATION_ROOT y directorios temporales de datos y vault, desactiva las pruebas contra servicios reales, elimina las variables de credenciales heredadas y dirige los destinos reales del backend y navegador a un puerto loopback cerrado. Conserva el directorio personal real. UV_NO_SYNC=1, UV_FROZEN=1 y pnpm_config_verify_deps_before_run=error impiden instalaciones implícitas en las órdenes hijas; si hace falta, usad la preparación congelada explícita anterior. La validación no arranca la aplicación personal, contenedores ni el empaquetado de versiones.

El modo completo regenera intencionadamente la documentación. Revisad y preparad esos cambios y repetid la validación de documentación previa a la PR con la misma base; no debe producir diferencias adicionales. Las regresiones comparan el plan completo con todas las órdenes de validación existentes del frontend y backend de CI para detectar omisiones cuando esta cambia.

El éxito local no es el éxito de GitHub: las cinco comprobaciones obligatorias deben pasar en el commit final de la PR, incluidos el arranque nativo real y la persistencia de Docker en sus ejecutores. La validación local no reproduce descargas sin caché, planificación de ejecutores, otros sistemas operativos, instaladores ni despliegues. La orden no publica ni fusiona commits.

Si el código o HEAD cambian durante la validación, esta falla y debe repetirse; solo se excluyen las diferencias previstas de los catálogos generados.

Comprobación unificada de tipos

Ejecute pnpm typecheck desde la raíz del repositorio. Comprueba, en este orden, TypeScript del frontend, mypy estricto de todo el backend (excepto las pruebas), mypy estricto de todos los archivos Python públicos indexados del pipeline y, finalmente, la sintaxis Python de backend, pipeline, scripts y extensiones. Cada error detiene las etapas siguientes y conserva el código de salida.

Las órdenes individuales typecheck:backend-boundaries y typecheck:pipeline siguen disponibles. Es una comprobación estática: no sustituye lint, pruebas unitarias, builds, flujos de navegador ni validación del despliegue. Superarla no acredita la eliminación de todos los límites con Any explícito. La regresión comprueba los ámbitos completos y utiliza ejecutables simulados aislados en POSIX para verificar el orden y la propagación de errores; no acredita la ejecución en Windows.

Pruebas del backend

Pytest cubre servicios, dependencias de rutas, normalización, almacenamiento, seguridad, concurrencia y regresiones. Las pruebas utilizan directorios temporales para vaults y datos locales. Los proveedores externos se sustituyen por stubs salvo que la prueba esté marcada explícitamente como live/E2E.

Las suites importantes incluyen:

  • Autenticación, PAT, inicialización del workspace, roles e interfaces públicas.
  • Confinamiento de rutas, escrituras seguras, ETags, condiciones de carrera, registro y sidecars.
  • Fórmulas, rollups, filtros tipados, relaciones, planificación y tareas programadas.
  • MIME/CID del correo, fusión de contactos y vCard, confinamiento de calendario y recordatorios.
  • Enrutamiento de IA, habilidades, resiliencia MCP, confirmaciones y herramientas generadas.
  • Complementos, importaciones, citas, normalización de lectores, XSS y SSRF.

Pruebas del frontend

Vitest cubre componentes, hooks, registros, utilidades de formato, lógica tipada de vistas y comportamiento del estado. ESLint y la compilación de producción con Vite son obligatorios. check:i18n verifica que las claves referenciadas de textos visibles para el usuario existan en todos los idiomas.

La compilación debe terminar con cero errores. Las advertencias existentes no son permiso para añadir nuevas advertencias sin revisión.

Los límites de propiedad se comprueban con gnosi/feature-boundaries en ESLint. La ampliación revisada prevé un manifiesto de entradas públicas exactas en frontend/feature-public-entries.json, con un motivo por ruta. Los consumidores externos a una feature usan su raíz/index o una entrada explícitamente revisada; los archivos vecinos no listados siguen siendo privados. Se comprueban imports estáticos, reexports, imports diferidos literales e imports de tipos TypeScript. El manifiesto no debe crear un agregador de carga inmediata ni alterar los límites de carga diferida.

Las reglas shared → ninguna feature/app y features → ningún app son incondicionales, también para tipos y entradas del manifiesto. Los módulos internos de una feature pueden usar imports locales. Los contratos globales de código están en frontend/tests/contracts/; el guardrail complementa el lint AST. Se debe verificar la implementación después del traslado; esta documentación no acredita que la verificación global haya pasado.

En máquinas con recursos limitados, ejecute las comprobaciones de compilación y tipado que consumen mucha CPU por separado de la suite completa con DOM real. Si el trabajo en paralelo provoca que las pruebas agoten sus plazos, repita la suite afectada de forma aislada y después la suite completa con un número acotado de workers (por ejemplo, pnpm --filter @gnosi/frontend exec vitest run --maxWorkers=2 --minWorkers=2). Mantenga intactas las aserciones y los plazos; superar una ejecución aislada no demuestra que la suite completa pase.

Límites de tamaño de producción

El build del frontend ejecuta scripts/check-bundle-size.ts después de Vite. Los límites fijos, en bytes JavaScript sin comprimir, son: archivo de entrada 1.400.000; fragmento mayor 1.800.000; editor vendor 1.550.000; tldraw vendor 1.350.000; ruta de configuración 600.000. Un fragmento revisado ausente o duplicado hace fallar la comprobación. Las pruebas cubren URL de despliegue relativas, de raíz y con prefijo, crecimiento y fragmentos ausentes. El tamaño del archivo de entrada no mide todo el grafo inicial de dependencias, la transferencia comprimida ni el tiempo de arranque. El aviso existente de Vite de 1.500 kB sigue visible; estos límites evitan crecimiento, no acreditan un rendimiento óptimo.

Pruebas visuales y de extremo a extremo

Playwright se ejecuta como un proyecto del host contra la aplicación nativa. La configuración anónima cubre el arranque y el comportamiento público; la autenticada cubre la funcionalidad del workspace. Las pruebas de dominio ejercitan Vault, paneles, correo, calendario, contactos, dibujos, automatización, chat del agente y navegación.

Las instantáneas visuales cubren páginas representativas de escritorio y móvil. Ante un cambio de interfaz, inspeccione la página renderizada, pulse el control modificado, observe la consola y tome una captura. Confirme que los modales, las capas superpuestas, las notificaciones emergentes y los menús utilizan el sistema registrado de z-index y no bloquean la interacción.

Control de accesibilidad

El proyecto accessibility de Playwright es un control bloqueante de WCAG 2.2 AA. Ejecuta axe sobre doce rutas seleccionadas del producto en los temas claro y oscuro, incluidos el contraste de color, las etiquetas, las regiones y las relaciones ARIA. El marcado propio de la aplicación siempre permanece dentro de la auditoría y la suite no mantiene una lista permanente de infracciones permitidas. Los datos de prueba deterministas activan los módulos opcionales de la matriz de rutas, y cada ruta también falla si el navegador genera un error de página no controlado; una superficie rota no puede superar axe.

Antes del análisis, cada caso exige la URL canónica esperada y una superficie visible propia de la funcionalidad, sin esqueleto de carga ni aviso de complemento desactivado. No recarga la página para reintentar un arranque fallido. La prueba del enlace de salto verifica el borde visible de dos píxeles y el subrayado de teclado; la navegación al grafo sigue el enlace del vault. Las capturas de multimedia y del centro de control conservan evidencia del contraste en claro y oscuro. Un resultado verde cubre estos casos y estados, no todas las interacciones, tecnologías de asistencia, datos personales ni la conformidad completa con WCAG.

Las comprobaciones de interacción complementan axe en aspectos que el análisis estático no puede demostrar: navegación de salto, foco visible y orden lógico, manejo completo por teclado, desplazamiento del foco entre pestañas móviles, Escape en diálogos cancelables, confinamiento y restauración del foco, nombres accesibles y anuncios de cambio de ruta. Los cambios compartidos de foco, modales, navegación o tokens de color deben superar este proyecto antes de una release.

El estilo global de foco utiliza el atributo data-focus-modality en la raíz del documento. La activación con puntero elimina los contornos genéricos; con teclado se aplican indicadores contextuales: el borde existente en los campos, subrayado en los enlaces y contorno en los controles sin borde. Los títulos editables del Vault conservan únicamente el cursor de escritura. Las pruebas unitarias cubren los cambios de modalidad y las pruebas de navegador, el foco con puntero y teclado en los temas claro y oscuro.

Pruebas de despliegue

El constructor de imágenes de CI registra la revisión Git extraída en org.opencontainers.image.revision y un identificador único de la invocación en io.gnosi.ci.build-id. Se deben listar y eliminar correctamente las imágenes de destino existentes, sin forzar imágenes en uso. Tras cada construcción, incluso si termina con código cero, la inspección debe devolver ambas etiquetas coincidentes. Un fallo del cliente posterior a la carga solo puede recuperarse con esta evidencia; una imagen anterior del mismo commit también falla porque su identificador de invocación es diferente. Los metadatos ausentes o malformados y los fallos de inspección o eliminación siguen siendo errores. La prueba real de arranque y persistencia sigue siendo obligatoria.

La imagen del backend ahora utiliza uv 0.10.0 con UV_HTTP_TIMEOUT=120, UV_HTTP_RETRIES=3, UV_CONCURRENT_DOWNLOADS=4 y UV_CONCURRENT_INSTALLS=2 explícitamente en la orden de instalación congelada. Las variables del workflow no se heredan implícitamente dentro de las construcciones Docker. Estos valores solo afectan a la instalación, no al entorno de ejecución de la aplicación. Las pruebas de regresión comparan el instalador y los límites con la CI compartida y rechazan valores ausentes, cambiados o duplicados. Las dependencias de la aplicación, los lockfiles, la asignación de ejecutores y el empaquetado de versiones no cambian.

La CI de Docker valida Compose, construye ambas imágenes y ejecuta scripts/smoke_docker.sh. La prueba comprueba el backend y el frontend en marcha, recrea los contenedores y verifica un marcador sintético en /data. Su limpieza de salida solo afecta a su proyecto Compose con nombre único, incluidos los volúmenes de prueba de ese proyecto.

La limpieza final ejecuta scripts/ci/prepare_docker_runner.py --cleanup: retira solo las etiquetas de imagen gnosi-frontend:ci y gnosi-backend:ci sin forzar imágenes en uso, limpia la caché de construcción no utilizada y regenerable, y verifica al menos 12 GiB libres. Nunca limpia globalmente contenedores, redes ni volúmenes. Una orden de limpieza de caché finalizada que informa de context deadline exceeded se puede repetir hasta tres intentos totales, separados por cinco segundos. Cada intento tiene un límite de proceso de 120 segundos; los pasos de capacidad y limpieza final tienen límites de diez minutos. Otros errores, un límite de proceso agotado, los reintentos agotados o el espacio insuficiente siguen haciendo fallar el check. Nunca se omiten las construcciones ni la prueba de persistencia.

La eliminación de imágenes tiene una recuperación limitada propia: si se agota el límite de proceso de 60 segundos, una consulta correcta debe confirmar si todavía existe la etiqueta exacta de CI. Su ausencia verificada completa la eliminación. Si sigue existiendo, se permite un reintento tras cinco segundos, comprobando de nuevo su presencia antes de eliminarla. Una inspección fallida, una imagen en uso o un segundo timeout con la etiqueta todavía presente siguen siendo errores. Se mantienen el límite exterior de diez minutos y la comprobación final de 12 GiB.

El trabajo de frontend aplica el presupuesto revisado de 4 GiB de heap de Node a todo el trabajo para que lint, comprobación de tipos, pruebas y build de producción compartan el mismo contrato de memoria previsible. Las pruebas de política de versiones de escritorio verifican las asignaciones locales exactas y todo el entorno de recursos Node/Python. Las pruebas de mutación rechazan ejecutores de GitHub, asignaciones locales modificadas, presupuestos ausentes y sobrescrituras por paso. Los cambios de CI requieren toda la suite de escritorio y los contratos de planificación Python.

La CI de Electron configura paquetes para macOS arm64/x64, Linux arm64 y Windows x64. Configurar esa matriz, pasar pruebas unitarias desktop o comprobar una migración sintética del perfil del navegador no valida los instaladores ni el backend congelado. Cada arquitectura requiere evidencia de instalación, arranque, persistencia y actualización desde 2.x. Actualmente, macOS utiliza actualizaciones manuales mediante el instalador. Una ejecución local en macOS no acredita las otras plataformas: no publique 3.0 antes de superar toda la matriz de release.

Correspondencia entre cambios y pruebas

Cambio Pruebas mínimas
Solo documentación revisada Comprobación del generador, validador, compilación estricta de documentación y prueba básica del portal en el navegador.
Lógica de generación de catálogos Pruebas unitarias del generador, determinismo entre dos ejecuciones, validador y compilación estricta de documentación.
Comportamiento del backend Regresión acotada con pytest y suite de integración afectada.
Comportamiento del frontend Vitest cuando sea viable, comprobación i18n, compilación de producción, acción en el navegador y captura.
Accesibilidad o token compartido de interfaz Vitest de la primitiva, paridad de los cuatro idiomas, matriz axe en claro y oscuro, pruebas de teclado y captura del navegador.
Autenticación, seguridad o comportamiento de rutas Pruebas negativas e intentos de acceso entre ámbitos, además del caso correcto.
Despliegue o dependencias Verificación nativa y CI de Docker o empaquetado, según corresponda.

Catálogo de pruebas

El catálogo de pruebas generado enumera los archivos de pruebas propios y las señales de navegación. La recopilación del ejecutor sigue siendo la fuente autoritativa del número de pruebas ejecutables.