Repository navigation
refactor(cli): the put commands build through one build_image() - #8
Merged
Merged
Conversation
The six put commands ran nine copies of the same `docker build` (a2a-agent, gateway, mcp-server, service-db x3, website x2, website-browser). They now call agent_env.utils.docker_build.build_image(), which library code can import too: stdlib only, no click, no providers. - build_image(dockerfile, context, tag, *, platform, build_args=None) builds only; each caller still puts the image. platform has no default, so a caller chooses; None or "" builds host-native. - A failed build raises DockerBuildError with docker's whole output (stderr merged into stdout, bytes that don't decode replaced). The CLI renders it as one user-facing error and exits 1, replacing the five per-site prefixes and service-db's "Aborted!". A missing docker binary is the same one line instead of a traceback. - DEFAULT_BUILD_PLATFORM moves to the new module; docker_build_platform_args goes. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…age captures output - The put test stopped each command at its first build, so service-db's db-web and db-mcp builds and website's frontend build were never checked. A test with the builds succeeding now asserts all of them; website's backend and frontend get separate folders so a swapped context shows. - A fake docker on PATH checks that both streams, and a byte that isn't UTF-8, reach DockerBuildError. - Drop two mock names the lift left unused. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
earakely-scale
requested review from
a team and
polakamtejas
as code owners
September 30, 2026 16:43
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The six put commands ran nine copies of the same
docker build. They now call one function,agent_env.utils.docker_build.build_image(), and library code can call it too. The bundle writers that build an env's or an agent's image from its folder come next, and they can't import the CLI.a2a-agent putenv gateway putenv mcp-server putenv service-db putenv website putenv website-browser put--build-argWhat changes
DockerImageArtifact.put, as before. The callers pass that different arguments, and a later change will rework its build-context half.platformhas no default, so a caller must choose one.Noneor""builds for this host. The put commands pass their--platformvalue, whose default is stilllinux/amd64.agent_env.clinor the providers; a test pins that.DEFAULT_BUILD_PLATFORMmoves to the new module.cli.utils.docker_build_platform_argsis gone; nothing outside the CLI imported it.What a user sees when a build fails. The error is now
DockerBuildError, which the CLI renders like its other user-facing errors: one error and exit 1, with the traceback only under--verbose. That replaces five different per-command prefixes, and service-db'sAborted!.The message now carries docker's whole output, not just its stderr, so the legacy builder's
RUNoutput is no longer dropped. Output that isn't UTF-8 is replaced rather than crashing the decode. A missingdockerbinary is the same one line instead of a traceback.The successful path and its progress lines are unchanged.
Not in this PR
agent-env upstill bootstraps its infra envs by shelling out to the put commands. Moving those bodies into library code belongs with the bootstrap work.put_from_github, the env snapshot image,run_docker_container) are shell strings built on the VM, so they're left as they are.build_imageisn't added to it, since its signature may still change.@localor uppercase ids; the bundle writer must tag throughimage_repository();Testing
make unit-test): 5,628 passed, 13 skipped.tst/unit/utils/docker_build_test.py: the argv forlinux/amd64,linux/arm64,""andNonewith a build arg; a failed build's message; a fakedockeron PATH whose stdout, stderr and a non-UTF-8 byte all reach the error; a missingdocker; import purity.tst/unit/cli/build_platform_test.py: each of the six puts callsbuild_imagewith its Dockerfile, context, tag,--platformand build args, and a failed build ends in oneError:line with exit 1. With the builds succeeding, service-db's three builds and website's two are each checked, so all nine are covered. None of the six had a test of its build arguments before.cli.env.<module>.subprocess.runnow patchbuild_image. The one whose build was meant to fail raisesDockerBuildError, so it can't reach the realDockerImageArtifact.put.dockeron PATH,env gateway putandenv service-db puteach print one error line, exit 1, and write no store;mainfails the same gateway build the same way, with the legacy builder building amd64;build_imageof a trivial Dockerfile builds an arm64 image, and a missing context raisesDockerBuildError.🤖 Generated with Claude Code
The PR appears safe to merge; this review found no outstanding finding.
What we checked:
uv.lockmatch their manifests. The publish job reads the protocol version from its manifest before pinning the framework build.Summary
Six local
putcommands now use one shared Docker image builder, which library code can call without importing the CLI. Build failures use one error type that keeps Docker’s full output.Diagram
%%{init: {'theme': 'neutral'}}%% flowchart LR A[Six put commands] --> B[build_image] B --> C[Local Docker build] C --> D[DockerImageArtifact.put] B -- Build fails --> E[DockerBuildError] E --> F[CLI error and exit 1]Reviews (2) · Last reviewed commit: "Merge remote-tracking branch 'origin/mai..."