From 6c1e5fff5291297f6ab1573b144390f36b135cbe Mon Sep 17 00:00:00 2001 From: Dev Agent Date: Fri, 5 Jun 2026 07:34:48 +0300 Subject: [PATCH] feat(staging): add isolated orchestrator-staging service (port 8501, separate DB) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add orchestrator-staging compose service under profile 'staging' so normal 'docker compose up -d' does NOT start it. - Port 8501 via command override; network_mode: host (no ports mapping needed). - DB isolation via separate volume ./data/staging:/app/data — physically separate from prod ./data/orchestrator.db on the host. - ORCH_DB_PATH=/app/data/orchestrator.db explicit in env (same container path, isolated by volume mount). - Add .env.staging.example with all required keys and placeholders. - Update .gitignore: add .env.staging and data/staging/ exclusions. - Add docs/STAGING.md: how to start staging, architecture table, roadmap. Refs: ORCH-31 (Stage 1 of 5) --- .env.staging.example | 52 +++++++++++++++++++++++++++ .gitignore | 4 +++ docker-compose.yml | 36 +++++++++++++++++++ docs/STAGING.md | 85 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 177 insertions(+) create mode 100644 .env.staging.example create mode 100644 docs/STAGING.md diff --git a/.env.staging.example b/.env.staging.example new file mode 100644 index 0000000..f3af589 --- /dev/null +++ b/.env.staging.example @@ -0,0 +1,52 @@ +# STAGING env for orchestrator-staging (port 8501). +# Plane/Gitea tokens and sandbox project — configured in ORCH-32. +# On Stage 1 (ORCH-31) you can copy from prod .env, changing only isolation-related keys. +# +# DO NOT COMMIT the real .env.staging — this file is the template only. +# Create .env.staging on the server and fill in real values before starting staging. + +# ── Plane ───────────────────────────────────────────────────────────────────── +ORCH_PLANE_API_URL=http://localhost:8091 +ORCH_PLANE_API_TOKEN= +ORCH_PLANE_WORKSPACE_SLUG= +ORCH_PLANE_WEBHOOK_SECRET= + +# Per-agent Plane bot tokens (authorship in Plane comments). +# Leave empty to use ORCH_PLANE_API_TOKEN fallback. +ORCH_PLANE_BOT_ANALYST= +ORCH_PLANE_BOT_ARCHITECT= +ORCH_PLANE_BOT_DEVELOPER= +ORCH_PLANE_BOT_REVIEWER= +ORCH_PLANE_BOT_TESTER= +ORCH_PLANE_BOT_DEPLOYER= +ORCH_PLANE_BOT_STREAM= + +# ── Gitea ───────────────────────────────────────────────────────────────────── +ORCH_GITEA_URL=http://localhost:3000 +ORCH_GITEA_PUBLIC_URL=https://git.mva154.duckdns.org +ORCH_GITEA_TOKEN= +ORCH_GITEA_WEBHOOK_SECRET= + +# ── Telegram ────────────────────────────────────────────────────────────────── +ORCH_TELEGRAM_BOT_TOKEN= +ORCH_TELEGRAM_CHAT_ID= + +# ── Claude / repos ──────────────────────────────────────────────────────────── +ORCH_CLAUDE_BIN=/usr/bin/claude +ORCH_REPOS_DIR=/repos +ORCH_HOST_REPOS_DIR=/home/slin/repos + +# ── Database (ISOLATION KEY for staging) ───────────────────────────────────── +# The staging volume mounts ./data/staging:/app/data, so the DB physically lives +# at ./data/staging/orchestrator.db on the host — fully isolated from prod. +# Do NOT change this path; isolation is achieved via the volume mount, not this path. +ORCH_DB_PATH=/app/data/orchestrator.db + +# ── Concurrency / worker ────────────────────────────────────────────────────── +ORCH_MAX_CONCURRENCY=1 +ORCH_QUEUE_POLL_INTERVAL=2.0 + +# ── Deploy hook ─────────────────────────────────────────────────────────────── +DEPLOY_SSH_USER=slin +DEPLOY_SSH_HOST=127.0.0.1 +DEPLOY_HOOK_SCRIPT=/home/slin/bin/enduro-deploy-hook.sh diff --git a/.gitignore b/.gitignore index 83d0390..90996a7 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,7 @@ __pycache__/ data/ *.db .pytest_cache/ +# ORCH-31: staging env (secrets, not committed — see .env.staging.example) +.env.staging +# ORCH-31: staging DB data directory +data/staging/ diff --git a/docker-compose.yml b/docker-compose.yml index 6bdb92e..21ab1c7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -25,3 +25,39 @@ services: - DEPLOY_HOOK_SCRIPT=/home/slin/bin/enduro-deploy-hook.sh group_add: - "999" + + # ORCH-31: staging instance (port 8501, isolated DB). + # Starts ONLY with: docker compose --profile staging up -d orchestrator-staging + # Normal "docker compose up -d" does NOT start this service. + orchestrator-staging: + profiles: + - staging + build: . + container_name: orchestrator-staging + restart: unless-stopped + init: true + network_mode: host + command: ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8501"] + volumes: + - ./data/staging:/app/data + - /home/slin/repos:/repos + - /var/run/docker.sock:/var/run/docker.sock + - /usr/lib/node_modules/@anthropic-ai/claude-code:/opt/claude-code:ro + - /usr/bin/node:/usr/bin/node:ro + - /home/slin/.claude:/home/slin/.claude + - /home/slin/.claude.json:/home/slin/.claude.json:ro + - /home/slin/.orchestrator-ssh:/root/.ssh:ro + env_file: .env.staging + environment: + - ORCH_REPOS_DIR=/repos + - ORCH_HOST_REPOS_DIR=/home/slin/repos + - DEPLOY_SSH_USER=slin + - DEPLOY_SSH_HOST=127.0.0.1 + - DEPLOY_HOOK_SCRIPT=/home/slin/bin/enduro-deploy-hook.sh + # Staging DB is isolated via ./data/staging volume mount. + # Inside the container the path remains /app/data/orchestrator.db (same default), + # but on the host it physically lives at ./data/staging/orchestrator.db — + # completely separate from prod ./data/orchestrator.db. + - ORCH_DB_PATH=/app/data/orchestrator.db + group_add: + - "999" diff --git a/docs/STAGING.md b/docs/STAGING.md new file mode 100644 index 0000000..f750b20 --- /dev/null +++ b/docs/STAGING.md @@ -0,0 +1,85 @@ +# Staging Environment (ORCH-31) + +Orchestrator supports a permanent **staging instance** running on port **8501** with a +fully-isolated SQLite database. The staging instance shares the same codebase and +Dockerfile as production but is started under the `staging` Docker Compose profile so it +**never starts accidentally** during a normal `docker compose up -d`. + +## Architecture + +| | Production | Staging | +|---|---|---| +| Port | 8500 | 8501 | +| Container name | `orchestrator` | `orchestrator-staging` | +| DB (host path) | `./data/orchestrator.db` | `./data/staging/orchestrator.db` | +| DB (container path) | `/app/data/orchestrator.db` | `/app/data/orchestrator.db` | +| env file | `.env` | `.env.staging` | +| Compose profile | *(default)* | `staging` | + +DB isolation is achieved via a separate volume mount (`./data/staging:/app/data`), not by +changing `ORCH_DB_PATH` — the container path stays identical while the host path is a +different directory. + +## Prerequisites + +1. **`.env.staging`** — create from the template (see below). This file is **not committed** + to the repo (it contains secrets). Copy and fill in values before first start. +2. **`./data/staging/`** directory — created automatically on first container start. + +### Create `.env.staging` + +```bash +cd /home/slin/repos/orchestrator +cp .env.staging.example .env.staging +# Edit .env.staging — fill in real tokens / secrets. +# At Stage 1 (ORCH-31) you can reuse prod values; sandbox Plane project +# and isolated Gitea webhook will be wired in ORCH-32. +nano .env.staging +``` + +## Starting Staging + +```bash +cd /home/slin/repos/orchestrator +docker compose --profile staging up -d orchestrator-staging +``` + +Check it is running: + +```bash +docker ps | grep orchestrator-staging +curl -s http://localhost:8501/health | python3 -m json.tool +``` + +## Stopping Staging + +```bash +docker compose --profile staging stop orchestrator-staging +# or remove the container entirely: +docker compose --profile staging down orchestrator-staging +``` + +## Normal `up -d` does NOT start staging + +```bash +# This starts ONLY the prod orchestrator (port 8500). Staging is NOT affected. +docker compose up -d +``` + +The `profiles: [staging]` directive in `docker-compose.yml` ensures staging is +completely invisible to commands that do not pass `--profile staging`. + +## Logs + +```bash +docker logs -f orchestrator-staging +``` + +## Roadmap + +| Task | Description | +|---|---| +| **ORCH-31** *(this PR)* | Infra: compose service, .env template, gitignore, docs | +| **ORCH-32** | Sandbox: isolated Plane project + Gitea repo for staging | +| **ORCH-33** | Test suite running against staging endpoint | +| **ORCH-34** | Deploy hook: promote `orchestrator:candidate` image to staging | -- 2.49.1