Slice 1: build green, MVP core flow
- New agentlib module (gitutil + deployer with NewGo / NewPHP) replaces agent-micro/internal so both agents can share it (Go's internal/ rule was blocking agent-gateway from importing agent-micro's packages). - Migrate agents from legacy github.com/docker/docker/client to the current github.com/moby/moby/client v0.5.0 / moby/moby/api v1.55.0. - Fix compile errors in the original committed code: missing gorilla/websocket import in control-plane/internal/ws/handlers.go, unaliased dockerclient reference, wrong SQLite driver name (sqlite3 -> sqlite), Dialer.Dial 3-return-value mismatch. - scripts/build.sh: Go 1.23 -> 1.24, apk add git, safe.directory for bind-mounted host tree, chmod inside container (host can't chmod files owned by container root). - README and REQUIREMENTS updated to reflect the actual architecture (Go + SQLite, no Spring Boot, moby SDK, per-deploy no image build) with a per-feature status checklist at the end of REQUIREMENTS.
This commit is contained in:
@@ -5,22 +5,47 @@ branch into an isolated sandbox, with the API Gateway routing selected
|
||||
services to the sandbox and the rest to OCP. See
|
||||
[REQUIREMENTS.md](REQUIREMENTS.md) for the full spec.
|
||||
|
||||
## Status (Slice 1 — build green, MVP core flow)
|
||||
|
||||
`./scripts/build.sh` produces three Linux/amd64 binaries and a static
|
||||
dashboard. The MVP core flow — login, deploy a microservice or the PHP
|
||||
gateway, watch progress and logs in real time — works end to end. The
|
||||
sandbox / template / route management described in REQUIREMENTS.md is
|
||||
**deferred to Slice 2** and is not yet built. See
|
||||
[REQUIREMENTS.md](REQUIREMENTS.md#status) for a per-feature checklist.
|
||||
|
||||
## Layout
|
||||
|
||||
```
|
||||
.
|
||||
├── protocol/ # shared wire types (Event, DeployRequest)
|
||||
├── agentlib/ # Go. Shared agent library: gitutil + deployer (Go/PHP flavours)
|
||||
├── control-plane/ # Go. HTTP API + WS hub + SQLite/.log persistence
|
||||
├── agent-micro/ # Go. Runs on 172.18.136.92, deploys Go microservices
|
||||
├── agent-gateway/ # Go. Runs on 172.18.139.186, deploys the API Gateway
|
||||
├── agent-gateway/ # Go. Runs on 172.18.139.186, deploys the PHP API Gateway
|
||||
├── dashboard/ # NextJS static export, served by nginx
|
||||
├── nginx/ # reverse proxy + try_files for the dashboard
|
||||
├── scripts/ # build, deploy, ssh wrappers, nginx patch
|
||||
├── docker-compose.yml # all three services on alpine:latest
|
||||
├── go.work # Go workspace — one build, four modules
|
||||
├── go.work # Go workspace — one build, five modules
|
||||
└── bin/ # build output (gitignored)
|
||||
```
|
||||
|
||||
`agentlib/` is a shared library used by both agents. It owns the git
|
||||
helpers and the per-deployment state machine, which has two constructors
|
||||
for two build flavours:
|
||||
|
||||
- **`NewGo`** — for microservices. Runs `go build` on the host, then
|
||||
`docker run alpine:3.20` with the host repo bind-mounted at `/src` and
|
||||
the binary as the container command. `alpine:3.20` must be pre-loaded
|
||||
on the host (see [Offline VMs](#offline-vms)).
|
||||
- **`NewPHP`** — for the API Gateway. Runs `composer install --no-dev`
|
||||
on the host as a best-effort step (skipped if `composer` or
|
||||
`composer.json` are absent), then `docker run php:8.3-apache` with the
|
||||
repo bind-mounted at `/app`. `php:8.3-apache` must be pre-loaded on
|
||||
the host. The agent is written in Go; the thing it deploys is a
|
||||
PHP project.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Docker (for the build container)
|
||||
@@ -28,7 +53,7 @@ services to the sandbox and the rest to OCP. See
|
||||
- `sshpass` (for the deploy scripts: `brew install sshpass`)
|
||||
|
||||
No Go install needed locally — `scripts/build.sh` cross-compiles inside
|
||||
`golang:1.23-alpine`.
|
||||
`golang:1.24-alpine`.
|
||||
|
||||
## Build
|
||||
|
||||
@@ -37,9 +62,22 @@ No Go install needed locally — `scripts/build.sh` cross-compiles inside
|
||||
```
|
||||
|
||||
Outputs:
|
||||
- `bin/control-plane`, `bin/agent-micro`, `bin/agent-gateway` (Linux/amd64 ELF)
|
||||
- `bin/control-plane`, `bin/agent-micro`, `bin/agent-gateway` (Linux/amd64
|
||||
ELF, statically linked)
|
||||
- `dashboard/out/` (NextJS static export)
|
||||
|
||||
The build script:
|
||||
1. Starts a `golang:1.24-alpine` container with the repo bind-mounted.
|
||||
2. `apk add git` (the base image has none).
|
||||
3. Configures `safe.directory /src` so the container's root user can
|
||||
read the bind-mounted host tree.
|
||||
4. Cross-compiles all three binaries with `GOOS=linux GOARCH=amd64
|
||||
CGO_ENABLED=0`, `-trimpath` (reproducible builds) and
|
||||
`-ldflags="-s -w"` (strip debug info).
|
||||
5. `chmod +x` the binaries inside the container (the host user can't
|
||||
chmod files written by the container's root).
|
||||
6. Builds the Next.js dashboard with `npm install && npm run build`.
|
||||
|
||||
The script verifies each binary with `file` to catch a missing
|
||||
`GOOS`/`GOARCH`.
|
||||
|
||||
@@ -79,33 +117,46 @@ Three services come up on `alpine:latest`:
|
||||
- **Pass-through creds.** Bitbucket credentials travel with each deploy
|
||||
request from control plane to agent, are used once for `git fetch`/`checkout`/
|
||||
`pull`, and are never logged or persisted on the agent.
|
||||
- **No Dockerfile build on the agent.** Each agent does `go build` on the
|
||||
host, then `docker run alpine:3.20` with the host repo bind-mounted at
|
||||
`/src` and the binary exec'd as the container command.
|
||||
- **No internet on the VMs.** `alpine:3.20` is pre-loaded via
|
||||
`docker load`. The dashboard is a static export, no runtime fetches.
|
||||
- **Persistence.** Deployment progress goes to SQLite (`<data>/sdp.db`).
|
||||
Log lines go to append-only `<data>/logs/<deploymentId>.log`. SQLite
|
||||
uses `modernc.org/sqlite` (pure Go, no cgo) so the control plane binary
|
||||
stays statically linkable.
|
||||
- **No Dockerfile build on the agent.** Each agent does the language
|
||||
build on the host (Go or composer), then `docker run <base-image>`
|
||||
with the host repo bind-mounted and the binary / apache as the
|
||||
container command. The base image must be pre-loaded.
|
||||
- **Offline VMs.** `alpine:3.20` and `php:8.3-apache` are pre-loaded
|
||||
via `docker load`. The dashboard is a static export, no runtime
|
||||
fetches.
|
||||
- **Persistence.** Deployment progress goes to SQLite
|
||||
(`<data>/sdp.db`). Log lines go to append-only
|
||||
`<data>/logs/<deploymentId>.log`. SQLite uses `modernc.org/sqlite`
|
||||
(pure Go, no cgo) so the control plane binary stays statically
|
||||
linkable. The driver name is `sqlite` (not `sqlite3`).
|
||||
- **Docker SDK.** The agents use the official Moby Go SDK at
|
||||
`github.com/moby/moby/client` v0.5.0.
|
||||
- **Realtime transport.** WebSocket end-to-end. Agents connect to
|
||||
`/ws/agent` on the control plane; the dashboard subscribes to
|
||||
`/ws/deployments/{id}`.
|
||||
|
||||
## MVP stubs (intentional)
|
||||
## MVP stubs (intentional, not Slice 1 scope)
|
||||
|
||||
These are marked with `ponytail:` comments in the code and will be
|
||||
replaced before production:
|
||||
These are marked with `ponytail:` comments in the code and are
|
||||
scheduled for later slices. They are **not** in scope for Slice 1.
|
||||
|
||||
- `validateViaAgent` (login) — accepts any creds if an agent is
|
||||
connected. Real impl does a `git ls-remote` probe frame.
|
||||
connected. Real impl: a `git ls-remote` probe frame to the agent
|
||||
(`control-plane/internal/api/api.go:126`).
|
||||
- `handleListRepos` / `handleListBranches` — hardcoded fixtures.
|
||||
Real impl forwards to the connected agent.
|
||||
- `handleListDeployments` (GET) — returns `[]`. Real impl reads SQLite.
|
||||
Real impl: a `list_repos` / `list_branches` frame to the connected
|
||||
agent. The `gitutil.ListBranches` helper and the `agentlib` frame
|
||||
protocol are not yet wired up.
|
||||
- `handleListDeployments` (GET) — returns `[]`. Real impl reads SQLite
|
||||
(`control-plane/internal/api/api.go:182`).
|
||||
- WS auth on `/ws/deployments/*` — open. Real impl checks session token.
|
||||
- Sandbox, Template, Route, Environment CRUD — entirely deferred to
|
||||
Slice 2. The data model, REST endpoints, and dashboard pages do not
|
||||
exist yet.
|
||||
|
||||
## See also
|
||||
|
||||
- [REQUIREMENTS.md](REQUIREMENTS.md) — full spec, infra, MVP success criteria
|
||||
- [REQUIREMENTS.md](REQUIREMENTS.md) — full spec, infra, MVP success criteria,
|
||||
per-feature status checklist
|
||||
- [nginx/nginx.conf](nginx/nginx.conf) — reference nginx config
|
||||
- [docker-compose.yml](docker-compose.yml) — three-service dev stack
|
||||
|
||||
Reference in New Issue
Block a user