Add mcp build command and deploy auto-build
Extends MCP to own the full build-push-deploy lifecycle. When deploying, the CLI checks whether each component's image tag exists in the registry and builds/pushes automatically if missing and build config is present. - Add Build, Push, ImageExists to runtime.Runtime interface (podman impl) - Add mcp build <service>[/<image>] command - Add [build] section to CLI config (workspace path) - Add path and [build.images] to service definitions - Wire auto-build into mcp deploy before agent RPC - Update ARCHITECTURE.md with runtime interface and deploy auto-build docs Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,7 @@ package runtime
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strings"
|
||||
@@ -177,6 +178,40 @@ func (p *Podman) Inspect(ctx context.Context, name string) (ContainerInfo, error
|
||||
return info, nil
|
||||
}
|
||||
|
||||
// Build builds a container image from a Dockerfile.
|
||||
func (p *Podman) Build(ctx context.Context, image, contextDir, dockerfile string) error {
|
||||
args := []string{"build", "-t", image, "-f", dockerfile, contextDir}
|
||||
cmd := exec.CommandContext(ctx, p.command(), args...) //nolint:gosec // args built programmatically
|
||||
cmd.Dir = contextDir
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("podman build %q: %w: %s", image, err, out)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Push pushes a container image to a remote registry.
|
||||
func (p *Podman) Push(ctx context.Context, image string) error {
|
||||
cmd := exec.CommandContext(ctx, p.command(), "push", image) //nolint:gosec // args built programmatically
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("podman push %q: %w: %s", image, err, out)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ImageExists checks whether an image tag exists in a remote registry.
|
||||
func (p *Podman) ImageExists(ctx context.Context, image string) (bool, error) {
|
||||
cmd := exec.CommandContext(ctx, p.command(), "manifest", "inspect", "docker://"+image) //nolint:gosec // args built programmatically
|
||||
if err := cmd.Run(); err != nil {
|
||||
// Exit code 1 means the manifest was not found.
|
||||
var exitErr *exec.ExitError
|
||||
if ok := errors.As(err, &exitErr); ok && exitErr.ExitCode() == 1 {
|
||||
return false, nil
|
||||
}
|
||||
return false, fmt.Errorf("podman manifest inspect %q: %w", image, err)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// podmanPSEntry is a single entry from podman ps --format json.
|
||||
type podmanPSEntry struct {
|
||||
Names []string `json:"Names"`
|
||||
|
||||
Reference in New Issue
Block a user