From 9037f2dd69eb2806791b51ab79f0f9bd11673f7e Mon Sep 17 00:00:00 2001 From: bruno Date: Tue, 3 Nov 2026 08:44:08 -0500 Subject: [PATCH 1/4] =?UTF-8?q?fix(ci):=20e2e=20joint=20l'app=20par=20DNS?= =?UTF-8?q?=20de=20r=C3=A9seau=20(DinD),=20plus=20de=20port=20publi=C3=A9?= =?UTF-8?q?=20ni=20curls=20sans=20timeout?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le step 'Start ObsiGate' pendait : boucle de health curls sans --max-time vers l'IP passerelle:2029 (injoignable/port fuité par un run antérieur) = 150 s de blocage par tentative. L'app est désormais rattachée au réseau du job et jointe par nom (obsigate-e2e:8080), avec timeout partout et dump des logs container à l'échec. --- .gitea/workflows/ci.yml | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index fa03077..7df7f81 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -272,7 +272,13 @@ jobs: - name: Start ObsiGate run: | docker rm -f obsigate-e2e 2>/dev/null || true - docker create --name obsigate-e2e -p 2029:8080 \ + # DinD robuste : PAS de port publié (les ports 2029 fuités par des + # runs antérieurs font échouer « docker start », et l'IP passerelle + # du job n'est pas toujours joignable → boucle de health curls sans + # timeout qui pendaient 150 s chacun). À la place, l'app est + # rattachée au réseau du job et jointable par nom DNS embarqué. + JOBNET=$(docker inspect -f '{{range $k, $v := .NetworkSettings.Networks}}{{$k}} {{end}}' "$(hostname)" 2>/dev/null | awk '{print $1}') + docker create --name obsigate-e2e \ -v $(pwd)/test_vault:/vaults/TestVault \ -v $(pwd)/test_dir:/vaults/TestDir \ -e VAULT_1_NAME=TestVault \ @@ -288,17 +294,22 @@ jobs: # fixtures avant le démarrage (l'indexeur scanne au démarrage). docker cp test_vault/. obsigate-e2e:/vaults/TestVault docker cp test_dir/. obsigate-e2e:/vaults/TestDir + if [ -n "$JOBNET" ]; then docker network connect "$JOBNET" obsigate-e2e || true; fi docker start obsigate-e2e - # Le port publié est joignable via l'IP de la passerelle (localhost - # du job container ne voit pas le port publié sur l'hôte). - GW=$(ip route show default | awk '{print $3}' || echo 172.17.0.1) - echo "Gateway IP: $GW" - # Wait for health check - for i in $(seq 1 30); do - if curl -sf "http://$GW:2029/api/health"; then echo "Health OK"; break; fi + if [ -n "$JOBNET" ]; then + APP_URL="http://obsigate-e2e:8080" + else + echo "Réseau du job introuvable (JOBNET vide) — impossible de localiser l'app sans port publié" + exit 1 + fi + echo "APP_URL: $APP_URL" + # --max-time : ne JAMAIS pendre sans timeout (bug d'origine : curls + # sans timeout = 150 s × 31 tentatives, job « bloqué »). + for i in $(seq 1 40); do + if curl -sf --max-time 3 "$APP_URL/api/health"; then echo "Health OK"; break; fi sleep 1 done - curl -sf "http://$GW:2029/api/health" >/dev/null || { echo "App not reachable at $GW:2029"; exit 1; } + curl -sf --max-time 5 "$APP_URL/api/health" >/dev/null || { echo "App not reachable at $APP_URL"; docker logs --tail 40 obsigate-e2e; exit 1; } # Les fixtures sont copiées via `docker cp` en root → rendre le vault # inscriptible par l'utilisateur non-root de l'app (UID 1000), sinon # toute création/édition de fichier renvoie 403 « Vault is read-only ». @@ -306,9 +317,10 @@ jobs: - name: Run E2E tests run: | - GW=$(ip route show default | awk '{print $3}' || echo 172.17.0.1) - echo "Using BASE_URL=http://$GW:2029" - BASE_URL="http://$GW:2029" npx playwright test --project=chromium-desktop --reporter=list + BASE_URL="http://obsigate-e2e:8080" + docker exec obsigate-e2e true >/dev/null 2>&1 || { echo "obsigate-e2e n'est pas en marche"; exit 1; } + echo "Using BASE_URL=$BASE_URL" + BASE_URL="$BASE_URL" npx playwright test --project=chromium-desktop --reporter=list - name: Upload test results if: always() -- 2.54.0 From ca367b6918bda4153c2d90a910682e4dc7d7b5ab Mon Sep 17 00:00:00 2001 From: bruno Date: Tue, 3 Nov 2026 09:26:42 -0500 Subject: [PATCH 2/4] =?UTF-8?q?test(e2e):=20helpers=20ne=20d=C3=A9pendent?= =?UTF-8?q?=20plus=20du=20signal=20=5F=5FOBSIGATE=5FBOOTED=20retir=C3=A9?= =?UTF-8?q?=20(bfe0c75)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bfe0c75 a retiré le splash et son signal de boot côté app sans adapter les helpers des specs ; login() attendait window.__OBSIGATE_BOOTED → timeout 60 s × chaque test des 8 suites. Signal de rechange sans dépendance au flag interne : document prêt ET premier .tree-item rendu (preuve que l'init a lié données+handlers). Validé local : 14 passed sur les 3 suites qui échouaient en CI (obsigate:ci v2.82.8, auth off, mêmes fixtures). --- tests/e2e/excalidraw.spec.js | 2 +- tests/e2e/header-sidebar.spec.js | 2 +- tests/e2e/image-viewer.spec.js | 2 +- tests/e2e/media-viewer.spec.js | 2 +- tests/e2e/nav-tab.spec.js | 2 +- tests/e2e/pdf-viewer.spec.js | 2 +- tests/e2e/xlsx-viewer.spec.js | 2 +- tests/e2e/xss.spec.js | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/e2e/excalidraw.spec.js b/tests/e2e/excalidraw.spec.js index dfa88dc..0936c12 100644 --- a/tests/e2e/excalidraw.spec.js +++ b/tests/e2e/excalidraw.spec.js @@ -25,7 +25,7 @@ async function login(page) { await page.click('#login-btn'); } // Wait until app init() resolved (all handlers bound). - await page.waitForFunction(() => window.__OBSIGATE_BOOTED === true, { timeout: 20000 }); + await page.waitForFunction(() => document.readyState === 'complete' && !!document.querySelector('.tree-item'), { timeout: 20000 }); } async function openFile(page, vault, filePath) { diff --git a/tests/e2e/header-sidebar.spec.js b/tests/e2e/header-sidebar.spec.js index 9b3bea9..cafadba 100644 --- a/tests/e2e/header-sidebar.spec.js +++ b/tests/e2e/header-sidebar.spec.js @@ -28,7 +28,7 @@ async function login(page) { await page.fill('#login-password', CREDS.password); await page.click('#login-btn'); } - await page.waitForFunction(() => window.__OBSIGATE_BOOTED === true, { timeout: 20000 }); + await page.waitForFunction(() => document.readyState === 'complete' && !!document.querySelector('.tree-item'), { timeout: 20000 }); } async function authEnabled(page) { diff --git a/tests/e2e/image-viewer.spec.js b/tests/e2e/image-viewer.spec.js index 85911e7..c552a58 100644 --- a/tests/e2e/image-viewer.spec.js +++ b/tests/e2e/image-viewer.spec.js @@ -26,7 +26,7 @@ async function login(page) { await page.fill('#login-password', CREDS.password); await page.click('#login-btn'); } - await page.waitForFunction(() => window.__OBSIGATE_BOOTED === true, { timeout: 20000 }); + await page.waitForFunction(() => document.readyState === 'complete' && !!document.querySelector('.tree-item'), { timeout: 20000 }); } async function openFile(page, vault, filePath) { diff --git a/tests/e2e/media-viewer.spec.js b/tests/e2e/media-viewer.spec.js index 18baa71..5ca245f 100644 --- a/tests/e2e/media-viewer.spec.js +++ b/tests/e2e/media-viewer.spec.js @@ -25,7 +25,7 @@ async function login(page) { await page.fill('#login-password', CREDS.password); await page.click('#login-btn'); } - await page.waitForFunction(() => window.__OBSIGATE_BOOTED === true, { timeout: 20000 }); + await page.waitForFunction(() => document.readyState === 'complete' && !!document.querySelector('.tree-item'), { timeout: 20000 }); } async function openFile(page, vault, filePath) { diff --git a/tests/e2e/nav-tab.spec.js b/tests/e2e/nav-tab.spec.js index 2cb3957..98650ab 100644 --- a/tests/e2e/nav-tab.spec.js +++ b/tests/e2e/nav-tab.spec.js @@ -12,7 +12,7 @@ import { test, expect } from '@playwright/test'; async function boot(page) { await page.goto('/'); - await page.waitForFunction(() => window.__OBSIGATE_BOOTED === true, { timeout: 20000 }); + await page.waitForFunction(() => document.readyState === 'complete' && !!document.querySelector('.tree-item'), { timeout: 20000 }); await page.waitForSelector('#dashboard-home, #search-input', { timeout: 15000 }); } diff --git a/tests/e2e/pdf-viewer.spec.js b/tests/e2e/pdf-viewer.spec.js index 515f4cf..b1bea0c 100644 --- a/tests/e2e/pdf-viewer.spec.js +++ b/tests/e2e/pdf-viewer.spec.js @@ -30,7 +30,7 @@ async function login(page) { await page.fill('#login-password', CREDS.password); await page.click('#login-btn'); } - await page.waitForFunction(() => window.__OBSIGATE_BOOTED === true, { timeout: 20000 }); + await page.waitForFunction(() => document.readyState === 'complete' && !!document.querySelector('.tree-item'), { timeout: 20000 }); } async function openFile(page, vault, filePath) { diff --git a/tests/e2e/xlsx-viewer.spec.js b/tests/e2e/xlsx-viewer.spec.js index ff9976a..e1cceaf 100644 --- a/tests/e2e/xlsx-viewer.spec.js +++ b/tests/e2e/xlsx-viewer.spec.js @@ -57,7 +57,7 @@ async function login(page) { await page.fill('#login-password', process.env.OBSIGATE_PASS || 'test123'); await page.click('#login-btn'); } - await page.waitForFunction(() => window.__OBSIGATE_BOOTED === true, { timeout: 20000 }); + await page.waitForFunction(() => document.readyState === 'complete' && !!document.querySelector('.tree-item'), { timeout: 20000 }); } async function openFixture(page) { diff --git a/tests/e2e/xss.spec.js b/tests/e2e/xss.spec.js index 68022f4..e3600a2 100644 --- a/tests/e2e/xss.spec.js +++ b/tests/e2e/xss.spec.js @@ -117,7 +117,7 @@ test.describe('XSS — lecteur markdown (BUG-021)', () => { await api(request, 'POST', `/api/file/${VAULT}`, { path: XSS_FILE, content: `${XSS_BODY}\n` }); await page.goto(BASE); - await page.waitForFunction(() => window.__OBSIGATE_BOOTED === true, { timeout: 20000 }); + await page.waitForFunction(() => document.readyState === 'complete' && !!document.querySelector('.tree-item'), { timeout: 20000 }); await openFile(page, VAULT, XSS_FILE); const content = page.locator('#content-area'); -- 2.54.0 From b87ac72d788f93c7a9791c24ad26a6a9f85ebfdd Mon Sep 17 00:00:00 2001 From: bruno Date: Tue, 3 Nov 2026 09:59:18 -0500 Subject: [PATCH 3/4] =?UTF-8?q?ci(wip):=20runs-on=20ci-deepin=20=E2=80=94?= =?UTF-8?q?=20contournement=20r=C3=A9gression=20extraction=20moby=2029.x?= =?UTF-8?q?=20du=20runner=20VM=20(=C3=A0=20retirer=20quand=20daemon=20VM?= =?UTF-8?q?=20r=C3=A9par=C3=A9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitea/workflows/ci.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index 7df7f81..c8ffe3b 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -12,7 +12,7 @@ on: jobs: # ── Lint ────────────────────────────────────────────────────────── lint: - runs-on: ubuntu-latest + runs-on: ci-deepin steps: - uses: actions/checkout@v4 @@ -100,7 +100,7 @@ jobs: # ── Tests ───────────────────────────────────────────────────────── test: needs: lint - runs-on: ubuntu-latest + runs-on: ci-deepin steps: - uses: actions/checkout@v4 @@ -127,7 +127,7 @@ jobs: # ── Security scan ───────────────────────────────────────────────── security: - runs-on: ubuntu-latest + runs-on: ci-deepin steps: - uses: actions/checkout@v4 @@ -209,7 +209,7 @@ jobs: # ── Docker build ────────────────────────────────────────────────── build: needs: test - runs-on: ubuntu-latest + runs-on: ci-deepin steps: - uses: actions/checkout@v4 @@ -252,7 +252,7 @@ jobs: # ── E2E Tests (Playwright) ───────────────────────────────────────── e2e: needs: build - runs-on: ubuntu-latest + runs-on: ci-deepin steps: - uses: actions/checkout@v4 -- 2.54.0 From e28a537f79fec61691b9f0d3a2a8f6ac67658ee2 Mon Sep 17 00:00:00 2001 From: bruno Date: Tue, 3 Nov 2026 11:17:35 -0500 Subject: [PATCH 4/4] =?UTF-8?q?fix(e2e):=20z-index=20barre=20r=C3=A9sultat?= =?UTF-8?q?s=20au-dessus=20de=20la=20barre=20DRACO=20+=20signal=20de=20boo?= =?UTF-8?q?t=20du=20spec=20.ts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - obsigate.spec.ts attendait encore le flag __OBSIGATE_BOOTED retiré (même cause que les 8 suites js, corrigée ici) ; - .results-bar (z 50) était masquée par .draco-spark-flottant (z 65, même position bas-centre) → « subtree intercepts pointer events » sur #rb-next/#rb-case : 2 tests en timeout de clic. Bug d'UI réel (l'utilisateur ne peut pas cliquer les flèches pendant qu'Spark flotte), corrigé par z-index 66. Validé local : 2 passed en 10 s (au lieu de 2×60 s de timeout). --- frontend/style.css | 2 +- tests/e2e/obsigate.spec.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/style.css b/frontend/style.css index 73d72fe..d220366 100644 --- a/frontend/style.css +++ b/frontend/style.css @@ -8493,7 +8493,7 @@ body.popup-mode .content-area { box-shadow: 0 2px 16px rgba(0,0,0,0.35); width: fit-content; max-width: 95%; - z-index: 50; + z-index: 66; /* au-dessus de .draco-spark-flottant (65) sinon la barre flottante DRACO intercepte les clics des flèches de recherche */ backdrop-filter: blur(8px); } .results-bar-count { diff --git a/tests/e2e/obsigate.spec.ts b/tests/e2e/obsigate.spec.ts index 5a1f893..b76d5fe 100644 --- a/tests/e2e/obsigate.spec.ts +++ b/tests/e2e/obsigate.spec.ts @@ -9,7 +9,7 @@ const BASE = process.env.BASE_URL || 'http://localhost:2029'; async function goHome(page) { await page.goto(BASE); // Wait until app init() resolved (all handlers bound, incl. search). - await page.waitForFunction(() => (window as any).__OBSIGATE_BOOTED === true, { timeout: 20000 }); + await page.waitForFunction(() => document.readyState === 'complete' && !!document.querySelector('.tree-item'), { timeout: 20000 }); await page.waitForSelector('#dashboard-home, #search-input', { timeout: 15000 }); } -- 2.54.0