From f5943047211deff87d8958b3b2c2717d28cbf15f Mon Sep 17 00:00:00 2001 From: ADMIN Date: Sat, 24 Oct 2026 00:11:13 +0000 Subject: [PATCH] fix(ci): point KOMODO_HOST to public/internal url and add wait_for_update --- .gitea/workflows/deploy.yml | 34 ++++++++++++++--------- scripts/deploy.py | 54 +++++++++++++++++++++++++++++++++---- 2 files changed, 70 insertions(+), 18 deletions(-) diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index f1fddfb..7649b59 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -12,7 +12,7 @@ jobs: name: Deploy to Komodo runs-on: hp env: - KOMODO_HOST: ${{ secrets.KOMODO_HOST || 'http://localhost:9120' }} + KOMODO_HOST: ${{ secrets.KOMODO_HOST || 'https://komodo.nickmalik.dev' }} KOMODO_API_KEY: ${{ secrets.KOMODO_API_KEY }} KOMODO_API_SECRET: ${{ secrets.KOMODO_API_SECRET }} steps: @@ -32,16 +32,24 @@ jobs: echo "=== Deploying OpenHands Agent Canvas ===" python3 scripts/deploy.py - - name: Verify Health + - name: Check Stack Status run: | - echo "=== Checking health endpoint on port 18000 ===" - sleep 10 - for i in 1 2 3 4 5 6; do - if curl -fsSL -o /dev/null "http://127.0.0.1:18000/" 2>/dev/null || curl -fsSL -o /dev/null "http://127.0.0.1:18000/canvas" 2>/dev/null; then - echo "OpenHands Agent Canvas is reachable on http://127.0.0.1:18000/ !" - exit 0 - fi - echo "Waiting for container startup (attempt $i/6)..." - sleep 5 - done - echo "Container is deploying in background. Check status in Komodo Web UI." + echo "=== Stack deployment completed. Verifying stack info via Komodo API ===" + python3 -c " + import urllib.request, json, os + host = os.getenv('KOMODO_HOST', 'https://komodo.nickmalik.dev').rstrip('/') + key = os.getenv('KOMODO_API_KEY') + secret = os.getenv('KOMODO_API_SECRET') + if key and secret: + req = urllib.request.Request( + f'{host}/read/GetStack', + data=json.dumps({'stack': 'openhands-agent-canvas'}).encode(), + headers={'Content-Type': 'application/json', 'x-api-key': key, 'x-api-secret': secret}, + method='POST' + ) + try: + res = json.loads(urllib.request.urlopen(req, timeout=30).read().decode()) + print('Stack Status:', res.get('state', 'N/A')) + except Exception as e: + print('Note:', e) + " diff --git a/scripts/deploy.py b/scripts/deploy.py index 87f4fe2..8fbb608 100755 --- a/scripts/deploy.py +++ b/scripts/deploy.py @@ -2,7 +2,8 @@ """ Deploy script for OpenHands Agent Canvas on Komodo Core. Reads docker-compose.yml, ensures the Komodo Stack exists on server-tsj08, -updates the Compose configuration, and triggers deployment via Komodo API. +updates the Compose configuration, triggers deployment via Komodo API, +and waits for deployment completion. """ import os @@ -14,6 +15,7 @@ import urllib.error STACK_NAME = "openhands-agent-canvas" DEFAULT_SERVER = "server-tsj08" +DEFAULT_KOMODO_HOST = "https://komodo.nickmalik.dev" def get_komodo_config(): @@ -28,13 +30,16 @@ def get_komodo_config(): import tomllib with open(cfg_path, "rb") as f: cfg = tomllib.load(f) - host = host or cfg.get("host", "http://localhost:9120") + host = host or cfg.get("host", DEFAULT_KOMODO_HOST) key = key or cfg.get("cli_key", "") secret = secret or cfg.get("cli_secret", "") except Exception as e: print(f"[WARN] Failed to parse {cfg_path}: {e}") - host = host or "http://localhost:9120" + # Fallback to public/internal Komodo domain if localhost is passed inside a runner container + if not host or "localhost" in host or "127.0.0.1" in host: + host = DEFAULT_KOMODO_HOST + if not (key and secret): print("::error::KOMODO_API_KEY and KOMODO_API_SECRET must be set.") sys.exit(1) @@ -63,6 +68,39 @@ def api_call(host, key, secret, endpoint, payload): raise RuntimeError(f"Komodo API {endpoint} error {e.code}: {err}") from e +def wait_for_update(host, key, secret, update_id, max_wait_sec=300): + print(f"[INFO] Monitoring deployment update {update_id}...") + start_time = time.time() + last_status = None + + while time.time() - start_time < max_wait_sec: + time.sleep(5) + try: + updates_data = api_call(host, key, secret, "/read/ListUpdates", {}) + for u in updates_data.get("updates", []): + uid = (u.get("_id") or {}).get("$oid") or u.get("id") + if uid == update_id: + status = u.get("status") + if status != last_status: + print(f" -> Deployment status: {status}") + last_status = status + if status in ("Complete", "Failed", "Cancelled"): + success = u.get("success", False) + for log in (u.get("logs") or [])[-10:]: + print(f" [log] {log}") + if success: + print(f"[SUCCESS] Deployment completed successfully!") + return True + else: + print(f"::error::Deployment finished with status {status}") + return False + except Exception as e: + print(f"[WARN] Error polling update status: {e}") + + print(f"[WARN] Deployment is taking longer than {max_wait_sec}s (likely pulling large image). Continuing.") + return True + + def main(): host, key, secret = get_komodo_config() print(f"=== Komodo Target: {host} ===") @@ -81,7 +119,7 @@ def main(): elif server_id: print(f"[INFO] Target server '{DEFAULT_SERVER}' resolved to id: {server_id}") else: - print(f"::error::No active servers found in Komodo.") + print("::error::No active servers found in Komodo.") sys.exit(1) # 2. Read docker-compose.yml @@ -130,7 +168,13 @@ def main(): host, key, secret, "/execute/DeployStack", {"stack": STACK_NAME, "services": [], "stop_time": None} ) - print(f"[SUCCESS] Deploy execution dispatched: {deploy_res}") + update_id = (deploy_res.get("_id") or {}).get("$oid") or deploy_res.get("id") + if update_id: + ok = wait_for_update(host, key, secret, update_id, max_wait_sec=300) + if not ok: + sys.exit(1) + else: + print(f"[SUCCESS] Deploy execution dispatched: {deploy_res}") if __name__ == "__main__":