"""De volgorde van de lagen in de Dockerfile bepaalt hoe lang een build duurt. Docker hergebruikt een laag alleen zolang niets ervóór is gewijzigd. Stond het versienummer bovenaan, dan gooide élke uitgave alles daarna weg: apt-get, de Docker-CLI van 70 MB, de front-end-bestanden. Een release duurde daardoor een kwartier terwijl er drie regels Python waren veranderd. """ from pathlib import Path WORTEL = Path(__file__).resolve().parent.parent REGELS = (WORTEL / "Dockerfile").read_text(encoding="utf-8").splitlines() def _regel_van(fragment: str) -> int: """Het regelnummer van de eerste regel die dit fragment bevat.""" for i, r in enumerate(REGELS): if fragment in r and not r.lstrip().startswith("#"): return i raise AssertionError(f"niet gevonden in de Dockerfile: {fragment}") def test_de_broncode_komt_na_alles_wat_zelden_verandert(): """De code wijzigt bij elke commit; wat daarvoor staat blijft in de cache.""" code = _regel_van("COPY server-up/ ./") for eerder in ("apt-get update", "download.docker.com", "COPY --from=build /inst", "static/fonts", "static/vendor", "mkdir -p /data/stacks"): assert _regel_van(eerder) < code, \ f"'{eerder}' hoort vóór de broncode te staan, anders vervalt zijn cache" def test_het_versienummer_staat_helemaal_onderaan(): """SU_VERSION verandert per uitgave. Alles wat erná komt wordt opnieuw gebouwd, dus er hoort niets meer achter te staan dan het label zelf.""" versie = _regel_van("ARG SU_VERSION") for later in ("apt-get update", "download.docker.com", "static/vendor", "COPY server-up/ ./", "ENTRYPOINT"): assert _regel_van(later) < versie, \ f"'{later}' staat ná ARG SU_VERSION en wordt dus elke release herbouwd" def test_de_frontendbestanden_worden_niet_door_de_broncode_overschreven(): """Ze komen nu vóór `COPY server-up/`. Dat mag alleen als daar geen eigen static-map in zit, want anders zou die de gedownloade bestanden vervangen.""" assert not (WORTEL / "server-up" / "static").exists(), ( "server-up/static bestaat nu wél; zet de downloads dan weer ná de COPY " "of geef ze een andere plek") def test_de_gepinde_versies_staan_er_nog(): """De cache blijft alleen staan zolang deze regels niet wijzigen — dus als ze veranderen hoort dat een bewuste keuze te zijn.""" tekst = "\n".join(REGELS) for gepind in ("@mdi/font@7.4.47", "alpinejs@3.14.1", "htmx.org@2.0.3", "tailwindcss.com/3.4.16", "docker-27.5.1.tgz", "compose/releases/download/v2.32.4"): assert gepind in tekst, f"versie niet meer vastgezet: {gepind}"