From b479205396f0405d9644a090044550c16c6faf32 Mon Sep 17 00:00:00 2001 From: Brooklyn Nicholson Date: Mon, 27 Apr 2026 10:15:00 -0500 Subject: [PATCH] fix(docker): tighten TUI build contract --- Dockerfile | 2 +- tests/tools/test_dockerfile_pid1_reaping.py | 40 +++++++++++++++++++-- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index bfe6402d6..7f4ebc2d1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -31,7 +31,7 @@ WORKDIR /opt/hermes COPY package.json package-lock.json ./ COPY web/package.json web/package-lock.json web/ COPY ui-tui/package.json ui-tui/package-lock.json ui-tui/ -COPY ui-tui/packages/hermes-ink/package.json ui-tui/packages/hermes-ink/ +COPY ui-tui/packages/hermes-ink/package.json ui-tui/packages/hermes-ink/package-lock.json ui-tui/packages/hermes-ink/ RUN npm install --prefer-offline --no-audit && \ npx playwright install --with-deps chromium --only-shell && \ diff --git a/tests/tools/test_dockerfile_pid1_reaping.py b/tests/tools/test_dockerfile_pid1_reaping.py index 657eba9dc..1e47b64f6 100644 --- a/tests/tools/test_dockerfile_pid1_reaping.py +++ b/tests/tools/test_dockerfile_pid1_reaping.py @@ -30,6 +30,31 @@ def dockerfile_text() -> str: return DOCKERFILE.read_text() +def _dockerfile_instructions(dockerfile_text: str) -> list[str]: + instructions: list[str] = [] + current = "" + + for raw_line in dockerfile_text.splitlines(): + line = raw_line.strip() + if not line or line.startswith("#"): + continue + + current = f"{current} {line.removesuffix('\\').strip()}".strip() + if not line.endswith("\\"): + instructions.append(current) + current = "" + + return instructions + + +def _run_steps(dockerfile_text: str) -> list[str]: + return [ + instruction + for instruction in _dockerfile_instructions(dockerfile_text) + if instruction.startswith("RUN ") + ] + + def test_dockerfile_installs_an_init_for_zombie_reaping(dockerfile_text): """Some init (tini, dumb-init, catatonit) must be installed. @@ -80,8 +105,19 @@ def test_dockerfile_entrypoint_routes_through_the_init(dockerfile_text): def test_dockerfile_installs_tui_dependencies(dockerfile_text): assert "ui-tui/package.json" in dockerfile_text - assert "cd ui-tui && npm install" in dockerfile_text + assert "ui-tui/packages/hermes-ink/package-lock.json" in dockerfile_text + assert any( + "ui-tui" in step + and "npm" in step + and (" install" in step or " ci" in step) + for step in _run_steps(dockerfile_text) + ) def test_dockerfile_builds_tui_assets(dockerfile_text): - assert "cd ../ui-tui && npm run build" in dockerfile_text + assert any( + "ui-tui" in step + and "npm" in step + and "run build" in step + for step in _run_steps(dockerfile_text) + )