diff --git a/tests/tools/test_dockerfile_pid1_reaping.py b/tests/tools/test_dockerfile_pid1_reaping.py index 52532a78..8d5e38f2 100644 --- a/tests/tools/test_dockerfile_pid1_reaping.py +++ b/tests/tools/test_dockerfile_pid1_reaping.py @@ -106,8 +106,16 @@ def test_dockerfile_entrypoint_routes_through_the_init(dockerfile_text): def test_dockerfile_installs_tui_dependencies(dockerfile_text): + """The Dockerfile must install ui-tui's npm dependencies during build, + and must copy the workspace package tree (not just manifests) so npm + can resolve the @hermes/ink ``file:`` dep without falling back to the + bare manifest. See PR #16690 + a49f4c6 for the design. + """ assert "ui-tui/package.json" in dockerfile_text - assert "ui-tui/packages/hermes-ink/package-lock.json" in dockerfile_text + # ui-tui/packages/hermes-ink/ is a `file:` workspace; copying the FULL + # tree (not just its manifests) is what lets npm resolve it correctly. + # Catches the regression where someone reverts to manifest-only copies. + assert "COPY ui-tui/packages/hermes-ink/ ui-tui/packages/hermes-ink/" 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) @@ -121,17 +129,24 @@ def test_dockerfile_builds_tui_assets(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_dockerfile_forces_npm_install_links_false_for_workspace_resolution(dockerfile_text): + """The Dockerfile must force npm to install ``file:`` deps as symlinks + rather than copies. Debian's bundled npm 9.x defaults to install-links=true + (deps installed as copies), which produces a hidden + node_modules/.package-lock.json that permanently disagrees with the root + lockfile (which is generated by npm 10+ using symlinks). The disagreement + trips the TUI launcher's _tui_need_npm_install() check on every startup + and triggers an EACCES-failing runtime `npm install`. + + Replaces the older `--prefix node_modules/@hermes/ink` materialization + pattern (PR #16690) — that approach was retired in a49f4c6 in favor of + install-links=false because the materialization step was rebuilding TUI + assets unnecessarily. + """ + assert "npm_config_install_links=false" in dockerfile_text, ( + "ENV npm_config_install_links=false missing — without it, Debian npm 9.x " + "installs file: deps as copies, breaking @hermes/ink workspace resolution. " + "See PR #16690 + a49f4c6." )