From cf8b5edf2cf43e50cab4d1110028e91031a04fb9 Mon Sep 17 00:00:00 2001 From: Amit Paz Date: Fri, 26 Jun 2026 19:38:20 +0300 Subject: [PATCH] =?UTF-8?q?fix(compose):=20align=20agentlens=20to=20curren?= =?UTF-8?q?t=20image=20=E2=80=94=20JWT=5FSECRET=20+=20health=20port?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The stack's agentlens was perpetually unhealthy (it was pinned to 0.12.2-era env). Two concrete causes, both fixed: 1. Current AgentLens REQUIRES JWT_SECRET — fatal at boot if unset, even with AUTH_DISABLED=true. The compose only gave JWT_SECRET to agentgate. Added it to agentlens (reuses the stack's shared dev secret). 2. The image's built-in HEALTHCHECK probes port 3400 (its default PORT), but we run it on 3000 — so the healthcheck never passed. Added a compose healthcheck that probes the real port (node fetch localhost:3000/api/stats; the node base image has no curl/wget). Verified locally: `docker compose --profile governance up -d --wait` now brings agentlens + agentgate + lore + lore-db all to (healthy). CI: re-widened the smoke test from lore-only back to the full governance profile (agentlens + agentgate + lore) with health polling on /api/stats, /health, /health. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_019tXZpN29akdmG8AEjgSZwk --- .github/workflows/ci.yml | 26 ++++++++++++-------------- docker-compose.yml | 12 ++++++++++++ 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 457fb6b..9113d80 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,22 +19,20 @@ jobs: - name: Validate compose config run: docker compose config -q - # #96 changed the registry, so prove every minimal image resolves + pulls - # from ghcr.io/agentkitai/* (the migration). agentgate + mesh aren't - # published yet (mesh is archived → needs a one-time GHCR mirror). - - name: Pull minimal images from GHCR (validates the #96 migration) - run: docker compose --profile minimal pull - - # Bring up lore + its DB and verify health from the ghcr image. NOTE: - # agentlens:latest is a newer major than this compose's env was written for - # (it was pinned to 0.12.2) and reports unhealthy — aligning the compose - # to current service majors is tracked separately, not part of #96. - - name: Bring up lore + verify health + # Bring up the full governance profile (agentlens + agentgate + lore + + # lore-db) from the ghcr.io/agentkitai/* images and wait for every + # healthcheck. (agentlens now boots healthy after the JWT_SECRET + + # health-probe-port alignment.) + - name: Bring up the governance stack (wait for healthchecks) + run: docker compose --profile governance up -d --wait --wait-timeout 240 + + - name: Poll documented health endpoints run: | set -e - docker compose up -d --wait --wait-timeout 180 lore - curl -fsS http://localhost:8765/health > /dev/null - echo "lore healthy from ghcr.io/agentkitai/lore." + curl -fsS http://localhost:3000/api/stats > /dev/null # AgentLens + curl -fsS http://localhost:3002/health > /dev/null # AgentGate + curl -fsS http://localhost:8765/health > /dev/null # Lore + echo "governance stack healthy (agentlens + agentgate + lore)." - name: Dump logs on failure if: failure() diff --git a/docker-compose.yml b/docker-compose.yml index c154b3b..c55bb75 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -16,6 +16,9 @@ services: - NODE_ENV=production - AUTH_DISABLED=true - DB_PATH=/app/data/agentlens.db + # JWT_SECRET is REQUIRED by current AgentLens (fatal at boot if unset, + # even with AUTH_DISABLED). Reuses the stack's shared dev secret. + - JWT_SECRET=${JWT_SECRET:?set JWT_SECRET in .env (copy from .env.example)} - AGENTGATE_URL=http://agentgate:3002 - LORE_ENABLED=true - LORE_MODE=remote @@ -26,6 +29,15 @@ services: networks: - agentkit restart: unless-stopped + # The image's built-in HEALTHCHECK probes port 3400 (its default PORT), but + # we run it on 3000 — so override it to probe the real port. (node base image, + # no curl/wget.) + healthcheck: + test: ["CMD-SHELL", "node -e \"fetch('http://localhost:3000/api/stats').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))\""] + interval: 5s + timeout: 3s + retries: 10 + start_period: 10s # Hard-depend only on lore (present in every profile); agentgate is reached # via its runtime URL (best-effort), so the minimal profile doesn't have to # pull it in. It still comes up first in governance.