Merge pull request #16605 from NousResearch/bb/fix-tui-docker-ink-build

fix(docker): prebuild TUI assets in image
This commit is contained in:
brooklyn! 2026-04-27 10:17:58 -05:00 committed by GitHub
commit 512c610058
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 51 additions and 2 deletions

View File

@ -30,18 +30,22 @@ WORKDIR /opt/hermes
# unless the lockfiles themselves change.
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/package-lock.json ui-tui/packages/hermes-ink/
RUN npm install --prefer-offline --no-audit && \
npx playwright install --with-deps chromium --only-shell && \
(cd web && npm install --prefer-offline --no-audit) && \
(cd ui-tui && npm install --prefer-offline --no-audit) && \
npm cache clean --force
# ---------- Source code ----------
# .dockerignore excludes node_modules, so the installs above survive.
COPY --chown=hermes:hermes . .
# Build web dashboard (Vite outputs to hermes_cli/web_dist/)
RUN cd web && npm run build
# Build browser dashboard and terminal UI assets.
RUN cd web && npm run build && \
cd ../ui-tui && npm run build
# ---------- Permissions ----------
# Make install dir world-readable so any HERMES_UID can read it at runtime.

View File

@ -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.
@ -76,3 +101,23 @@ def test_dockerfile_entrypoint_routes_through_the_init(dockerfile_text):
"If tini is only installed but not wired into ENTRYPOINT, hermes "
"still runs as PID 1 and zombies will accumulate (#15012)."
)
def test_dockerfile_installs_tui_dependencies(dockerfile_text):
assert "ui-tui/package.json" 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 any(
"ui-tui" in step
and "npm" in step
and "run build" in step
for step in _run_steps(dockerfile_text)
)