Slice 2: port 3452, nginx sandbox mount, AGENTS.md, docs, deploy script cleanup
- control-plane default listen addr is now :3452 (was :8080). An unusual port to avoid collisions on the VM. - agent-micro and agent-gateway default SDP_CP_URL points at ws://localhost:3452/ws/agent. docker-compose.yml updates the control plane command, host port mapping, and agent -cp URLs. - nginx/nginx.conf (the legacy root-mount reference) uses 127.0.0.1:3452 for the upstream. nginx/sandbox.conf is the new deployment config: four location blocks for the /sandbox/credit-card mount — _next/static serves cached chunks, /api/ and /ws/ proxy to 127.0.0.1:3452, /sandbox/credit-card serves the static dashboard with try_files for SPA routing. - scripts/patch-nginx.sh: deleted. The user configures nginx on 186 by hand. scripts/deploy.sh no longer calls it. - AGENTS.md: new file. Documents the build/lint/test commands (with the golang:1.24-alpine container — local Go can't fetch the toolchain), the wire protocol, the Slice-2 conventions (sdp-<repo> container naming, snapshot persistence, PreGitReset/AfterStart hooks), the repo-path gotcha, and the build-artifacts-in-git rationale. - dashboard/out: now tracked in git, alongside bin/. The dashboard static export is scp'd to 186 on deploy; the VMs have no internet so they can't regenerate it. .gitignore comment explains this and warns against re-ignoring. - README.md / REQUIREMENTS.md: status updated to 'Slice 2 done', per-feature checklist marked. Erangel repo path corrected to /var/www/html/erangel-ocean (was wrongly ~/SDP in earlier docs).
This commit is contained in:
@@ -5,27 +5,42 @@ 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)
|
||||
## Status (Slice 2 — sandboxes, routes, real auth, all MVP features)
|
||||
|
||||
`./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.
|
||||
dashboard. The full MVP flow works end to end:
|
||||
|
||||
- Real Bitbucket auth via `git ls-remote` against the api-gateway.
|
||||
- Real repo and branch listing via agent WS frames.
|
||||
- Sandbox / template / environment CRUD with persisted metadata in
|
||||
SQLite.
|
||||
- Route overrides per sandbox, with live read-back of the
|
||||
`<service>_url` map from the gateway's `config.php` after every
|
||||
branch switch. The agent patches the file and gracefully reloads
|
||||
apache.
|
||||
- Per-deploy port binding: the user picks the host port per service
|
||||
(e.g. eredar at `172.18.136.92:9001`), the container's exposed port
|
||||
is published to that port.
|
||||
- Erangel deploy: `git reset --hard → fetch → checkout → pull →
|
||||
composer install → start container → re-apply route overrides`.
|
||||
Per-branch OCP-default snapshot persisted to
|
||||
`<repo>/.sdp/ocp-defaults.json`.
|
||||
|
||||
See [REQUIREMENTS.md](REQUIREMENTS.md#status) for the per-feature
|
||||
checklist.
|
||||
|
||||
## Layout
|
||||
|
||||
```
|
||||
.
|
||||
├── protocol/ # shared wire types (Event, DeployRequest)
|
||||
├── protocol/ # shared wire types (Event, DeployRequest, RouteOverride, ...)
|
||||
├── 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 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
|
||||
├── nginx/ # reference nginx config (manually applied on 186)
|
||||
├── scripts/ # build, deploy, ssh wrappers
|
||||
├── docker-compose.yml # all three services on alpine:latest
|
||||
├── go.work # Go workspace — one build, five modules
|
||||
└── bin/ # build output (gitignored)
|
||||
@@ -39,10 +54,14 @@ for two build flavours:
|
||||
`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
|
||||
- **`NewPHP`** — for the API Gateway (erangel). Runs
|
||||
`git reset --hard → fetch → checkout → pull → composer install
|
||||
(best-effort) → docker run php:8.3-apache`, with the repo
|
||||
bind-mounted at `/var/www/html/erangel-ocean` and
|
||||
`APACHE_DOCUMENT_ROOT=/var/www/html/erangel-ocean` so the gateway is
|
||||
served at `/erangel/`, mirroring production. After the container is
|
||||
up, the agent's `AfterStart` callback re-applies the active route
|
||||
overrides and reloads apache. `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.
|
||||
|
||||
@@ -93,8 +112,10 @@ This script:
|
||||
2. SSHs to **172.18.139.186** (`administrator`) and pushes
|
||||
`bin/control-plane`, `bin/agent-gateway`, and `dashboard/out/` to
|
||||
`~/SDP/`
|
||||
3. Idempotently splices the SDP location block into
|
||||
`/etc/nginx/sites-available/default` on 186 and reloads nginx
|
||||
|
||||
Nginx on 186 is configured by hand; the dashboard ends up at
|
||||
`/home/administrator/SDP/dashboard/`. The required location block is
|
||||
in [nginx/nginx.conf](nginx/nginx.conf).
|
||||
|
||||
Override the creds via `SDP_92_PASS` / `SDP_186_PASS` env vars.
|
||||
|
||||
@@ -108,7 +129,7 @@ docker compose up -d
|
||||
```
|
||||
|
||||
Three services come up on `alpine:latest`:
|
||||
- `control-plane` → `:8080`
|
||||
- `control-plane` → `:3452` (an unusual port to avoid collisions)
|
||||
- `agent-micro` (connects to control plane, has docker socket + repos mounted)
|
||||
- `agent-gateway` (same shape)
|
||||
|
||||
@@ -135,24 +156,32 @@ Three services come up on `alpine:latest`:
|
||||
`/ws/agent` on the control plane; the dashboard subscribes to
|
||||
`/ws/deployments/{id}`.
|
||||
|
||||
## MVP stubs (intentional, not Slice 1 scope)
|
||||
## MVP stubs (intentional, deferred)
|
||||
|
||||
These are marked with `ponytail:` comments in the code and are
|
||||
scheduled for later slices. They are **not** in scope for Slice 1.
|
||||
scheduled for later slices.
|
||||
|
||||
- `validateViaAgent` (login) — accepts any creds if an agent is
|
||||
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: 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.
|
||||
- `CheckOrigin` in the WS upgrader — open CORS, intentional for an
|
||||
internal tool.
|
||||
- "Drop on backpressure" policy for slow WS subscribers — replace with
|
||||
flow control or persistent event log if the dashboard ever needs
|
||||
catch-up replay.
|
||||
- O(n) log tail scan in `store.TailLogs` — fine for tail use; swap to
|
||||
a ring buffer if logs get huge.
|
||||
|
||||
## Slice 2 dashboard
|
||||
|
||||
The dashboard has these pages:
|
||||
|
||||
- `/` — login (real git-ls-remote via the gateway agent).
|
||||
- `/dashboard` — quick deploy (ad-hoc single-service deploy).
|
||||
- `/dashboard/sandboxes` — list, create, clone-from-template.
|
||||
- `/dashboard/sandboxes/{id}` — sandbox detail. Live routes from the
|
||||
gateway's `config.php`, per-route toggle (OCP / sandbox override),
|
||||
microservice deploys with per-service host port and env.
|
||||
- `/dashboard/templates` — template CRUD.
|
||||
- `/dashboard/environments` — env CRUD.
|
||||
- `/dashboard/history` — deployment history (filterable by sandbox).
|
||||
|
||||
## See also
|
||||
|
||||
|
||||
Reference in New Issue
Block a user