feat(mosaico): make docker/mosaico a self-contained deployment bundle#2556
Conversation
docker/Dockerfile ADDs docker/mosaico into the test stage, so a local docker build --target test bakes any local docker/mosaico/.env into an image layer. Exclude .env everywhere in the build context. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Reference pragent/pr-agent:0.40.0-mosaico_agent instead of building pr-agent-solution-agent:local, so the overlay works without a pr-agent checkout. Also corrects three defects that would break registration on the demonstrator: - host port 22000 collided with DOCSTRING_AGENT_PORT; use 23000 - AGENT_NAME must be the kebab-case slug register-agent.py looks up - AGENT_CARD_URL is stored in the repository and fetched by clients outside Docker, so it must be host-reachable, not a service name Healthcheck now matches the peer agents' probe verbatim. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Placeholders only. Covers the standalone docker run vars, the demonstrator overlay knobs, and AGENT_CARD_HOST/PORT - omitting those is what silently leaves the agent advertising an unreachable localhost card URL. Records that 01-compose.sh loads exactly env/langfuse.env and env/llm.env, so nothing outside those two files is picked up. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The template pinned 0.35.0 and had to be bumped every release. Use 1.0.0, matching all four peer registration JSONs in the demonstrator: it describes the registration contract, not the running build. The agent card's own version is derived from the package and needs no maintenance. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Pulls the pinned image, boots it and validates the agent card; also exercises /health and a live review round-trip when LLM creds are present. Fixes the A2A call, which still spoke the pre-1.0 protocol and could not have passed: 1.0 requires the A2A-Version header (a missing header is treated as 0.3 and rejected), renames the method to SendMessage, drops the kind discriminator, and returns the reply as a task artifact. The old assertion read status.message, which is populated only on failure - so it failed on success and would have passed on a failed task. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Written for an integrator who has never cloned pr-agent: no repo paths, no build steps. Documents the upstream relationship, that upgrading is a one-line tag bump, the AGENT_CARD_HOST/PORT pitfall, and why an unhealthy container blocks registration by design. Corrects the documented wire protocol to A2A 1.0 (SendMessage plus the A2A-Version header, reply delivered as a task artifact) and drops the cloud dry-run probe section, since probe.py is not in the published image. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Verbatim copy of the repo-root LICENSE, so the bundle stays correctly licensed when deployed as a standalone repository. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Code Review by Qodo
1.
|
PR Summary by QodoMake docker/mosaico a self-contained deployment bundle (pinned published image)
AI Description
Diagram
High-Level Assessment
Files changed (7)
|
Two user-visible strings still named message/send, which no longer exists on the 1.0 endpoint. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Code Review by Qodo
1. Healthcheck needs PORT set
|
PORT is supplied by base-definitions.yml's agent service, so the probe is correct as composed today. The :-9000 fallback removes the dependency on an external file: with PORT unset the old form expanded to http://localhost:/health, which can never succeed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The smoke test published a configurable host port but never set AGENT_CARD_*, so the card kept advertising localhost:9000 and PORT=19000 ./smoke_test.sh passed against a card nobody could reach. Set AGENT_CARD_HOST/PORT to the published port and assert supportedInterfaces[0].url matches. This is the misconfiguration the README calls the easiest to get wrong, so the bundle's own self-test now covers it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The header claimed 'canonical source', which is right here but false in the GitLab deployment mirror where these files are copied verbatim. Point at the canonical location by name instead, so the same text is correct in both and a re-copy cannot reintroduce a false claim. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Code review by qodo was updated up to the latest commit 67174a5 |
The /health body embeds the raw provider exception when unhealthy, and the fixed /tmp paths were both world-readable and pre-creatable by anyone on a shared host. mktemp -d is 0700 by construction; the existing EXIT trap now clears it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Code review by qodo was updated up to the latest commit 3bdb302 |
… curl The EXIT trap force-removed a fixed container name unconditionally, so a run that died early (failed pull, or a lost `docker run` name race) reaped a container it never created - including one a concurrent run was still using. Gate it on a `started` flag. The header advertises unattended poll-loop use, so give every request a connect timeout and a generous ceiling rather than letting a stalled container hang the loop forever. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Code review by qodo was updated up to the latest commit 4203da6 |
Docker already caps the probe at its 30s default, so it could not hang indefinitely, but an explicit timeout makes the bound self-describing. 25s sits between /health's own 10s LLM timeout and Docker's 30s cap, so a stalled probe reports unhealthy instead of being killed mid-flight. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Code review by qodo was updated up to the latest commit 1b9540c |
Why
The MOSAICO consortium asked how a "forked pr-agent" on GitLab would be maintained. It is not a fork: the MOSAICO A2A agent is merged upstream in
pr_agent/mosaico/, ships in the release wheel, and is published aspragent/pr-agent:<version>-mosaico_agent.This makes
docker/mosaico/a self-contained deployment bundle that consumes that published image, so the GitLab side can hold deployment assets only and no Python. Upgrading becomes a one-line tag bump.What changed
pragent/pr-agent:0.40.0-mosaico_agentinstead of building:local, so it works with no checkout.22000collided withDOCSTRING_AGENT_PORT; now23000AGENT_NAMEwas a display string;register-agent.pylooks up the kebab-case slugAGENT_CARD_URLused a compose service name, but it is stored in the repository and fetched by clients outside Docker, so it must be host-reachableA2A-Versionheader (a missing header is treated as0.3and rejected), renames the method toSendMessage, drops thekinddiscriminator, and returns the reply as a task artifact. The old assertion readstatus.message, which is only populated on failure, so it failed on success and would have passed on a failed task. The README documented the same stale protocol.LICENSE.0.35.0to1.0.0, matching all four peer registration JSONs; it describes the contract, not the running build, so it no longer needs a bump per release..dockerignore:docker/DockerfileADDsdocker/mosaicointo theteststage, so a localdocker build --target testbaked any local.envinto an image layer. That stage is not in the publish matrix, so nothing was ever pushed.The cloud dry-run probe section is dropped from the README:
probe.pyis untracked and confirmed absent from the published image, so those instructions cannot work outside a checkout.Verification
pytest tests/unittest: 1518 passed, 1 skipped, 1 xfaileddocker compose configagainst a copy of the mosaico-demonstrator resolves cleanly; the healthcheck matchesip-solution-agentanddocstring-agentbyte for byte./smoke_test.shagainst the pinned image:FULL ROUND-TRIP PASSED(card validated,/health200, live review returned)No pr-agent source is removed or modified;
pr_agent/mosaico/stays upstream.