fix(docker): materialize bundled TUI Ink package (#16690)
* fix(docker): materialize bundled TUI Ink package * fix(docker): keep nested deps out of build context * fix(docker): make TUI Ink smoke check deterministic * test(docker): skip dockerignore assertion in partial checkouts * fix(docker): use lockfile install for vendored Ink deps * test(cli): expect deterministic npm ci in /update flow * fix(docker): fall back to npm install for vendored Ink deps * fix(docker): keep bundled Ink source for TUI runtime builds * fix(docker): dedupe React in vendored Ink package
This commit is contained in:
parent
124da27767
commit
5f215b13ce
@ -5,7 +5,9 @@
|
|||||||
|
|
||||||
# Dependencies
|
# Dependencies
|
||||||
node_modules
|
node_modules
|
||||||
|
**/node_modules
|
||||||
.venv
|
.venv
|
||||||
|
**/.venv
|
||||||
|
|
||||||
# CI/CD
|
# CI/CD
|
||||||
.github
|
.github
|
||||||
|
|||||||
10
Dockerfile
10
Dockerfile
@ -14,7 +14,7 @@ ENV PLAYWRIGHT_BROWSERS_PATH=/opt/hermes/.playwright
|
|||||||
# that would otherwise accumulate when hermes runs as PID 1. See #15012.
|
# that would otherwise accumulate when hermes runs as PID 1. See #15012.
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
apt-get install -y --no-install-recommends \
|
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/*
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# Non-root user for runtime; UID can be overridden via HERMES_UID at runtime
|
# 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.
|
# Build browser dashboard and terminal UI assets.
|
||||||
RUN cd web && npm run build && \
|
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 ----------
|
# ---------- Permissions ----------
|
||||||
# Make install dir world-readable so any HERMES_UID can read it at runtime.
|
# Make install dir world-readable so any HERMES_UID can read it at runtime.
|
||||||
|
|||||||
@ -130,7 +130,7 @@ class TestCmdUpdateBranchFallback:
|
|||||||
# 3. web/ — install + "npm run build" for the web frontend
|
# 3. web/ — install + "npm run build" for the web frontend
|
||||||
full_flags = [
|
full_flags = [
|
||||||
"/usr/bin/npm",
|
"/usr/bin/npm",
|
||||||
"install",
|
"ci",
|
||||||
"--silent",
|
"--silent",
|
||||||
"--no-fund",
|
"--no-fund",
|
||||||
"--no-audit",
|
"--no-audit",
|
||||||
@ -139,7 +139,7 @@ class TestCmdUpdateBranchFallback:
|
|||||||
assert npm_calls == [
|
assert npm_calls == [
|
||||||
(full_flags, PROJECT_ROOT),
|
(full_flags, PROJECT_ROOT),
|
||||||
(full_flags, PROJECT_ROOT / "ui-tui"),
|
(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"),
|
(["/usr/bin/npm", "run", "build"], PROJECT_ROOT / "web"),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@ -21,6 +21,7 @@ import pytest
|
|||||||
|
|
||||||
REPO_ROOT = Path(__file__).resolve().parents[2]
|
REPO_ROOT = Path(__file__).resolve().parents[2]
|
||||||
DOCKERFILE = REPO_ROOT / "Dockerfile"
|
DOCKERFILE = REPO_ROOT / "Dockerfile"
|
||||||
|
DOCKERIGNORE = REPO_ROOT / ".dockerignore"
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="module")
|
@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/package.json" in dockerfile_text
|
||||||
assert "ui-tui/packages/hermes-ink/package-lock.json" in dockerfile_text
|
assert "ui-tui/packages/hermes-ink/package-lock.json" in dockerfile_text
|
||||||
assert any(
|
assert any(
|
||||||
"ui-tui" in step
|
"ui-tui" in step and "npm" in step and (" install" in step or " ci" in step)
|
||||||
and "npm" in step
|
|
||||||
and (" install" in step or " ci" in step)
|
|
||||||
for step in _run_steps(dockerfile_text)
|
for step in _run_steps(dockerfile_text)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_dockerfile_builds_tui_assets(dockerfile_text):
|
def test_dockerfile_builds_tui_assets(dockerfile_text):
|
||||||
assert any(
|
assert any(
|
||||||
"ui-tui" in step
|
"ui-tui" in step and "npm" in step and "run build" in step
|
||||||
and "npm" in step
|
|
||||||
and "run build" in step
|
|
||||||
for step in _run_steps(dockerfile_text)
|
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
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user