Els treballs pesants de CI segueixen aquest ordre: backend, frontend i Docker. El Mac i la MV Linux comparteixen recursos físics; el frontend utilitza un sol procés de proves. La fallada anterior no omet les comprovacions següents, però es mantenen la cancel·lació i les restriccions dels forks. Les suites aïllades de dibuixos i citacions disposen de cinc minuts per procés, incloses les importacions inicials i totes les assercions. Les proves integrades d’eines generades utilitzen el límit de producció sense modificar-lo; una regressió separada verifica el límit explícit.
Totes les execucions de CI utilitzen màquines locals: Linux ARM64 per a backend, native smoke i Docker; macOS ARM64 per a frontend; macOS X64 per a documentació. Si falta un executor compatible, els treballs queden en cua. Cap PR, pujada ni validació de versions recorre a executors de GitHub. Es mantenen els permisos de només lectura, les dependències i les restriccions al mateix repositori; els forks no poden executar-se a les màquines del propietari.
Els grups de concurrency del flux de treball utilitzen un prefix específic de
CI, el nom del flux i el número de PR. Un commit nou cancel·la els treballs
anteriors en execució i en cua només d’aquella PR. La cancel·lació només s’activa
per als esdeveniments pull_request; els altres utilitzen el github.run_id
únic, de manera que les pujades i les comprovacions reutilitzables de versions
no es cancel·len entre si ni entren en conflicte amb el bloqueig de versions
del flux que les crida. Els noms de les comprovacions obligatòries, els àmbits
complets de proves, els permisos de només lectura i les restriccions dels forks
es mantenen. Afegir capacitat no elimina les dependències existents entre treballs.
El treball de frontend desactiva la memòria cau remota de
dependències a setup-node: omet cache i estableix explícitament
package-manager-cache: false. Això evita esperar restauracions opcionals
encallades i omet les pujades de memòria cau remota, tot conservant el magatzem
local de pnpm. pnpm install --frozen-lockfile continua instal·lant i verificant
les dependències, i totes les comprovacions de frontend i escriptori continuen
sent obligatòries. Això no elimina l’accés a la xarxa necessari per obtenir les
dependències que faltin.
El treball de frontend natiu demana explícitament Python 3.11 gestionat per a
macOS ARM64 amb UV_PYTHON=cpython-3.11-macos-aarch64-none i verifica
platform.machine() abans d’instal·lar dependències. Un intèrpret Intel
instal·lat no ha de seleccionar silenciosament les dependències x86_64 amb
Rosetta. El flux compartit de CI estableix un límit de lectura HTTP de 120 segons,
tres reintents HTTP, un màxim de quatre descàrregues simultànies i dos fils
d’instal·lació per a totes les instal·lacions Python directes: frontend, backend,
smoke natiu i documentació. Els treballs i passos han d’heretar aquests valors
sense sobreescriure’ls. La comprovació prèvia de l’intèrpret del frontend té cinc
minuts. Les instal·lacions completes uv sync --frozen, inclòs el smoke natiu,
tenen quaranta-cinc minuts; la instal·lació congelada de docs-ci en té quinze.
Això admet descàrregues sense memòria cau als executors locals. Aquests límits conserven
els entorns nous per treball, l’aïllament de la memòria cau i totes les proves;
no amaguen errors d’instal·lació ni garanteixen la disponibilitat de la xarxa.
Les assignacions d’executors, l’empaquetament de versions i les proves no canvien.
El CI compartit fixa uv a 0.10.0 perquè el límit de reintents existent també
cobreixi els temps d’espera després de rebre part d’un paquet. Amb 0.9.15,
aquesta fallada durant la transferència podia aturar la instal·lació sense
reintentar-la, malgrat els reintents HTTP configurats. S’utilitza la
correcció original dels temps d’espera en transferències,
no un embolcall de reintents ni un termini més llarg. Les descàrregues completades
romanen a la memòria cau del mateix treball; una instal·lació fallida continua
fent fallar el treball. Les dependències congelades de l’app i les versions
de l’instal·lador de Pages i de l’empaquetament de versions no canvien.
Estratègia de proves¶
Capes de qualitat¶
flowchart TB
Static["Comprovacions estàtiques\nSintaxi Python, ESLint, i18n"] --> Unit["Proves unitàries\nnormalitzadors, polítiques, algoritmes"]
Unit --> Integration["Proves d'integració\nrutes, emmagatzematge, adaptadors"]
Integration --> E2E["Playwright\nnavegador real i serveis en execució"]
E2E --> Visual["Inspecció visual i captures de regressió"]
Integration --> Deploy["Proves bàsiques de Docker i paquets"]
Cap capa és suficient per si sola. Un build del frontend detecta errors d'importació i sintaxi, però no una interacció trencada. Una prova unitària de ruta no demostra la integració amb el navegador. Una captura no prova persistència ni autorització.
Validació unificada abans d’una PR¶
Prepareu primer les dependències congelades de JavaScript, execució i documentació:
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
A macOS, feu servir --resource-profile mac-idle per a la validació local acotada. Substitueix el heap predeterminat per 1536 MiB, executa amb prioritat 10, un worker i un fil de càlcul, i supervisa un pressupost RSS de 2 GiB per a l’ordre i els descendents. Cada fase comença només després de 30 segons de pressió de memòria normal. Les comprovacions estàtiques, els builds i les suites tenen límits de 5, 10 i 15 minuts respectivament.
L’avís sostingut durant 2 segons, la pressió crítica, el timeout, l’excés d’RSS o una fallada de supervisió aturen els processos propis i deixen la validació incompleta. No hi ha reintent automàtic ni augment del límit. Manteniu aturats altres jobs de validació; no tanqueu aplicacions de l’usuari ni carregueu models locals durant aquesta auditoria. Les suites Node de contractes i escriptori fan servir explícitament --test-concurrency=1.
uv run --frozen --no-sync python scripts/ci/pre_pr.py --base-ref origin/main --resource-profile mac-idle
L’entorn Python congelat es comprova sense instal·lar paquets ni eliminar-ne els addicionals.
L’entrada directa de Python evita la comprovació automàtica externa de dependències
de pnpm. L’àlies de paquet check:pre-pr també està disponible després d’instal·lar-les.
Feu servir --quick per a comprovacions estàtiques i contractes de CI, o --list
per inspeccionar el pla sense executar-lo. Cap dels dos acredita tota la PR.
El pla complet predeterminat també executa compatibilitat d’API, totes les
comprovacions de tipus del backend i pipeline, la política de recursos congelats,
les suites completes de Python, frontend i escriptori, el build de producció
del frontend i la validació completa de documentació amb actualització.
La base indicada amb --base-ref es resol una vegada a un commit immutable;
l’ordre no descarrega referències ni canvia de branca. Informa de HEAD i valida
l’arbre de treball actual, inclosos els canvis seguits preparats i no preparats.
Resoleu els conflictes i reviseu/prepareu o ignoreu els fitxers no seguits abans
de començar, perquè les comprovacions de l’índex no ometin codi nou. Python 3.11
i Node han de tenir arquitectures coincidents.
Les fases s’executen consecutivament amb el heap revisat de Node de 4 GiB i un sol procés de proves de frontend. El primer error atura la validació, conserva el codi de sortida i identifica la fase fallida; no es reintenta ni es converteix en èxit. Les eines absents i les interrupcions continuen sent errors. Llegiu el registre de la primera fase fallida abans de decidir si la causa és el codi, les dependències o la infraestructura.
L’entorn fill utilitza GNOSI_VALIDATION_ROOT i directoris temporals de dades
i vault, desactiva les proves contra serveis reals, elimina les variables de
credencials heretades i dirigeix els destins reals del backend i navegador a un
port loopback tancat. Manté intacte el directori personal real.
UV_NO_SYNC=1, UV_FROZEN=1 i pnpm_config_verify_deps_before_run=error
impedeixen instal·lacions implícites a les ordres filles; si cal, feu servir
la preparació congelada explícita anterior. La validació no arrenca l’app
personal, contenidors ni l’empaquetament de versions.
El mode complet regenera intencionadament la documentació. Reviseu i prepareu aquests canvis i repetiu la validació de documentació abans de la PR amb la mateixa base; no ha de produir cap diferència addicional. Les regressions comparen el pla complet amb totes les ordres de validació existents del frontend i backend de CI per detectar omissions quan aquesta canvia.
L’èxit local no és l’èxit de GitHub: les cinc comprovacions obligatòries han de passar al commit final de la PR, incloent-hi l’arrencada nativa real i la persistència de Docker als seus executors. La validació local no reprodueix descàrregues sense memòria cau, planificació d’executors, altres sistemes operatius, instal·ladors ni desplegaments. L’ordre no publica ni fusiona commits.
Si el codi o HEAD canvien durant la validació, aquesta falla i cal repetir-la;
només s’exclouen les diferències previstes dels catàlegs generats.
Comprovació unificada de tipus¶
Executeu pnpm typecheck des de l'arrel del repositori. Comprova, en aquest
ordre, TypeScript del frontend, mypy estricte de tot el backend (excloent-ne
les proves), mypy estricte de tots els fitxers Python públics indexats del
pipeline i, finalment, la sintaxi Python de backend, pipeline, scripts i
extensions. Qualsevol error atura les etapes següents i conserva el codi de sortida.
Les ordres individuals typecheck:backend-boundaries i
typecheck:pipeline continuen disponibles. És una comprovació estàtica:
no substitueix lint, proves unitàries, builds, fluxos de navegador ni validació
del desplegament. Passar-la no acredita que s'hagin eliminat tots els límits
amb Any explícit. La regressió verifica els àmbits complets i usa executables
simulats aïllats en POSIX per comprovar l'ordre i la propagació dels errors;
no acredita l'execució a Windows.
Proves del backend¶
Pytest cobreix serveis, dependències de ruta, normalització, emmagatzematge, seguretat, concurrència i regressions. Les proves utilitzen directoris temporals de vault i dades locals. Els proveïdors externs se simulen, tret que una prova estigui marcada explícitament com a real/E2E.
Hi ha suites importants que inclouen:
- Autenticació, PAT, inicialització de workspace, rols i superfícies públiques.
- Confinament de rutes, escriptures segures, ETags, condicions de cursa, registre i sidecars.
- Fórmules, rollups, filtres tipats, relacions, planificació i programació de tasques.
- MIME/CID del correu, fusió de contactes/vCard, confinament del calendari i recordatoris.
- Encaminament d'IA, habilitats, resiliència MCP, confirmacions i eines generades.
- Plugins, importacions, citacions, normalització del lector, XSS i SSRF.
Proves del frontend¶
Vitest cobreix components, hooks, registres, utilitats de format, lògica de vistes
tipada i comportament de l'estat. ESLint i el build de producció de Vite són
obligatoris. check:i18n verifica que les claus visibles per l'usuari referenciades
existeixin a tots els idiomes.
El build ha d'acabar sense errors. Els avisos existents no autoritzen a afegir-ne de nous sense revisió.
Els límits de propietat es comproven amb gnosi/feature-boundaries a ESLint.
L'ampliació revisada preveu un manifest d'entrades públiques exactes a
frontend/feature-public-entries.json, amb un motiu per camí.
Els consumidors externs a una feature usen l'arrel/index o una entrada
explícitament revisada; els fitxers veïns no llistats continuen privats.
Cal comprovar imports estàtics, reexports, imports diferits literals i imports
de tipus TypeScript. El manifest no ha de crear un agregador de càrrega
immediata ni alterar els límits de càrrega diferida.
Les regles shared → cap feature/app i features → cap app són
incondicionals, també per als tipus i les entrades del manifest. Els mòduls
interns d'una feature poden usar imports locals. Els contractes globals de codi
són a frontend/tests/contracts/; el guardrail complementa el lint AST.
Cal verificar la implementació després del trasllat; aquesta documentació no
acredita que la verificació global hagi passat.
En màquines amb recursos limitats, executeu els builds i les comprovacions de
tipus intensives en CPU separadament de la suite completa amb DOM real. Si el
paral·lelisme provoca que caduquin proves, repetiu la suite afectada aïlladament
i després la suite completa amb workers limitats, per exemple
pnpm --filter @gnosi/frontend exec vitest run --maxWorkers=2 --minWorkers=2.
Manteniu les assercions i els temps límit; una passada aïllada no acredita que
tota la suite passi.
Límits de mida de producció¶
El build del frontend executa scripts/check-bundle-size.ts després de Vite.
Els límits fixos, en bytes JavaScript sense comprimir, són: fitxer d'entrada
1.400.000; fragment més gran 1.800.000; editor vendor 1.550.000; tldraw vendor
1.350.000; ruta de configuració 600.000. Un fragment revisat absent o duplicat
fa fallar la comprovació. Les proves cobreixen URL de desplegament relatives,
d'arrel i amb prefix, creixement i fragments absents. La mida del fitxer
d'entrada no mesura tot el graf inicial de dependències, la transferència
comprimida ni el temps d'arrencada. L'avís existent de Vite de 1.500 kB
continua visible; aquests límits eviten creixement, no acrediten rendiment òptim.
Proves d'extrem a extrem i visuals¶
Playwright s'executa com a projecte del host contra l'aplicació nativa. La preparació anònima cobreix l'arrencada i el comportament públic; l'autenticada, la funcionalitat del workspace. Les proves de domini exerciten Vault, tauler, correu, calendari, contactes, dibuixos, automatització, xat d'agent i navegació.
Les captures visuals cobreixen pàgines representatives d'escriptori i mòbil. Si canvia la interfície, inspeccioneu la pàgina real, cliqueu el control modificat, reviseu la consola i feu una captura. Confirmeu que diàlegs, superposicions, avisos emergents i menús utilitzen el sistema z-index registrat i no bloquegen la interacció.
Porta d’accessibilitat¶
El projecte accessibility de Playwright és una porta bloquejant de WCAG 2.2
AA. Executa axe sobre dotze rutes seleccionades del producte en els
temes clar i fosc, incloent-hi contrast de color, etiquetes, regions i relacions
ARIA. El marcatge propi de l’aplicació sempre queda dins l’auditoria i no es manté
una llista permanent d'excepcions de violacions. La dada
de prova determinista activa els mòduls opcionals de la matriu de rutes, i cada
ruta també falla si el navegador genera un error de pàgina no gestionat; una
superfície trencada no pot superar axe.
Abans de l’anàlisi, cada cas exigeix l’URL canònic esperat i una superfície visible pròpia de la funcionalitat, sense esquelet de càrrega ni avís de complement desactivat. No recarrega la pàgina per reintentar una arrencada fallida. La prova de l’enllaç de salt verifica la vora visible de dos píxels i el subratllat de teclat; la navegació al graf segueix l’enllaç del vault. Les captures de multimèdia i del centre de control conserven evidència del contrast en clar i fosc. Un resultat verd cobreix aquests casos i estats, no totes les interaccions, tecnologies d’assistència, dades personals ni la conformitat completa amb WCAG.
Les proves d’interacció complementen axe amb navegació de salt, focus visible i ordenat, teclat complet, focus roving de les pestanyes mòbils, Escape als diàlegs cancel·lables, focus trap i retorn del focus, noms accessibles i anuncis de canvi de ruta. Els canvis compartits de focus, diàlegs, navegació o tokens de color han de superar aquest projecte abans de publicar una release.
L’estil global de focus utilitza l’atribut data-focus-modality a l’arrel del
document. L’activació amb punter elimina els contorns genèrics; amb teclat
s’apliquen indicadors contextuals: la vora existent als camps, subratllat als
enllaços i contorn als controls sense vora. Els títols editables del Vault
conserven només el cursor d’escriptura. Les proves unitàries cobreixen els
canvis de modalitat i les proves de navegador, el focus amb punter i teclat en
els temes clar i fosc.
Comprovacions de desplegament¶
El constructor d'imatges de CI registra la revisió Git extreta a
org.opencontainers.image.revision i un identificador únic de la invocació a
io.gnosi.ci.build-id. Cal llistar i eliminar correctament les imatges de
destinació existents, sense forçar les imatges en ús. Després de cada construcció,
també si acaba amb codi zero, la inspecció ha de retornar les dues etiquetes
coincidents. Una fallada del client posterior a la càrrega només es pot recuperar
amb aquesta evidència; una imatge anterior del mateix commit també falla perquè
té un identificador d'invocació diferent. Les metadades absents o malformades i
les fallades d'inspecció o eliminació continuen sent errors. La prova real
d'arrencada i persistència continua sent obligatòria.
La imatge del backend ara utilitza uv 0.10.0 amb UV_HTTP_TIMEOUT=120,
UV_HTTP_RETRIES=3, UV_CONCURRENT_DOWNLOADS=4 i UV_CONCURRENT_INSTALLS=2
explícitament a l'ordre d'instal·lació congelada. Les variables del workflow no
s'hereten implícitament dins de les construccions Docker. Aquests valors només
afecten la instal·lació, no l'entorn d'execució de l'aplicació. Les proves de
regressió comparen l'instal·lador i els límits amb la CI compartida i rebutgen
valors absents, canviats o duplicats. Les dependències de l'aplicació, els
lockfiles, l'assignació d'executors i l'empaquetament de versions no canvien.
La CI de Docker valida Compose, construeix les dues imatges i executa
scripts/smoke_docker.sh. La prova comprova el backend i el frontend en marxa,
recrea els contenidors i verifica un marcador sintètic a /data. La neteja de
sortida només afecta el seu projecte Compose amb nom únic, inclosos els volums
de prova d'aquell projecte.
La neteja final executa scripts/ci/prepare_docker_runner.py --cleanup: retira
només les etiquetes d'imatge gnosi-frontend:ci i gnosi-backend:ci sense forçar
imatges en ús, neteja la memòria cau de construcció no utilitzada i regenerable,
i verifica almenys 12 GiB lliures. Mai no fa una neteja global de contenidors,
xarxes o volums. Una ordre de neteja de memòria cau finalitzada que informa de
context deadline exceeded es pot repetir fins a tres intents totals,
separats per cinc segons. Cada intent té un límit de procés de 120 segons;
els passos de capacitat i neteja final tenen límits de deu minuts. Altres
errors, un límit de procés esgotat, els reintents esgotats o l'espai insuficient
continuen fent fallar el check. Mai no s'ometen les construccions ni la prova
de persistència.
L'eliminació d'imatges té una recuperació limitada pròpia: si s'esgota el límit de procés de 60 segons, una consulta correcta ha de confirmar si encara existeix l'etiqueta exacta de CI. La seva absència verificada completa l'eliminació. Si continua existint, es permet un reintent al cap de cinc segons, comprovant-ne de nou la presència abans d'eliminar-la. Una inspecció fallida, una imatge en ús o un segon timeout amb l'etiqueta encara present continuen sent errors. Es mantenen el límit exterior de deu minuts i la comprovació final de 12 GiB.
El job de frontend aplica el pressupost revisat de 4 GiB de heap de Node a tot el job perquè lint, comprovació de tipus, proves i build de producció comparteixin el mateix contracte de memòria previsible. Les proves de política de versions d’escriptori verifiquen les assignacions locals exactes i tot l’entorn de recursos Node/Python. Les proves de mutació rebutgen executors de GitHub, assignacions locals modificades, pressupostos absents i sobreescriptures per pas. Els canvis de CI requereixen tota la suite d’escriptori i els contractes de planificació Python.
La CI d'Electron configura paquets per a macOS arm64/x64, Linux arm64 i Windows x64. Configurar aquesta matriu, passar proves unitàries desktop o comprovar una migració sintètica del perfil del navegador no valida els instal·ladors ni el backend congelat. Cada arquitectura requereix evidència d'instal·lació, arrencada, persistència i actualització des de 2.x. Actualment, macOS utilitza actualitzacions manuals mitjançant l'instal·lador. Una execució local a macOS no acredita les altres plataformes: no publiqueu 3.0 abans de superar tota la matriu de release.
Mapatge de canvi a prova¶
| Canvi | Evidència mínima |
|---|---|
| Només documentació revisada | Comprovació del generador, validador, build estricte i prova bàsica del portal al navegador. |
| Lògica dels catàlegs generats | Proves unitàries del generador, determinisme en dues execucions, validador i build estricte. |
| Comportament del backend | Regressió acotada de pytest i suite d'integració afectada. |
| Comportament del frontend | Vitest quan sigui viable, comprovació i18n, build de producció, acció al navegador i captura. |
| Accessibilitat o token compartit d’interfície | Vitest de la primitiva, paritat dels quatre idiomes, matriu axe en clar i fosc, proves de teclat i captura del navegador. |
| Autenticació, seguretat o rutes | Proves negatives i intents entre àmbits, no només el camí correcte. |
| Desplegament o dependències | Verificació nativa i CI de Docker o paquets segons correspongui. |
Catàleg de proves¶
El catàleg de proves generat enumera els fitxers propis i senyals de navegació. La recollida del runner continua sent l'autoritat per comptar les proves executables.