diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 9529c2d..362b799 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -192,6 +192,9 @@ for a service by prefix and derive component names automatically ``` mcp login Authenticate to MCIAS, store token +mcp build Build and push images for a service +mcp build / Build and push a single image + mcp deploy Deploy all components from service definition mcp deploy / Deploy a single component mcp deploy -f Deploy from explicit file @@ -203,8 +206,8 @@ mcp list List services from all agents (registry, mcp ps Live check: query runtime on all agents, show running containers with uptime and version mcp status [service] Full picture: live query + drift + recent events -mcp sync Push service definitions to agent (update desired - state without deploying) +mcp sync Push service definitions to agent; build missing + images if source tree is available mcp adopt Adopt all -* containers into a service mcp purge [service[/component]] Remove stale registry entries (--dry-run to preview) @@ -235,11 +238,19 @@ Example: `~/.config/mcp/services/metacrypt.toml` name = "metacrypt" node = "rift" active = true +path = "metacrypt" + +[build] +uses_mcdsl = false + +[build.images] +metacrypt = "Dockerfile.api" +metacrypt-web = "Dockerfile.web" [[components]] name = "api" -image = "mcr.svc.mcp.metacircular.net:8443/metacrypt:latest" -network = "docker_default" +image = "mcr.svc.mcp.metacircular.net:8443/metacrypt:v1.0.0" +network = "mcpnet" user = "0:0" restart = "unless-stopped" ports = ["127.0.0.1:18443:8443", "127.0.0.1:19443:9443"] @@ -247,8 +258,8 @@ volumes = ["/srv/metacrypt:/srv/metacrypt"] [[components]] name = "web" -image = "mcr.svc.mcp.metacircular.net:8443/metacrypt-web:latest" -network = "docker_default" +image = "mcr.svc.mcp.metacircular.net:8443/metacrypt-web:v1.0.0" +network = "mcpnet" user = "0:0" restart = "unless-stopped" ports = ["127.0.0.1:18080:8080"] @@ -334,6 +345,83 @@ Service definition files can be: - **Generated by converting from mcdeploy.toml** during initial MCP migration (one-time). +### Build Configuration + +Service definitions include a `[build]` section that tells MCP how to +build container images from source. This replaces the standalone +`mcdeploy.toml` -- MCP owns the full build-push-deploy lifecycle. + +Top-level build fields: + +| Field | Purpose | +|-------|---------| +| `path` | Source directory relative to the workspace root | +| `build.uses_mcdsl` | Whether the mcdsl module is needed at build time | +| `build.images.` | Maps each image name to its Dockerfile path | + +The workspace root is configured in `~/.config/mcp/mcp.toml`: + +```toml +[build] +workspace = "~/src/metacircular" +``` + +A service with `path = "mcr"` resolves to `~/src/metacircular/mcr`. The +convention assumes `~/src/metacircular/` on operator workstations +(vade, orion). The workspace path can be overridden but the convention +should hold for all standard machines. + +### Build and Release Workflow + +The standard release workflow for a service: + +1. **Tag** the release in git (`git tag -a v1.1.0`). +2. **Build** the images: `mcp build ` reads the service + definition, locates the source tree via `path`, and runs `docker + build` using each Dockerfile in `[build.images]`. Images are tagged + with the version from the component `image` field and pushed to MCR. +3. **Update** the service definition: bump the version tag in each + component's `image` field. +4. **Deploy**: `mcp sync` or `mcp deploy `. + +#### `mcp build` Resolution + +`mcp build ` does the following: + +1. Read the service definition to find `[build.images]` and `path`. +2. Resolve the source tree: `/`. +3. For each image in `[build.images]`: + a. Build with the Dockerfile at `/`. + b. If `uses_mcdsl = true`, include the mcdsl directory in the build + context (or use a multi-module build strategy). + c. Tag as `/:` (version extracted from the + matching component's `image` field). + d. Push to MCR. + +#### `mcp sync` Auto-Build + +`mcp sync` pushes service definitions to agents. Before deploying, it +checks that each component's image tag exists in the registry: + +- **Tag exists** → proceed with deploy. +- **Tag missing, source tree available** → build and push automatically, + then deploy. +- **Tag missing, no source tree** → fail with error: + `"mcr:v1.1.0 not found in registry and no source tree at ~/src/metacircular/mcr"`. + +This ensures `mcp sync` is a single command for the common case (tag, +update version, sync) while failing clearly when the build environment +is not available. + +#### Image Versioning + +Service definitions MUST pin explicit version tags (e.g., `v1.1.0`), +never `:latest`. This ensures: + +- `mcp status` shows the actual running version. +- Deployments are reproducible. +- Rollbacks are explicit (change the tag back to the previous version). + --- ## Agent