Relay 0.6.0: alles in een image, de app-map is leeg

Plan Eigenimage, fase 5, op keuze van de gebruiker: een image met de relay
erbij en geen tweede recept. agent.py, nginx.conf en index.html verhuizen
naar tools/evolu-relay/ naast src/; de Dockerfile blijft op node:24-slim en
haalt nginx en python3 uit apt. Drie containers uit een image: de relay als
node via de compose, de agent en nginx als root.

Anders dan alleen verplaatst: user www-data in nginx.conf (Debian heeft geen
gebruiker nginx), geen USER meer in de image, de versie in de kop via
api/status met RELAY_APP_VERSION. VERSION 0.6.0, manifest 0.6.0, drie keer
dezelfde tag in de compose, ongepind tot de eerste push.

Tests mee verhuisd; de vormtest toetst de drie tags tegen VERSION. Niet
gebouwd: er is hier geen Docker.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Harmen
2026-09-08 16:36:30 +02:00
co-authored by Claude Fable 5.1
parent 0e824a6354
commit a694a9cbd1
18 changed files with 327 additions and 177 deletions
+20 -16
View File
@@ -22,16 +22,16 @@ Draaien:
python tests/test_relay_agent.py
De test laadt `agent.py.template` rechtstreeks. Dat kan omdat dat bestand geen
accolade-variabelen bevat en de invulling door umbreld hem dus onveranderd laat;
de eerste toets hieronder controleert precies dat.
De test laadt `tools/evolu-relay/agent.py` rechtstreeks: het bestand dat de
Dockerfile in de image zet. Tot 0.6.0 heette dat `agent.py.template` en stond het
in de app-map; de eerste toets hieronder is uit die tijd en blijft staan.
"""
import sys
# Vóór de imports, want anders is het te laat: Python legt bytecode naast
# agent.py.template zodra die geïmporteerd wordt, en die rommel hoort niet in de
# app-map. Een keer is zo'n .pyc meegegaan in een commit.
# Vóór de imports, want anders is het te laat: Python legt bytecode naast agent.py
# zodra die geïmporteerd wordt, en die rommel hoort niet in de repo. Een keer is
# zo'n .pyc meegegaan in een commit.
sys.dont_write_bytecode = True
import importlib.machinery # noqa: E402
@@ -42,20 +42,18 @@ import tempfile # noqa: E402
from datetime import datetime, timedelta, timezone # noqa: E402
HERE = os.path.dirname(os.path.abspath(__file__))
APP = os.path.join(HERE, os.pardir, "whatsnext-evolu-relay")
TEMPLATE = os.path.join(APP, "agent.py.template")
AGENT = os.path.join(HERE, os.pardir, "tools", "evolu-relay", "agent.py")
def load_agent(state_dir):
"""Laadt agent.py.template als module, met zijn staat in een tijdelijke map.
"""Laadt agent.py als module, met zijn staat in een tijdelijke map.
De agent leest `RELAY_STATE_DIR` op moduleniveau, dus die moet vóór het laden
in de omgeving staan. Met een expliciete loader, want importlib kijkt normaal
naar de extensie en .template staat daar niet tussen.
in de omgeving staan. Met een expliciete loader, buiten sys.path om.
"""
os.environ["RELAY_STATE_DIR"] = state_dir
loader = importlib.machinery.SourceFileLoader("relay_agent", TEMPLATE)
spec = importlib.util.spec_from_file_location("relay_agent", TEMPLATE, loader=loader)
loader = importlib.machinery.SourceFileLoader("relay_agent", AGENT)
spec = importlib.util.spec_from_file_location("relay_agent", AGENT, loader=loader)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
@@ -94,11 +92,17 @@ def schrijf_owners(state_dir, staat):
# ── De aanname waar deze hele test op rust ───────────────────────────────────
def test_template_is_invulbaar_zonder_schade(u):
with open(TEMPLATE, "r", encoding="utf-8") as f:
"""Een restant uit de template-tijd dat blijft staan.
Het bestand zit sinds 0.6.0 in de image en gaat door geen envsubst meer. Maar
als iemand het ooit weer als template in een app-map zet, is dit de toets die
het meteen ziet.
"""
with open(AGENT, "r", encoding="utf-8") as f:
inhoud = f.read()
u.check("template bevat geen dollartekens",
u.check("agent.py bevat geen dollartekens",
"$" not in inhoud,
"umbreld zou die invullen en de Python-code slopen")
"een envsubst-stap zou die invullen en de Python-code slopen")
# ── Het tijdvenster ─────────────────────────────────────────────────────────