From 06fc3e579e87864729926b606eaed3274fd3f2f3 Mon Sep 17 00:00:00 2001 From: Jannes Stubbemann Date: Thu, 18 Jun 2026 19:24:11 +0200 Subject: [PATCH] fix(agent-image): ship the uv binary in the runtime stage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Second half of the #68 init-uv contract fix. #85 added the lockfiles at /opt/venv-template/, which let `init-uv` get past its `cp` step and reach `uv sync --frozen` — which then failed with exit 127 ("uv: not found"), because the runtime stage copies the resolved venv (/opt/venv) but never the uv binary. (Before #85, init-uv died at the earlier `cp`, masking this.) Copy uv/uvx into the runtime image (mirroring the builder stage) and set deterministic UV_* defaults so the pod-start `uv sync` never tries to download a Python or hardlink across the image-layer -> PVC boundary: - UV_PYTHON_DOWNLOADS=never - UV_PYTHON=/usr/local/bin/python - UV_LINK_MODE=copy Verified locally: building the image and running the exact init-uv command (cp + uv sync --frozen) now completes and populates the per-instance .venv. Refs #68 Co-Authored-By: Claude Opus 4.8 (1M context) --- images/hermes-agent/Dockerfile | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/images/hermes-agent/Dockerfile b/images/hermes-agent/Dockerfile index b5a0dc6..bdf7bbe 100644 --- a/images/hermes-agent/Dockerfile +++ b/images/hermes-agent/Dockerfile @@ -96,9 +96,22 @@ COPY --from=builder --chown=hermes:hermes /opt/venv /opt/venv # no HermesInstance ever reaches Ready. See #68. COPY --from=builder --chown=hermes:hermes /build/pyproject.toml /build/uv.lock /opt/venv-template/ +# Ship the uv binary in the runtime image too. The operator's `init-uv` init +# container runs `uv sync --frozen` (above) to materialise the env onto the +# per-instance PVC, so uv must be on PATH at runtime — the resolved venv at +# /opt/venv does not include uv. Without this, init-uv exits 127 +# ("uv: not found") and no HermesInstance reaches Ready. See #68. +COPY --from=uv /uv /uvx /usr/local/bin/ + +# UV_* defaults for the init-uv `uv sync` at pod start: pin a deterministic +# interpreter and a PVC-safe link mode so uv never tries to download a Python or +# hardlink across filesystems (image layer -> mounted PVC). ENV PATH="/opt/venv/bin:${PATH}" \ PYTHONUNBUFFERED=1 \ PYTHONDONTWRITEBYTECODE=1 \ + UV_PYTHON_DOWNLOADS=never \ + UV_PYTHON=/usr/local/bin/python \ + UV_LINK_MODE=copy \ HOME=/home/hermes # Image metadata. The HERMES_VERSION label is the one the operator's autoupdate