mirror of
https://github.com/techforces-ai/Cial.git
synced 2026-05-15 20:14:11 +00:00
Update API docs, recipes, design doc, deploy-pipeline architecture,
and deploy-logs ops doc to match the new synchronous behaviour
(commit 8505981). The endpoint now returns 200/500 with status,
durationMs, exitCode, errorSummary, and an inline logTail (last
~8KB) — no polling, no companion GET endpoint.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
4.4 KiB
4.4 KiB
Deploy pipeline
End-to-end flow when something hits POST /api/v1/self/deploy.
Components
┌────────────────────────┐ JSONL ┌────────────────────────┐
│ core-back │ over UDS │ edge supervisor │
│ ───────────── │ ──────────► │ ───────────── │
│ /api/v1/self/deploy │ │ /run/cial-supervisor │
│ │ │ │ .sock │
│ ▼ │ │ │ │
│ DeployService │ │ ▼ │
│ │ │ │ spawn / SIGTERM │
│ ▼ │ │ child processes │
│ BuildRunner │ └────────────────────────┘
│ (single-flight) │
│ │ │
│ ▼ │
│ spawn pnpm build │
└────────────────────────┘
Lifecycle
- Enqueue —
DeployService.start({ scope })→BuildRunner.enqueue().- One build at a time. New requests either coalesce (same mode + scope) or replace the queued slot.
- Build —
pnpm <filters> buildruns inmonorepoRoot.- Filters depend on scope (
platformvsall) — seerunner.ts. - Stdout/stderr streamed to the WS bridge as
deploy.logevents.
- Filters depend on scope (
- Restart — on build success,
SupervisorClient.restart('platform' | 'all')over the Unix socket.- Supervisor SIGTERMs each named child, respawns it, sends
restart.ack+restart.done. - For
edge(only inall+ unrestricted): supervisor exits, Docker restart-policy recreates the container.
- Supervisor SIGTERMs each named child, respawns it, sends
Files
| File | Role |
|---|---|
core/back/src/modules/deploy/runner.ts |
BuildRunner — pnpm spawn + log streaming |
core/back/src/modules/deploy/service.ts |
Glue — runner ↔ supervisor ↔ WS broadcast |
core/back/src/modules/deploy/supervisor-client.ts |
JSONL-over-UDS client |
core/edge/src/supervisor-ipc.ts |
Wire protocol + scope sets |
core/edge/src/supervisor.ts (prod) |
IPC server + child management |
core/edge/src/supervisor.dev.ts (dev) |
Same, but for pnpm dev:tenant |
core/back/src/modules/self/router.ts |
The agent-facing endpoints |
Build filters
// runner.ts
const PLATFORM_FILTERS = [
'--filter', '@cial/platform-front',
'--filter', '@cial/platform-back',
];
const ALL_FILTERS = [
'--filter', '@cial/protocol',
'--filter', '@cial/sdk',
'--filter', '@cial/core-ui',
'--filter', '@cial/back',
'--filter', '@cial/front',
'--filter', '@cial/edge',
'--filter', '@cial/platform-back',
'--filter', '@cial/platform-front',
];
Restart sets
// supervisor-ipc.ts
const PLATFORM_RESTARTABLES = new Set(['platform-front', 'platform-back']);
const ALL_RESTARTABLES = new Set([
'platform-front', 'platform-back',
'core-front', 'core-back',
'edge', // exits supervisor → docker restart-policy bounces container
]);
WS events
The deploy service broadcasts these to the requesting user's connected tabs:
deploy.start— { deployId, mode, targets[], sessionId }deploy.log— { deployId, stream, line }deploy.restart.start— { service }deploy.restart.done— { service, pid, durationMs }deploy.done— { deployId, ok, exitCode, durationMs, errorSummary }deploy.cancelled— { deployId }
Self-edit calls use requestedByUserId = '__self__', so WS broadcasts go nowhere. Instead, POST /api/v1/self/deploy is synchronous: the route handler subscribes to DeployService events (via service.waitForDone(deployId)), awaits the terminal done/cancelled event, then responds once with the final row + a tail of the log file. The agent gets a single blocking answer — no polling, no WS subscription needed.