diff --git a/.dockerignore b/.dockerignore index 0e4a88fd2f..542c96700e 100644 --- a/.dockerignore +++ b/.dockerignore @@ -5,7 +5,9 @@ # Dependencies node_modules +**/node_modules .venv +**/.venv # CI/CD .github diff --git a/Dockerfile b/Dockerfile index 7f4ebc2d15..d988ea6407 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,7 +14,7 @@ ENV PLAYWRIGHT_BROWSERS_PATH=/opt/hermes/.playwright # that would otherwise accumulate when hermes runs as PID 1. See #15012. RUN apt-get update && \ apt-get install -y --no-install-recommends \ - build-essential nodejs npm python3 ripgrep ffmpeg gcc python3-dev libffi-dev procps git openssh-client docker-cli tini && \ + build-essential nodejs npm python3 ripgrep ffmpeg gcc python3-dev libffi-dev procps git openssh-client docker-cli tini && \ rm -rf /var/lib/apt/lists/* # Non-root user for runtime; UID can be overridden via HERMES_UID at runtime @@ -45,7 +45,13 @@ COPY --chown=hermes:hermes . . # Build browser dashboard and terminal UI assets. RUN cd web && npm run build && \ - cd ../ui-tui && npm run build + cd ../ui-tui && npm run build && \ + rm -rf node_modules/@hermes/ink && \ + rm -rf packages/hermes-ink/node_modules && \ + cp -R packages/hermes-ink node_modules/@hermes/ink && \ + npm install --omit=dev --prefer-offline --no-audit --prefix node_modules/@hermes/ink && \ + rm -rf node_modules/@hermes/ink/node_modules/react && \ + node --input-type=module -e "await import('@hermes/ink')" # ---------- Permissions ---------- # Make install dir world-readable so any HERMES_UID can read it at runtime. diff --git a/tests/hermes_cli/test_cmd_update.py b/tests/hermes_cli/test_cmd_update.py index 1e6a2245b2..caac6d3727 100644 --- a/tests/hermes_cli/test_cmd_update.py +++ b/tests/hermes_cli/test_cmd_update.py @@ -130,7 +130,7 @@ class TestCmdUpdateBranchFallback: # 3. web/ — install + "npm run build" for the web frontend full_flags = [ "/usr/bin/npm", - "install", + "ci", "--silent", "--no-fund", "--no-audit", @@ -139,7 +139,7 @@ class TestCmdUpdateBranchFallback: assert npm_calls == [ (full_flags, PROJECT_ROOT), (full_flags, PROJECT_ROOT / "ui-tui"), - (["/usr/bin/npm", "install", "--silent"], PROJECT_ROOT / "web"), + (["/usr/bin/npm", "ci", "--silent"], PROJECT_ROOT / "web"), (["/usr/bin/npm", "run", "build"], PROJECT_ROOT / "web"), ] diff --git a/tests/tools/test_dockerfile_pid1_reaping.py b/tests/tools/test_dockerfile_pid1_reaping.py index 7538162798..52532a78dd 100644 --- a/tests/tools/test_dockerfile_pid1_reaping.py +++ b/tests/tools/test_dockerfile_pid1_reaping.py @@ -21,6 +21,7 @@ import pytest REPO_ROOT = Path(__file__).resolve().parents[2] DOCKERFILE = REPO_ROOT / "Dockerfile" +DOCKERIGNORE = REPO_ROOT / ".dockerignore" @pytest.fixture(scope="module") @@ -108,17 +109,37 @@ 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) + "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 + "ui-tui" in step and "npm" in step and "run build" in step for step in _run_steps(dockerfile_text) ) + + +def test_dockerfile_materializes_local_tui_ink_package(dockerfile_text): + assert any( + "ui-tui" in step + and "node_modules/@hermes/ink" in step + and "packages/hermes-ink" in step + and "rm -rf packages/hermes-ink/node_modules" in step + and "npm install --omit=dev" in step + and "--prefix node_modules/@hermes/ink" in step + and "rm -rf node_modules/@hermes/ink/node_modules/react" in step + and "await import('@hermes/ink')" in step + for step in _run_steps(dockerfile_text) + ) + + +def test_dockerignore_excludes_nested_dependency_dirs(): + if not DOCKERIGNORE.exists(): + pytest.skip(".dockerignore not present in this checkout") + + text = DOCKERIGNORE.read_text() + + assert "**/node_modules" in text + assert "**/.venv" in text