feat(api): add stateless deploy endpoint (POST /api/deploy)#11
Conversation
New POST /api/deploy endpoint that accepts kubeconfig, GitHub token, repo URL, and branch, then drives the full deployment pipeline without any database persistence: - Authenticates via kubeconfig → AIProxy token (no OAuth/cookie required) - Creates an in-memory fake Task to reuse ensureTaskDevboxRuntime - Provisions Devbox runtime, clones repo, installs brain-sandbox-skills - Starts Codex Gateway session and sends brain-github-deploy prompt - Polls for AI turn completion, streams progress via SSE - Extracts deployment-output.json and crossplane/ap.yaml from Devbox - Returns image ref + Crossplane AP YAML in the final SSE event - Cleans up Gateway session and Devbox in the finally block New files: - app/api/deploy/route.ts - lib/deploy-api/auth.ts - lib/deploy-api/orchestrator.ts - lib/deploy-api/prompt.ts - lib/deploy-api/result-parser.ts - lib/deploy-api/types.ts 🤖 Generated with [Qoder][https://qoder.com]
Documents the stateless deploy API endpoint including: - API contract (request/response/SSE events) - Authentication design (kubeconfig → AIProxy) - Zero-persistence strategy (in-memory fake Task) - Full execution flow diagram - brain-github-deploy skill phase overview - Module structure and dependency graph - Crossplane AP YAML format reference - Timeout and resource management table - Design decision rationale 🤖 Generated with [Qoder][https://qoder.com]
P1 - Skill marker now checks brain-github-deploy (was sealos-deploy):
- lib/devbox/runtime.ts: change agent/codex skill markers from
sealos-deploy/SKILL.md to brain-github-deploy/SKILL.md so that
repos with an older sealos-deploy install correctly trigger
reinstallation of brain-sandbox-skills
- Added post-install verification: bootstrap exits non-zero if
brain-github-deploy/SKILL.md is still absent after running
the install command
P1 - Devbox cleanup is now awaited:
- lib/deploy-api/orchestrator.ts: await deleteDevbox() with a
static error log on failure; cleanup always completes before
the SSE stream closes
P1 - Client disconnect now aborts the deployment:
- app/api/deploy/route.ts: AbortController triggered by both
ReadableStream.cancel() and req.signal (request disconnect)
- lib/deploy-api/orchestrator.ts: accepts AbortSignal, checks
abort before each poll, calls interruptCodexGatewayTurn() then
throws DeployError('aborted') for prompt cleanup
P2 - repoUrl validated as GitHub HTTPS URL:
- app/api/deploy/route.ts: GITHUB_REPO_URL_PATTERN regex rejects
any URL that is not https://github.com/{owner}/{repo}[.git]
P2 - Error events now include stable code and phase:
- lib/deploy-api/types.ts: add DeployErrorCode type and DeployError
class; update DeployErrorEvent to include code + phase fields
- lib/deploy-api/result-parser.ts: throw DeployError with
appropriate code (build_failed, result_missing) instead of
plain Error
- lib/deploy-api/orchestrator.ts: track currentPhase, propagate
code/phase to error SSE event; map unknown errors to
internal_error code
🤖 Generated with [Qoder][https://qoder.com]
|
|
||
| if ( | ||
| combined.includes('buildkit') || | ||
| combined.includes('ghcr.io') || |
🤖 Generated with [Qoder][https://qoder.com]
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 82c4b3e387
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const abortController = new AbortController() | ||
|
|
||
| // Propagate request-level disconnect signal | ||
| req.signal.addEventListener('abort', () => abortController.abort(), { once: true }) |
There was a problem hiding this comment.
Handle already-aborted requests before starting work
If the client disconnects while validateKubeconfig() is still awaiting the AIProxy network call, req.signal is already aborted by the time this listener is added, and abort listeners are not invoked retroactively. In that case the handler still creates the SSE stream and starts runDeployOrchestration(), which can provision a Devbox and run the deployment even though there is no client left to receive it; check req.signal.aborted immediately after auth (or wire the signal into auth) before launching orchestration.
Useful? React with 👍 / 👎.
|
|
||
| sendEvent('complete', result) | ||
| } catch (error) { | ||
| console.error('Deploy orchestration error:', error) |
There was a problem hiding this comment.
Avoid logging dynamic deployment errors
AGENTS.md forbids dynamic values in console.* logs outside the approved task-flow logging utility, and this catch logs the full runtime error for an endpoint that handles user-supplied kubeconfigs, GitHub tokens, repo URLs, and gateway/devbox diagnostics. When a Devbox/Gateway failure includes request details or tool output, this bypasses the static-log/redaction policy; keep the log message static or explicitly sanitize before logging.
Useful? React with 👍 / 👎.
Summary
POST /api/deploySSE endpoint that accepts kubeconfig + GitHub token + repo URL, drives the full deployment pipeline (Devbox → Codex Gateway → brain-github-deploy skill → BuildKit → GHCR push), and returns Crossplane AP YAML — all without any database persistenceChanges
New files (6):
app/api/deploy/route.ts— SSE endpoint with input validation, GitHub URL restriction, AbortControllerlib/deploy-api/types.ts— DeployPhase, DeployErrorCode, DeployError classlib/deploy-api/auth.ts— kubeconfig → AIProxy → GatewayConfiglib/deploy-api/orchestrator.ts— Core orchestration with abort support and phase trackinglib/deploy-api/prompt.ts— Deploy prompt with Sealos context injectionlib/deploy-api/result-parser.ts— Reads deployment-output.json + ap.yaml from DevboxModified files (1):
lib/devbox/runtime.ts— Skill marker changed fromsealos-deploytobrain-github-deploy; added post-install verificationDocumentation (1):
DEPLOY_API.md— Full technical documentation (API contract, auth flow, architecture, error codes)Test plan
pnpm type-checkpasses (verified)pnpm lintpasses with 0 errors (verified)pnpm format:checkpasses (verified)Manual test: invalid kubeconfig → 401 JSON response, no Devbox created
Manual test: non-GitHub repoUrl → 400 JSON response
Manual test: valid inputs → SSE stream with progress events → complete event with YAML
Manual test: client disconnect during execution → Devbox cleaned up
🤖 Generated with [Qoder][https://qoder.com]