Skip to content

fix: copy pyproject.toml + uv.lock to /opt/venv-template/ in agent image - #84

Closed
aabichou wants to merge 13 commits into
paperclipinc:mainfrom
aabichou:main
Closed

fix: copy pyproject.toml + uv.lock to /opt/venv-template/ in agent image#84
aabichou wants to merge 13 commits into
paperclipinc:mainfrom
aabichou:main

Conversation

@aabichou

Copy link
Copy Markdown

The operator's init-uv init container copies from /opt/venv-template/ but the Dockerfile never copies pyproject.toml and uv.lock into the runtime stage. This causes every HermesInstance to fail with:

cp: cannot stat '/opt/venv-template/pyproject.toml': No such file or directory
cp: cannot stat '/opt/venv-template/uv.lock': No such file or directory

Root cause: The two-stage Dockerfile copies the resolved venv from the builder stage but omits the project files that the operator's init container expects at /opt/venv-template/.

Fix: Add COPY --from=builder --chown=hermes:hermes /build/pyproject.toml /build/uv.lock /opt/venv-template/ to the runtime stage.

Fixes #68

The operator's init-uv init container copies these files from
/opt/venv-template/ to run 'uv sync --frozen'. The Dockerfile's
runtime stage was missing the COPY for these files.

Also update CI to push to the fork's ghcr.io.

Fixes: paperclipinc#68
@aabichou
aabichou requested a review from stubbi as a code owner June 17, 2026 18:40
aabichou and others added 12 commits June 17, 2026 19:43
The previous entrypoint exec'd `hermes-agent run` — which is the
standalone agent demo runner, not a long-running service. The
StatefulSet exposes port 8443 as `gateway`; the correct command is
`hermes gateway` (foreground messaging gateway).

Also set HERMES_HOME so the CLI discovers the operator-mounted
~/.hermes/config.yaml.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…teway

The StatefulSet readiness probe targets the gateway port (8443) and the
operator's IngressRoute fronts the same port for the UI. `hermes gateway`
serves only the messaging API, so users hitting the URL get nothing
useful and `--no-open --insecure` is required to bind on a headless
trusted-LAN deployment. `hermes dashboard` serves both the web UI and
the gateway endpoints on one port, satisfying the readiness probe.
`hermes dashboard` imports fastapi+uvicorn lazily; without the [web]
extra installed, the dashboard subcommand fails with "Web UI
dependencies not installed". This pulls fastapi==0.133.1 and
uvicorn[standard]==0.41.0 into the locked environment.

Also drops the unrecognized `[tool.uv] frozen = true` setting that uv
0.11.7 rejected with a TOML parse warning at runtime — `--frozen` is
already passed on the `uv sync` command line in the Dockerfile, so the
behavior is unchanged.
Upstream's [tool.setuptools.packages.find] omits hermes_cli.* so
non-editable installs (uv pip install from git) drop the
hermes_cli.dashboard_auth subpackage and 'hermes dashboard' fails to
import. The fork at aabichou/hermes-agent-src adds hermes_cli.* (plus
acp_adapter.* for safety) to the include list; otherwise identical to
upstream v2026.5.29.2.
uv installs hermes-agent from a git ref, which fetches the source tree
but never runs the JS toolchain. Upstream's wheel ships
hermes_cli/web_dist/** via package-data, but the directory is only
populated after \`cd web && npm run build\` against the source. With
web_dist empty in site-packages, every dashboard route responded
\`{"error":"Frontend not built"}\` even though the FastAPI server
itself was healthy.

Add a node:22 stage that clones the same fork ref pinned in
pyproject.toml and runs the production vite build, then COPY the
resulting web_dist/ into the venv's hermes_cli/ in the runtime stage.
Assets stay commit-aligned with the Python package because both come
from HERMES_AGENT_FORK_REF.
ARGs declared before FROM are only visible in FROM lines; re-declaring
without a default inside the stage leaves them empty, so the git clone
ran with an empty repo URL. Put the defaults on the in-stage ARGs.
@stubbi

stubbi commented Jun 18, 2026

Copy link
Copy Markdown
Collaborator

Thanks for digging into this, @aabichou — your root-cause diagnosis is exactly right: init-uv copies from /opt/venv-template/, and the agent Dockerfile never ships pyproject.toml/uv.lock there. 🙏

I'm going to close this PR in favor of a minimal fix (#85) rather than merge it as-is, because beyond the one-line COPY fix this PR also makes a number of changes we can't take on the release image:

  • Redirects the published image to a personal namespaceghcr.io/aabichou/hermes-agent instead of ghcr.io/paperclipinc/hermes-agent. This would break every existing HermesInstance and the autoupdate controller, which pull from the paperclipinc org.
  • Drops supply-chain guarantees — removes cosign keyless signing, the SBOM (Syft) generation + attestation, and build provenance. These are required for the OpenShift/Artifact Hub certification path.
  • Drops linux/arm64 from the build matrix (arm64 users would lose images).
  • Removes the agent/v* tag-push trigger and the uv.lock git-rev pin verification, so releases would no longer be reproducible/gated.

#85 is the surgical version of your fix — just the COPY --from=builder /build/pyproject.toml /build/uv.lock /opt/venv-template/ line — leaving the signing/SBOM/multi-arch pipeline intact. You're credited in the issue thread; if you'd like, the separate workflow modernizations (ubuntu-24.04 runner, build-push-action@v6, etc.) would be very welcome as their own focused PR.

Closing in favor of #85. Thanks again for the report and the fix!

@stubbi stubbi closed this Jun 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

operator: init-uv copies from /opt/venv-template (absent in published hermes-agent image) so no HermesInstance reaches Ready

2 participants