hyperdx/scripts/dev-env.sh

161 lines
7.8 KiB
Bash
Raw Normal View History

feat: isolate dev environment for multi-agent worktree support (#1994) ## Summary - Isolate dev, E2E, and integration test environments so multiple git worktrees can run all three simultaneously without port conflicts - Each worktree gets a deterministic slot (0-99) with unique port ranges: dev (30100-31199), E2E (20320-21399), CI integration (14320-40098) - Dev portal dashboard (http://localhost:9900) auto-discovers all running stacks, streams logs, and provides a History tab for past run logs ## Port Isolation | Environment | Port Range | Project Name | |---|---|---| | Dev stack | 30100-31199 | `hdx-dev-<slot>` | | E2E tests | 20320-21399 | `e2e-<slot>` | | CI integration | 14320-40098 | `int-<slot>` | All three can run simultaneously from the same worktree with zero port conflicts. ## Dev Portal Features **Live tab:** - Auto-discovers dev, E2E, and integration Docker containers + local services (API, App) - Groups all environments for the same worktree into a single card - SSE log streaming with ANSI color rendering, capped at 5000 lines - Auto-starts in background from `make dev`, `make dev-e2e`, `make dev-int` **History tab:** - Logs archived to `~/.config/hyperdx/dev-slots/<slot>/history/` on exit (instead of deleted) - Each archived run includes `meta.json` with worktree/branch metadata - Grouped by worktree with collapsible cards, search by worktree/branch - View any past log file in the same log panel, delete individual runs or clear all - Custom dark-themed confirm modal (no native browser dialogs) ## What Changed - **`scripts/dev-env.sh`** — Slot-based port assignments, portal auto-start, log archival on exit - **`scripts/test-e2e.sh`** — E2E port range (20320-21399), log capture via `tee`, portal auto-start, log archival - **`scripts/ensure-dev-portal.sh`** — Shared singleton portal launcher (works sourced or executed) - **`scripts/dev-portal/server.js`** — Discovery for dev/E2E/CI containers, history API (list/read/delete), local service port probing - **`scripts/dev-portal/index.html`** — Live/History tabs, worktree-grouped cards, search, collapse/expand, custom confirm modal, ANSI color log rendering - **`docker-compose.dev.yml`** — Parameterized ports/volumes/project name with `hdx.dev.*` labels - **`packages/app/tests/e2e/docker-compose.yml`** — Updated to new E2E port defaults - **`Makefile`** — `dev-int`/`dev-e2e` targets with log capture + portal auto-start; `dev-portal-stop`; `dev-clean` stops everything + wipes slot data - **`.env` files** — Ports use `${VAR:-default}` syntax across dev, E2E, and CI environments - **`agent_docs/development.md`** — Full documentation for isolation, port tables, E2E/CI port ranges ## How to Use ```bash # Start dev stack (auto-starts portal) make dev # Run E2E tests (auto-starts portal, separate ports) make dev-e2e FILE=navigation # Run integration tests (auto-starts portal, separate ports) make dev-int FILE=alerts # All three can run simultaneously from the same worktree # Portal at http://localhost:9900 shows everything # Stop portal make dev-portal-stop # Clean up everything (all stacks + portal + history) make dev-clean ``` ## Dev Portal <img width="1692" height="944" alt="image" src="https://github.com/user-attachments/assets/6ed388a3-43bc-4552-aa8d-688077b79fb7" /> <img width="1689" height="935" alt="image" src="https://github.com/user-attachments/assets/8677a138-0a40-4746-93ed-3b355c8bd45e" /> ## Test Plan - [x] Run `make dev` — verify services start with slot-assigned ports - [x] Run `make dev` in a second worktree — verify different ports, no conflicts - [x] Run `make dev-e2e` and `make dev-int` simultaneously — no port conflicts - [x] Open http://localhost:9900 — verify all stacks grouped by worktree - [x] Click a service to view logs — verify ANSI colors render correctly - [x] Stop a stack — verify logs archived to History tab with correct worktree - [x] History tab — search, collapse/expand, view archived logs, delete - [x] `make dev-clean` — stops everything, wipes slot data and history
2026-03-31 18:24:24 +00:00
#!/usr/bin/env bash
# ---------------------------------------------------------------------------
# Dev environment isolation helper
# ---------------------------------------------------------------------------
# Computes a deterministic port offset (HDX_DEV_SLOT, 0-99) from the current
# working directory name so that multiple git worktrees can run the full dev
# stack in parallel without port conflicts.
#
# Usage:
# source scripts/dev-env.sh # export env vars into current shell
# . scripts/dev-env.sh # same thing, POSIX style
#
# Override the slot manually:
# HDX_DEV_SLOT=5 . scripts/dev-env.sh
#
# Port allocation scheme — each service gets a 100-wide band in the 30100-31199
# range, well clear of:
# - CI integration test ports (14320-14419, 18123-18222, 19000-19099, 39999-40098)
# - E2E test ports (20320-21399)
# - Default dev ports (4317-4320, 8000, 8080, 8123, 8888, 9000, 13133, 14318, 27017)
# - OS ephemeral ports (32768+ Linux, 49152+ macOS)
#
# Port mapping (base + slot):
# API server : 30100 + slot (HYPERDX_API_PORT)
# App (Next.js) : 30200 + slot (HYPERDX_APP_PORT)
# OpAMP : 30300 + slot (HYPERDX_OPAMP_PORT)
# MongoDB : 30400 + slot (HDX_DEV_MONGO_PORT)
# ClickHouse HTTP : 30500 + slot (HDX_DEV_CH_HTTP_PORT)
# ClickHouse Native : 30600 + slot (HDX_DEV_CH_NATIVE_PORT)
# OTel health : 30700 + slot (HDX_DEV_OTEL_HEALTH_PORT)
# OTel gRPC : 30800 + slot (HDX_DEV_OTEL_GRPC_PORT)
# OTel HTTP : 30900 + slot (HDX_DEV_OTEL_HTTP_PORT)
# OTel metrics : 31000 + slot (HDX_DEV_OTEL_METRICS_PORT)
# OTel JSON HTTP : 31100 + slot (HDX_DEV_OTEL_JSON_HTTP_PORT)
# ---------------------------------------------------------------------------
# Compute slot from directory name (same algorithm as CI slot in Makefile)
HDX_DEV_SLOT="${HDX_DEV_SLOT:-$(printf '%s' "$(basename "$PWD")" | cksum | awk '{print $1 % 100}')}"
# Git metadata for portal labels
HDX_DEV_BRANCH="$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo 'unknown')"
HDX_DEV_WORKTREE="$(basename "$PWD")"
# --- Application ports (30100-30399) ---
HYPERDX_API_PORT=$((30100 + HDX_DEV_SLOT))
HYPERDX_APP_PORT=$((30200 + HDX_DEV_SLOT))
HYPERDX_OPAMP_PORT=$((30300 + HDX_DEV_SLOT))
# --- Docker service ports (30400-31199) ---
HDX_DEV_MONGO_PORT=$((30400 + HDX_DEV_SLOT))
HDX_DEV_CH_HTTP_PORT=$((30500 + HDX_DEV_SLOT))
HDX_DEV_CH_NATIVE_PORT=$((30600 + HDX_DEV_SLOT))
HDX_DEV_OTEL_HEALTH_PORT=$((30700 + HDX_DEV_SLOT))
HDX_DEV_OTEL_GRPC_PORT=$((30800 + HDX_DEV_SLOT))
HDX_DEV_OTEL_HTTP_PORT=$((30900 + HDX_DEV_SLOT))
HDX_DEV_OTEL_METRICS_PORT=$((31000 + HDX_DEV_SLOT))
HDX_DEV_OTEL_JSON_HTTP_PORT=$((31100 + HDX_DEV_SLOT))
# --- Docker Compose project name (unique per slot) ---
HDX_DEV_PROJECT="hdx-dev-${HDX_DEV_SLOT}"
Fix dev env port resolution and improve multi-worktree support (#2025) ## Summary - Fix dev environment port isolation so OTel collector, MongoDB, and ClickHouse resolve to the correct worktree-specific ports - Add slot-specific session cookies so multiple worktrees on localhost don't interfere with each other's login sessions - Share NX build cache across worktrees for faster builds - Add worktrunk project config for automated worktree lifecycle management ## Changes ### Port resolution fix **Root `.env`**: Replace self-referential `HDX_DEV_*` vars (e.g. `HDX_DEV_OTEL_HTTP_PORT=${HDX_DEV_OTEL_HTTP_PORT:-4318}`) with plain default values. The `${VAR:-default}` syntax caused `dotenv-expand` infinite recursion, preventing `dev-env.sh` port overrides from taking effect. **`packages/api/.env.development`**: Remove redundant self-referential port declarations and `:-default` fallbacks from `${HDX_DEV_*}` references. Ports now come exclusively from `dev-env.sh` exports or root `.env` defaults. **`packages/app/.env.development`**: Set `HYPERDX_API_KEY` to `super-secure-ingestion-api-key` (matching the API/collector) instead of a placeholder. Remove self-referential port declarations. **`packages/app/src/config.ts`**: Add `process.env.OTEL_EXPORTER_OTLP_ENDPOINT` as fallback for `HDX_COLLECTOR_URL` so the browser OTel SDK picks up the correct collector endpoint. ### Session cookie isolation **`packages/api/src/api-app.ts`**: Use `connect.sid.<slot>` as the session cookie name in dev mode so multiple worktrees on `localhost` maintain independent sessions. Guarded behind `config.IS_DEV && process.env.HDX_DEV_SLOT` — production uses the default `connect.sid`. ### Shared NX build cache **`scripts/dev-env.sh`**: Set `NX_CACHE_DIRECTORY=~/.config/hyperdx/nx-cache` so all worktrees share a single content-hash-based build cache. Unchanged packages get cache hits regardless of worktree; changed packages rebuild correctly. ### Worktrunk project config **`.config/wt.toml`**: New project config for [worktrunk](https://worktrunk.dev) (`wt`) worktree lifecycle hooks: - `pre-start`: Symlink `node_modules/` from primary worktree (instant, no copy) - `post-start`: Copy `.env.local` from primary worktree - `post-remove`: Tear down Docker stacks (`dev-down`, `dev-int-down`, `dev-e2e-down`) for the removed worktree's slot
2026-04-01 20:53:09 +00:00
# --- Shared NX build cache across all worktrees ---
# NX cache is content-hash based so changed files get cache misses (correct
# behavior). Unchanged packages reuse cached output regardless of worktree.
NX_CACHE_DIRECTORY="${HOME}/.config/hyperdx/nx-cache"
mkdir -p "$NX_CACHE_DIRECTORY"
feat: isolate dev environment for multi-agent worktree support (#1994) ## Summary - Isolate dev, E2E, and integration test environments so multiple git worktrees can run all three simultaneously without port conflicts - Each worktree gets a deterministic slot (0-99) with unique port ranges: dev (30100-31199), E2E (20320-21399), CI integration (14320-40098) - Dev portal dashboard (http://localhost:9900) auto-discovers all running stacks, streams logs, and provides a History tab for past run logs ## Port Isolation | Environment | Port Range | Project Name | |---|---|---| | Dev stack | 30100-31199 | `hdx-dev-<slot>` | | E2E tests | 20320-21399 | `e2e-<slot>` | | CI integration | 14320-40098 | `int-<slot>` | All three can run simultaneously from the same worktree with zero port conflicts. ## Dev Portal Features **Live tab:** - Auto-discovers dev, E2E, and integration Docker containers + local services (API, App) - Groups all environments for the same worktree into a single card - SSE log streaming with ANSI color rendering, capped at 5000 lines - Auto-starts in background from `make dev`, `make dev-e2e`, `make dev-int` **History tab:** - Logs archived to `~/.config/hyperdx/dev-slots/<slot>/history/` on exit (instead of deleted) - Each archived run includes `meta.json` with worktree/branch metadata - Grouped by worktree with collapsible cards, search by worktree/branch - View any past log file in the same log panel, delete individual runs or clear all - Custom dark-themed confirm modal (no native browser dialogs) ## What Changed - **`scripts/dev-env.sh`** — Slot-based port assignments, portal auto-start, log archival on exit - **`scripts/test-e2e.sh`** — E2E port range (20320-21399), log capture via `tee`, portal auto-start, log archival - **`scripts/ensure-dev-portal.sh`** — Shared singleton portal launcher (works sourced or executed) - **`scripts/dev-portal/server.js`** — Discovery for dev/E2E/CI containers, history API (list/read/delete), local service port probing - **`scripts/dev-portal/index.html`** — Live/History tabs, worktree-grouped cards, search, collapse/expand, custom confirm modal, ANSI color log rendering - **`docker-compose.dev.yml`** — Parameterized ports/volumes/project name with `hdx.dev.*` labels - **`packages/app/tests/e2e/docker-compose.yml`** — Updated to new E2E port defaults - **`Makefile`** — `dev-int`/`dev-e2e` targets with log capture + portal auto-start; `dev-portal-stop`; `dev-clean` stops everything + wipes slot data - **`.env` files** — Ports use `${VAR:-default}` syntax across dev, E2E, and CI environments - **`agent_docs/development.md`** — Full documentation for isolation, port tables, E2E/CI port ranges ## How to Use ```bash # Start dev stack (auto-starts portal) make dev # Run E2E tests (auto-starts portal, separate ports) make dev-e2e FILE=navigation # Run integration tests (auto-starts portal, separate ports) make dev-int FILE=alerts # All three can run simultaneously from the same worktree # Portal at http://localhost:9900 shows everything # Stop portal make dev-portal-stop # Clean up everything (all stacks + portal + history) make dev-clean ``` ## Dev Portal <img width="1692" height="944" alt="image" src="https://github.com/user-attachments/assets/6ed388a3-43bc-4552-aa8d-688077b79fb7" /> <img width="1689" height="935" alt="image" src="https://github.com/user-attachments/assets/8677a138-0a40-4746-93ed-3b355c8bd45e" /> ## Test Plan - [x] Run `make dev` — verify services start with slot-assigned ports - [x] Run `make dev` in a second worktree — verify different ports, no conflicts - [x] Run `make dev-e2e` and `make dev-int` simultaneously — no port conflicts - [x] Open http://localhost:9900 — verify all stacks grouped by worktree - [x] Click a service to view logs — verify ANSI colors render correctly - [x] Stop a stack — verify logs archived to History tab with correct worktree - [x] History tab — search, collapse/expand, view archived logs, delete - [x] `make dev-clean` — stops everything, wipes slot data and history
2026-03-31 18:24:24 +00:00
# Export everything
export HDX_DEV_SLOT
export HDX_DEV_BRANCH
export HDX_DEV_WORKTREE
export HYPERDX_API_PORT
export HYPERDX_APP_PORT
export HYPERDX_OPAMP_PORT
export HDX_DEV_MONGO_PORT
export HDX_DEV_CH_HTTP_PORT
export HDX_DEV_CH_NATIVE_PORT
export HDX_DEV_OTEL_HEALTH_PORT
export HDX_DEV_OTEL_GRPC_PORT
export HDX_DEV_OTEL_HTTP_PORT
export HDX_DEV_OTEL_METRICS_PORT
export HDX_DEV_OTEL_JSON_HTTP_PORT
export HDX_DEV_PROJECT
Fix dev env port resolution and improve multi-worktree support (#2025) ## Summary - Fix dev environment port isolation so OTel collector, MongoDB, and ClickHouse resolve to the correct worktree-specific ports - Add slot-specific session cookies so multiple worktrees on localhost don't interfere with each other's login sessions - Share NX build cache across worktrees for faster builds - Add worktrunk project config for automated worktree lifecycle management ## Changes ### Port resolution fix **Root `.env`**: Replace self-referential `HDX_DEV_*` vars (e.g. `HDX_DEV_OTEL_HTTP_PORT=${HDX_DEV_OTEL_HTTP_PORT:-4318}`) with plain default values. The `${VAR:-default}` syntax caused `dotenv-expand` infinite recursion, preventing `dev-env.sh` port overrides from taking effect. **`packages/api/.env.development`**: Remove redundant self-referential port declarations and `:-default` fallbacks from `${HDX_DEV_*}` references. Ports now come exclusively from `dev-env.sh` exports or root `.env` defaults. **`packages/app/.env.development`**: Set `HYPERDX_API_KEY` to `super-secure-ingestion-api-key` (matching the API/collector) instead of a placeholder. Remove self-referential port declarations. **`packages/app/src/config.ts`**: Add `process.env.OTEL_EXPORTER_OTLP_ENDPOINT` as fallback for `HDX_COLLECTOR_URL` so the browser OTel SDK picks up the correct collector endpoint. ### Session cookie isolation **`packages/api/src/api-app.ts`**: Use `connect.sid.<slot>` as the session cookie name in dev mode so multiple worktrees on `localhost` maintain independent sessions. Guarded behind `config.IS_DEV && process.env.HDX_DEV_SLOT` — production uses the default `connect.sid`. ### Shared NX build cache **`scripts/dev-env.sh`**: Set `NX_CACHE_DIRECTORY=~/.config/hyperdx/nx-cache` so all worktrees share a single content-hash-based build cache. Unchanged packages get cache hits regardless of worktree; changed packages rebuild correctly. ### Worktrunk project config **`.config/wt.toml`**: New project config for [worktrunk](https://worktrunk.dev) (`wt`) worktree lifecycle hooks: - `pre-start`: Symlink `node_modules/` from primary worktree (instant, no copy) - `post-start`: Copy `.env.local` from primary worktree - `post-remove`: Tear down Docker stacks (`dev-down`, `dev-int-down`, `dev-e2e-down`) for the removed worktree's slot
2026-04-01 20:53:09 +00:00
export NX_CACHE_DIRECTORY
feat: isolate dev environment for multi-agent worktree support (#1994) ## Summary - Isolate dev, E2E, and integration test environments so multiple git worktrees can run all three simultaneously without port conflicts - Each worktree gets a deterministic slot (0-99) with unique port ranges: dev (30100-31199), E2E (20320-21399), CI integration (14320-40098) - Dev portal dashboard (http://localhost:9900) auto-discovers all running stacks, streams logs, and provides a History tab for past run logs ## Port Isolation | Environment | Port Range | Project Name | |---|---|---| | Dev stack | 30100-31199 | `hdx-dev-<slot>` | | E2E tests | 20320-21399 | `e2e-<slot>` | | CI integration | 14320-40098 | `int-<slot>` | All three can run simultaneously from the same worktree with zero port conflicts. ## Dev Portal Features **Live tab:** - Auto-discovers dev, E2E, and integration Docker containers + local services (API, App) - Groups all environments for the same worktree into a single card - SSE log streaming with ANSI color rendering, capped at 5000 lines - Auto-starts in background from `make dev`, `make dev-e2e`, `make dev-int` **History tab:** - Logs archived to `~/.config/hyperdx/dev-slots/<slot>/history/` on exit (instead of deleted) - Each archived run includes `meta.json` with worktree/branch metadata - Grouped by worktree with collapsible cards, search by worktree/branch - View any past log file in the same log panel, delete individual runs or clear all - Custom dark-themed confirm modal (no native browser dialogs) ## What Changed - **`scripts/dev-env.sh`** — Slot-based port assignments, portal auto-start, log archival on exit - **`scripts/test-e2e.sh`** — E2E port range (20320-21399), log capture via `tee`, portal auto-start, log archival - **`scripts/ensure-dev-portal.sh`** — Shared singleton portal launcher (works sourced or executed) - **`scripts/dev-portal/server.js`** — Discovery for dev/E2E/CI containers, history API (list/read/delete), local service port probing - **`scripts/dev-portal/index.html`** — Live/History tabs, worktree-grouped cards, search, collapse/expand, custom confirm modal, ANSI color log rendering - **`docker-compose.dev.yml`** — Parameterized ports/volumes/project name with `hdx.dev.*` labels - **`packages/app/tests/e2e/docker-compose.yml`** — Updated to new E2E port defaults - **`Makefile`** — `dev-int`/`dev-e2e` targets with log capture + portal auto-start; `dev-portal-stop`; `dev-clean` stops everything + wipes slot data - **`.env` files** — Ports use `${VAR:-default}` syntax across dev, E2E, and CI environments - **`agent_docs/development.md`** — Full documentation for isolation, port tables, E2E/CI port ranges ## How to Use ```bash # Start dev stack (auto-starts portal) make dev # Run E2E tests (auto-starts portal, separate ports) make dev-e2e FILE=navigation # Run integration tests (auto-starts portal, separate ports) make dev-int FILE=alerts # All three can run simultaneously from the same worktree # Portal at http://localhost:9900 shows everything # Stop portal make dev-portal-stop # Clean up everything (all stacks + portal + history) make dev-clean ``` ## Dev Portal <img width="1692" height="944" alt="image" src="https://github.com/user-attachments/assets/6ed388a3-43bc-4552-aa8d-688077b79fb7" /> <img width="1689" height="935" alt="image" src="https://github.com/user-attachments/assets/8677a138-0a40-4746-93ed-3b355c8bd45e" /> ## Test Plan - [x] Run `make dev` — verify services start with slot-assigned ports - [x] Run `make dev` in a second worktree — verify different ports, no conflicts - [x] Run `make dev-e2e` and `make dev-int` simultaneously — no port conflicts - [x] Open http://localhost:9900 — verify all stacks grouped by worktree - [x] Click a service to view logs — verify ANSI colors render correctly - [x] Stop a stack — verify logs archived to History tab with correct worktree - [x] History tab — search, collapse/expand, view archived logs, delete - [x] `make dev-clean` — stops everything, wipes slot data and history
2026-03-31 18:24:24 +00:00
# --- Clean up stale Next.js state from previous sessions ---
# Nuke the entire .next directory to avoid stale webpack bundles, lock files,
# and cached module resolutions after common-utils rebuilds.
rm -rf "${PWD}/packages/app/.next" 2>/dev/null || true
# --- Set up directories for portal discovery + logs ---
HDX_DEV_SLOTS_DIR="${HOME}/.config/hyperdx/dev-slots"
HDX_DEV_LOGS_DIR="${HDX_DEV_SLOTS_DIR}/${HDX_DEV_SLOT}/logs"
mkdir -p "$HDX_DEV_LOGS_DIR"
export HDX_DEV_SLOTS_DIR
export HDX_DEV_LOGS_DIR
cat > "${HDX_DEV_SLOTS_DIR}/${HDX_DEV_SLOT}.json" <<EOF
{
"slot": ${HDX_DEV_SLOT},
"branch": "${HDX_DEV_BRANCH}",
"worktree": "${HDX_DEV_WORKTREE}",
"worktreePath": "${PWD}",
"apiPort": ${HYPERDX_API_PORT},
"appPort": ${HYPERDX_APP_PORT},
"opampPort": ${HYPERDX_OPAMP_PORT},
"mongoPort": ${HDX_DEV_MONGO_PORT},
"chHttpPort": ${HDX_DEV_CH_HTTP_PORT},
"chNativePort": ${HDX_DEV_CH_NATIVE_PORT},
"otelHttpPort": ${HDX_DEV_OTEL_HTTP_PORT},
"otelGrpcPort": ${HDX_DEV_OTEL_GRPC_PORT},
"otelJsonHttpPort": ${HDX_DEV_OTEL_JSON_HTTP_PORT},
"logsDir": "${HDX_DEV_LOGS_DIR}",
"pid": $$,
"startedAt": "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
}
EOF
# --- Start dev portal in background if port 9900 is free ---
# shellcheck source=./ensure-dev-portal.sh
source "${BASH_SOURCE[0]%/*}/ensure-dev-portal.sh"
# Clean up slot file and archive logs on exit
_hdx_cleanup_slot() {
if [ -n "$HDX_PORTAL_PID" ] && kill -0 "$HDX_PORTAL_PID" 2>/dev/null; then
kill "$HDX_PORTAL_PID" 2>/dev/null || true
fi
rm -f "${HDX_DEV_SLOTS_DIR}/${HDX_DEV_SLOT}.json" 2>/dev/null || true
# Archive logs to history instead of deleting
if [ -d "$HDX_DEV_LOGS_DIR" ] && [ -n "$(ls -A "$HDX_DEV_LOGS_DIR" 2>/dev/null)" ]; then
_ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
_hist="${HDX_DEV_SLOTS_DIR}/${HDX_DEV_SLOT}/history/dev-${_ts}"
mkdir -p "$_hist"
mv "$HDX_DEV_LOGS_DIR"/* "$_hist/" 2>/dev/null || true
cat > "$_hist/meta.json" <<METAEOF
{"worktree":"${HDX_DEV_WORKTREE}","branch":"${HDX_DEV_BRANCH}","worktreePath":"${PWD}"}
METAEOF
fi
rm -rf "$HDX_DEV_LOGS_DIR" 2>/dev/null || true
}
trap _hdx_cleanup_slot EXIT
# Print summary
echo "╔══════════════════════════════════════════════════════════════╗"
echo "║ HyperDX Dev Environment — Slot ${HDX_DEV_SLOT}$(printf '%*s' $((27 - ${#HDX_DEV_SLOT})) '')"
echo "╠══════════════════════════════════════════════════════════════╣"
echo "║ Branch: ${HDX_DEV_BRANCH}$(printf '%*s' $((45 - ${#HDX_DEV_BRANCH})) '')"
echo "║ Worktree: ${HDX_DEV_WORKTREE}$(printf '%*s' $((45 - ${#HDX_DEV_WORKTREE})) '')"
echo "╠══════════════════════════════════════════════════════════════╣"
echo "║ App (Next.js) http://localhost:${HYPERDX_APP_PORT}$(printf '%*s' $((22 - ${#HYPERDX_APP_PORT})) '')"
echo "║ API http://localhost:${HYPERDX_API_PORT}$(printf '%*s' $((22 - ${#HYPERDX_API_PORT})) '')"
echo "║ ClickHouse http://localhost:${HDX_DEV_CH_HTTP_PORT}$(printf '%*s' $((22 - ${#HDX_DEV_CH_HTTP_PORT})) '')"
echo "║ MongoDB localhost:${HDX_DEV_MONGO_PORT}$(printf '%*s' $((29 - ${#HDX_DEV_MONGO_PORT})) '')"
echo "║ OTel HTTP http://localhost:${HDX_DEV_OTEL_HTTP_PORT}$(printf '%*s' $((22 - ${#HDX_DEV_OTEL_HTTP_PORT})) '')"
echo "║ OTel gRPC localhost:${HDX_DEV_OTEL_GRPC_PORT}$(printf '%*s' $((29 - ${#HDX_DEV_OTEL_GRPC_PORT})) '')"
echo "║ OpAMP localhost:${HYPERDX_OPAMP_PORT}$(printf '%*s' $((29 - ${#HYPERDX_OPAMP_PORT})) '')"
echo "╠══════════════════════════════════════════════════════════════╣"
echo "║ Portal: http://localhost:${HDX_PORTAL_PORT}$(printf '%*s' $((28 - ${#HDX_PORTAL_PORT})) '')"
echo "╚══════════════════════════════════════════════════════════════╝"