Gate 0.1.0: eigen image, het command-blok is een script, de app-map is leeg
Plan Eigenimage, fase 1 tot en met 3. De vier templates verhuizen naar tools/electrum-gate/ zonder extensie; daarnaast Dockerfile (nginx:1.30-alpine plus python3), entrypoint.sh (het command-blok van de compose, zonder $$) en build.sh naar het voorbeeld van Evolu Relay. Een image voor beide containers, gebouwd op de Umbrel; open punt 2 en 3 daarmee beslist. Inhoudelijk anders dan alleen verplaatst: het log_format staat in stream.conf zelf, het backend-adres komt via twee plaatshouders zonder dollarteken uit de omgeving (ook in de server-service), en de pagina haalt versie en adres uit status.json via GATE_APP_VERSION. Tests mee verhuisd en uitgebreid: entrypoint.sh en Dockerfile in plaats van het command-blok, en de tag in de compose gelijk aan VERSION in build.sh voor elke eigen image. Mutatie-getest met drie ingrepen. Nog niet gebouwd: er is hier geen Docker. De tag staat ongepind tot de eerste push; dat is fase 4 en die is van de gebruiker. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
7b3804df89
commit
973b24a23f
@@ -20,7 +20,9 @@ Wat deze toetsen expres NIET doen: eisen dat elke image op een digest gepind is.
|
||||
Dat is wél de regel, maar op 25-08-2026 haalt geen van de twee apps hem, en een
|
||||
suite die altijd rood staat wordt niet gelezen. Het staat als taak in de plannen
|
||||
Umbrelapp en Publicatie-Gate. Wat hier wel gebeurt is de pinstatus afdrukken, zodat
|
||||
je hem ziet zonder erover te struikelen.
|
||||
je hem ziet zonder erover te struikelen. Wat wél getoetst wordt, sinds 07-09-2026:
|
||||
dat de tag van een eigen image gelijk is aan VERSION in het bijbehorende
|
||||
tools/<app>/build.sh, want een tag die nooit gebouwd is faalt pas op het apparaat.
|
||||
|
||||
Deze toetsen vinden hun apps zelf. Komt er een derde app bij, dan valt die
|
||||
automatisch onder alles hierboven en hoeft hier niets bij.
|
||||
@@ -172,6 +174,61 @@ def test_manifest_volgorde(u, app):
|
||||
not extra_ertussen, "ertussen: %r" % extra_ertussen)
|
||||
|
||||
|
||||
def recept_map(app):
|
||||
"""Waar het bouwrecept van een app staat: tools/<app-id zonder store-id>/.
|
||||
|
||||
Dat is de afspraak uit CLAUDE.md: een Dockerfile hoort niet in de app-map,
|
||||
want die staat niet in de update-whitelist. De mapnaam is het app-id zonder
|
||||
het store-voorvoegsel, dus whatsnext-evolu-relay bouwt in tools/evolu-relay/.
|
||||
"""
|
||||
kort = app.split("-", 1)[1] if "-" in app else app
|
||||
return os.path.join(REPO, "tools", kort)
|
||||
|
||||
|
||||
def test_image_tag_is_de_gebouwde(u, app):
|
||||
"""De tag in de compose is VERSION uit build.sh, voor elke eigen image.
|
||||
|
||||
Een tag die in de compose staat maar nooit gebouwd is, faalt pas op het
|
||||
apparaat met "pull access denied". En andersom, een VERSION die verhoogd is
|
||||
zonder de compose mee te nemen, levert een nieuwe image en een oude
|
||||
installatie zonder dat iets dat meldt. Beide staan als regel in CLAUDE.md;
|
||||
dit is de toets erop.
|
||||
|
||||
Alleen images uit het eigen recept: een vreemde image (postgres, nginx) heeft
|
||||
geen build.sh en valt hier buiten.
|
||||
"""
|
||||
build = os.path.join(recept_map(app), "build.sh")
|
||||
if not os.path.isfile(build):
|
||||
return
|
||||
|
||||
versie = None
|
||||
for regel in lees(build).splitlines():
|
||||
if regel.startswith("VERSION="):
|
||||
versie = regel.split("=", 1)[1].strip().strip('"')
|
||||
u.check("%s: build.sh heeft een VERSION" % app, bool(versie))
|
||||
if not versie:
|
||||
return
|
||||
|
||||
kort = os.path.basename(recept_map(app))
|
||||
compose = lees(os.path.join(REPO, app, "docker-compose.yml"))
|
||||
eigen = []
|
||||
for regel in compose.splitlines():
|
||||
kaal = regel.strip()
|
||||
if not kaal.startswith("image:"):
|
||||
continue
|
||||
image = kaal.split(":", 1)[1].strip()
|
||||
repo_en_tag = image.split("@", 1)[0]
|
||||
repo_naam = repo_en_tag.rsplit(":", 1)[0]
|
||||
if repo_naam.endswith("/" + kort):
|
||||
eigen.append(repo_en_tag)
|
||||
|
||||
u.check("%s: de compose gebruikt de eigen image" % app, bool(eigen),
|
||||
"geen image op .../%s gevonden" % kort)
|
||||
verkeerd = [i for i in eigen if not i.endswith(":" + versie)]
|
||||
u.check("%s: elke eigen image heeft tag %s uit build.sh" % (app, versie),
|
||||
not verkeerd, "gevonden: %r" % verkeerd)
|
||||
|
||||
|
||||
def test_compose_bestaat_en_hangt_samen(u, app):
|
||||
"""De app_proxy moet naar een service wijzen die bestaat.
|
||||
|
||||
@@ -285,14 +342,25 @@ def test_containernamen_zijn_volledig(u, app):
|
||||
|
||||
De vorm <app-id>_<service>_1 is wél uniek. Deze toets kijkt naar de plekken
|
||||
waar een naam als hostnaam wordt gebruikt: proxy_pass in een nginx-config, en
|
||||
de omgevingsvariabelen die een hostnaam dragen.
|
||||
de omgevingsvariabelen die een hostnaam dragen. Een nginx-config kan in de
|
||||
app-map staan (als *.template) of in het bouwrecept onder tools/ (als hij in
|
||||
een eigen image zit); beide worden gelezen.
|
||||
"""
|
||||
fout = []
|
||||
|
||||
bestanden = []
|
||||
for bestandsnaam in sorted(os.listdir(os.path.join(REPO, app))):
|
||||
if not bestandsnaam.endswith(".template") and bestandsnaam != "docker-compose.yml":
|
||||
continue
|
||||
tekst = lees(os.path.join(REPO, app, bestandsnaam))
|
||||
if bestandsnaam.endswith(".template") or bestandsnaam == "docker-compose.yml":
|
||||
bestanden.append(os.path.join(REPO, app, bestandsnaam))
|
||||
recept = recept_map(app)
|
||||
if os.path.isdir(recept):
|
||||
for bestandsnaam in sorted(os.listdir(recept)):
|
||||
if bestandsnaam.endswith(".conf"):
|
||||
bestanden.append(os.path.join(recept, bestandsnaam))
|
||||
|
||||
for pad in bestanden:
|
||||
bestandsnaam = os.path.relpath(pad, REPO).replace(os.sep, "/")
|
||||
tekst = lees(pad)
|
||||
for regel in tekst.splitlines():
|
||||
kaal = regel.strip()
|
||||
if kaal.startswith("#"):
|
||||
@@ -464,6 +532,7 @@ def main():
|
||||
test_verplichte_velden(u, app)
|
||||
test_manifest_volgorde(u, app)
|
||||
test_compose_bestaat_en_hangt_samen(u, app)
|
||||
test_image_tag_is_de_gebouwde(u, app)
|
||||
test_data_onder_data(u, app)
|
||||
test_containernamen_zijn_volledig(u, app)
|
||||
test_geen_werkbestanden_in_de_app_map(u, app)
|
||||
|
||||
Reference in New Issue
Block a user