hyperdx/agent_docs/development.md

250 lines
8.8 KiB
Markdown
Raw Normal View History

# Development Workflows
## Setup Commands
```bash
# Install dependencies and setup hooks
yarn setup
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
# Start full development stack (auto-assigns unique ports per worktree)
yarn dev # or equivalently: make dev
```
## Key Development Scripts
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
- `yarn dev` / `make dev`: Start full dev stack with worktree-isolated ports. A
dev portal at http://localhost:9900 auto-starts showing all running stacks.
- `yarn dev:down` / `make dev-down`: Stop the dev stack for the current worktree
- `make dev-portal`: Start the dev portal manually (auto-started by `yarn dev`)
- `yarn lint`: Run linting across all packages
- `yarn dev:unit`: Run unit tests in watch mode (per package)
## Environment Configuration
- `.env.development`: Development environment variables
- Docker Compose manages ClickHouse, MongoDB, OTel Collector
- Hot reload enabled for all services in development
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
## Worktree Isolation (Multi-Agent / Multi-Developer)
When multiple git worktrees need to run the dev stack simultaneously (e.g.
multiple agents or developers working in parallel), use `make dev` instead of
`yarn dev`. This automatically assigns unique ports per worktree.
### How It Works
1. A deterministic slot (0-99) is computed from the worktree directory name (via
`cksum`)
2. Each service gets a unique port: `base + slot` (see table below)
3. Docker Compose runs with a unique project name (`hdx-dev-<slot>`)
4. Volume paths include the slot to prevent data corruption between worktrees
### Dev Port Mapping (base + slot)
Ports are allocated in the 30100-31199 range to avoid conflicts with CI
integration tests (14320-40098) and E2E tests (20320-21399).
| Service | Base Port | Range | Env Variable |
| ----------------- | --------- | ------------- | ----------------------------- |
| API server | 30100 | 30100 - 30199 | `HYPERDX_API_PORT` |
| App (Next.js) | 30200 | 30200 - 30299 | `HYPERDX_APP_PORT` |
| OpAMP | 30300 | 30300 - 30399 | `HYPERDX_OPAMP_PORT` |
| MongoDB | 30400 | 30400 - 30499 | `HDX_DEV_MONGO_PORT` |
| ClickHouse HTTP | 30500 | 30500 - 30599 | `HDX_DEV_CH_HTTP_PORT` |
| ClickHouse Native | 30600 | 30600 - 30699 | `HDX_DEV_CH_NATIVE_PORT` |
| OTel health | 30700 | 30700 - 30799 | `HDX_DEV_OTEL_HEALTH_PORT` |
| OTel gRPC | 30800 | 30800 - 30899 | `HDX_DEV_OTEL_GRPC_PORT` |
| OTel HTTP | 30900 | 30900 - 30999 | `HDX_DEV_OTEL_HTTP_PORT` |
| OTel metrics | 31000 | 31000 - 31099 | `HDX_DEV_OTEL_METRICS_PORT` |
| OTel JSON HTTP | 31100 | 31100 - 31199 | `HDX_DEV_OTEL_JSON_HTTP_PORT` |
### Dev Portal
The dev portal is a centralized web dashboard that discovers all running
worktree stacks by inspecting Docker container labels and slot files.
```bash
# Start the portal (runs on fixed port 9900)
make dev-portal
# Open in browser
open http://localhost:9900
```
The portal auto-refreshes every 3 seconds and shows each worktree's:
- Branch name and slot number
- All services with status (running/stopped) and clickable port links
- Separate cards for each active worktree
### Overriding the Slot
```bash
# Use a specific slot instead of the auto-computed one
HDX_DEV_SLOT=5 make dev
```
## Testing Strategy
### Testing Tools
- **Unit Tests**: Jest with TypeScript support
- **Integration Tests**: Jest with database fixtures
- **Frontend Testing**: React Testing Library + Jest
- **E2E Testing**: Playwright (frontend) and Custom smoke tests with BATS
(ingestion)
### Testing Patterns
- **TDD Approach**: Write tests before implementation for new features
- **Test organization**: Tests co-located with source files in `__tests__/`
directories
- **Mocking**: MSW for API mocking in frontend tests
- **Database testing**: Isolated test databases with fixtures
Enable parallel integration testing across multiple worktrees (#1917) ## Summary - Enable multiple agents/developers to run `make dev-int` simultaneously from different git worktrees without Docker port conflicts - Compute a deterministic port offset (0-99) from the worktree directory name via `cksum`, giving each worktree its own isolated Docker Compose project and port range - Switch `.env.test` files to use `${HDX_CI_*:-default}` variable expansion (powered by `dotenv-expand`) so test processes connect to the correct dynamic ports ## How it works Each worktree gets a unique **slot** derived from its directory name. All service ports are offset by that slot: | Service | Base port | Example (slot 68) | |-----------------|-----------|-------------------| | ClickHouse HTTP | 18123 | 18191 | | MongoDB | 39999 | 40067 | | API test server | 19000 | 19068 | | OpAMP | 14320 | 14388 | Docker Compose project names are also unique (`int-<slot>`), isolating containers and networks. Backward compatible — when no `HDX_CI_*` env vars are set, all ports fall back to their original defaults. ## Changes - **Makefile**: Added `HDX_CI_SLOT` computation and dynamic project names/ports for all `dev-int` targets - **docker-compose.ci.yml**: Ports use `${HDX_CI_*:-default}` env vars; removed unused OTel collector published port; removed hardcoded network name (auto-generated from project name) - **packages/api/.env.test** / **packages/common-utils/.env.test**: Ports use `${HDX_CI_*:-default}` expansion syntax - **packages/api/jest.config.js** / **packages/common-utils/jest.int.config.js**: Switched from `dotenv/config` to `dotenv-expand/config` to enable variable expansion - **packages/api/package.json** / **packages/common-utils/package.json**: Added `dotenv-expand` devDependency - **agent_docs/development.md**: Documented multi-agent worktree support ## Testing Ran full Alert integration test suite (`make dev-int FILE=alerts`) — **6 test suites, 150 tests passed** on slot 68 with dynamic ports.
2026-03-16 19:42:08 +00:00
### CI / Integration Testing
Enable parallel integration testing across multiple worktrees (#1917) ## Summary - Enable multiple agents/developers to run `make dev-int` simultaneously from different git worktrees without Docker port conflicts - Compute a deterministic port offset (0-99) from the worktree directory name via `cksum`, giving each worktree its own isolated Docker Compose project and port range - Switch `.env.test` files to use `${HDX_CI_*:-default}` variable expansion (powered by `dotenv-expand`) so test processes connect to the correct dynamic ports ## How it works Each worktree gets a unique **slot** derived from its directory name. All service ports are offset by that slot: | Service | Base port | Example (slot 68) | |-----------------|-----------|-------------------| | ClickHouse HTTP | 18123 | 18191 | | MongoDB | 39999 | 40067 | | API test server | 19000 | 19068 | | OpAMP | 14320 | 14388 | Docker Compose project names are also unique (`int-<slot>`), isolating containers and networks. Backward compatible — when no `HDX_CI_*` env vars are set, all ports fall back to their original defaults. ## Changes - **Makefile**: Added `HDX_CI_SLOT` computation and dynamic project names/ports for all `dev-int` targets - **docker-compose.ci.yml**: Ports use `${HDX_CI_*:-default}` env vars; removed unused OTel collector published port; removed hardcoded network name (auto-generated from project name) - **packages/api/.env.test** / **packages/common-utils/.env.test**: Ports use `${HDX_CI_*:-default}` expansion syntax - **packages/api/jest.config.js** / **packages/common-utils/jest.int.config.js**: Switched from `dotenv/config` to `dotenv-expand/config` to enable variable expansion - **packages/api/package.json** / **packages/common-utils/package.json**: Added `dotenv-expand` devDependency - **agent_docs/development.md**: Documented multi-agent worktree support ## Testing Ran full Alert integration test suite (`make dev-int FILE=alerts`) — **6 test suites, 150 tests passed** on slot 68 with dynamic ports.
2026-03-16 19:42:08 +00:00
For integration testing:
```bash
Enable parallel integration testing across multiple worktrees (#1917) ## Summary - Enable multiple agents/developers to run `make dev-int` simultaneously from different git worktrees without Docker port conflicts - Compute a deterministic port offset (0-99) from the worktree directory name via `cksum`, giving each worktree its own isolated Docker Compose project and port range - Switch `.env.test` files to use `${HDX_CI_*:-default}` variable expansion (powered by `dotenv-expand`) so test processes connect to the correct dynamic ports ## How it works Each worktree gets a unique **slot** derived from its directory name. All service ports are offset by that slot: | Service | Base port | Example (slot 68) | |-----------------|-----------|-------------------| | ClickHouse HTTP | 18123 | 18191 | | MongoDB | 39999 | 40067 | | API test server | 19000 | 19068 | | OpAMP | 14320 | 14388 | Docker Compose project names are also unique (`int-<slot>`), isolating containers and networks. Backward compatible — when no `HDX_CI_*` env vars are set, all ports fall back to their original defaults. ## Changes - **Makefile**: Added `HDX_CI_SLOT` computation and dynamic project names/ports for all `dev-int` targets - **docker-compose.ci.yml**: Ports use `${HDX_CI_*:-default}` env vars; removed unused OTel collector published port; removed hardcoded network name (auto-generated from project name) - **packages/api/.env.test** / **packages/common-utils/.env.test**: Ports use `${HDX_CI_*:-default}` expansion syntax - **packages/api/jest.config.js** / **packages/common-utils/jest.int.config.js**: Switched from `dotenv/config` to `dotenv-expand/config` to enable variable expansion - **packages/api/package.json** / **packages/common-utils/package.json**: Added `dotenv-expand` devDependency - **agent_docs/development.md**: Documented multi-agent worktree support ## Testing Ran full Alert integration test suite (`make dev-int FILE=alerts`) — **6 test suites, 150 tests passed** on slot 68 with dynamic ports.
2026-03-16 19:42:08 +00:00
# Build dependencies (run once before first test run)
make dev-int-build
Enable parallel integration testing across multiple worktrees (#1917) ## Summary - Enable multiple agents/developers to run `make dev-int` simultaneously from different git worktrees without Docker port conflicts - Compute a deterministic port offset (0-99) from the worktree directory name via `cksum`, giving each worktree its own isolated Docker Compose project and port range - Switch `.env.test` files to use `${HDX_CI_*:-default}` variable expansion (powered by `dotenv-expand`) so test processes connect to the correct dynamic ports ## How it works Each worktree gets a unique **slot** derived from its directory name. All service ports are offset by that slot: | Service | Base port | Example (slot 68) | |-----------------|-----------|-------------------| | ClickHouse HTTP | 18123 | 18191 | | MongoDB | 39999 | 40067 | | API test server | 19000 | 19068 | | OpAMP | 14320 | 14388 | Docker Compose project names are also unique (`int-<slot>`), isolating containers and networks. Backward compatible — when no `HDX_CI_*` env vars are set, all ports fall back to their original defaults. ## Changes - **Makefile**: Added `HDX_CI_SLOT` computation and dynamic project names/ports for all `dev-int` targets - **docker-compose.ci.yml**: Ports use `${HDX_CI_*:-default}` env vars; removed unused OTel collector published port; removed hardcoded network name (auto-generated from project name) - **packages/api/.env.test** / **packages/common-utils/.env.test**: Ports use `${HDX_CI_*:-default}` expansion syntax - **packages/api/jest.config.js** / **packages/common-utils/jest.int.config.js**: Switched from `dotenv/config` to `dotenv-expand/config` to enable variable expansion - **packages/api/package.json** / **packages/common-utils/package.json**: Added `dotenv-expand` devDependency - **agent_docs/development.md**: Documented multi-agent worktree support ## Testing Ran full Alert integration test suite (`make dev-int FILE=alerts`) — **6 test suites, 150 tests passed** on slot 68 with dynamic ports.
2026-03-16 19:42:08 +00:00
# Run API integration tests (spins up Docker services, runs tests, tears down)
make dev-int FILE=<TEST_FILE_NAME>
# Run common-utils integration tests
make dev-int-common-utils FILE=<TEST_FILE_NAME>
```
Enable parallel integration testing across multiple worktrees (#1917) ## Summary - Enable multiple agents/developers to run `make dev-int` simultaneously from different git worktrees without Docker port conflicts - Compute a deterministic port offset (0-99) from the worktree directory name via `cksum`, giving each worktree its own isolated Docker Compose project and port range - Switch `.env.test` files to use `${HDX_CI_*:-default}` variable expansion (powered by `dotenv-expand`) so test processes connect to the correct dynamic ports ## How it works Each worktree gets a unique **slot** derived from its directory name. All service ports are offset by that slot: | Service | Base port | Example (slot 68) | |-----------------|-----------|-------------------| | ClickHouse HTTP | 18123 | 18191 | | MongoDB | 39999 | 40067 | | API test server | 19000 | 19068 | | OpAMP | 14320 | 14388 | Docker Compose project names are also unique (`int-<slot>`), isolating containers and networks. Backward compatible — when no `HDX_CI_*` env vars are set, all ports fall back to their original defaults. ## Changes - **Makefile**: Added `HDX_CI_SLOT` computation and dynamic project names/ports for all `dev-int` targets - **docker-compose.ci.yml**: Ports use `${HDX_CI_*:-default}` env vars; removed unused OTel collector published port; removed hardcoded network name (auto-generated from project name) - **packages/api/.env.test** / **packages/common-utils/.env.test**: Ports use `${HDX_CI_*:-default}` expansion syntax - **packages/api/jest.config.js** / **packages/common-utils/jest.int.config.js**: Switched from `dotenv/config` to `dotenv-expand/config` to enable variable expansion - **packages/api/package.json** / **packages/common-utils/package.json**: Added `dotenv-expand` devDependency - **agent_docs/development.md**: Documented multi-agent worktree support ## Testing Ran full Alert integration test suite (`make dev-int FILE=alerts`) — **6 test suites, 150 tests passed** on slot 68 with dynamic ports.
2026-03-16 19:42:08 +00:00
**Multi-agent / worktree support:**
The `make dev-int` command automatically assigns unique Docker ports per
worktree directory, so multiple agents can run integration tests in parallel
without port conflicts.
- A deterministic slot (0-99) is computed from the worktree directory name
- Each slot gets its own Docker Compose project name and port range
- Override the slot manually: `make dev-int HDX_CI_SLOT=5 FILE=alerts`
- The slot and assigned ports are printed when `dev-int` starts
Port mapping (base + slot):
| Service | Default port (slot 0) | Variable |
| --------------- | --------------------- | ----------------- |
| ClickHouse HTTP | 18123 | HDX_CI_CH_PORT |
| MongoDB | 39999 | HDX_CI_MONGO_PORT |
| API test server | 19000 | HDX_CI_API_PORT |
| OpAMP | 14320 | HDX_CI_OPAMP_PORT |
**CI Testing Notes:**
Enable parallel integration testing across multiple worktrees (#1917) ## Summary - Enable multiple agents/developers to run `make dev-int` simultaneously from different git worktrees without Docker port conflicts - Compute a deterministic port offset (0-99) from the worktree directory name via `cksum`, giving each worktree its own isolated Docker Compose project and port range - Switch `.env.test` files to use `${HDX_CI_*:-default}` variable expansion (powered by `dotenv-expand`) so test processes connect to the correct dynamic ports ## How it works Each worktree gets a unique **slot** derived from its directory name. All service ports are offset by that slot: | Service | Base port | Example (slot 68) | |-----------------|-----------|-------------------| | ClickHouse HTTP | 18123 | 18191 | | MongoDB | 39999 | 40067 | | API test server | 19000 | 19068 | | OpAMP | 14320 | 14388 | Docker Compose project names are also unique (`int-<slot>`), isolating containers and networks. Backward compatible — when no `HDX_CI_*` env vars are set, all ports fall back to their original defaults. ## Changes - **Makefile**: Added `HDX_CI_SLOT` computation and dynamic project names/ports for all `dev-int` targets - **docker-compose.ci.yml**: Ports use `${HDX_CI_*:-default}` env vars; removed unused OTel collector published port; removed hardcoded network name (auto-generated from project name) - **packages/api/.env.test** / **packages/common-utils/.env.test**: Ports use `${HDX_CI_*:-default}` expansion syntax - **packages/api/jest.config.js** / **packages/common-utils/jest.int.config.js**: Switched from `dotenv/config` to `dotenv-expand/config` to enable variable expansion - **packages/api/package.json** / **packages/common-utils/package.json**: Added `dotenv-expand` devDependency - **agent_docs/development.md**: Documented multi-agent worktree support ## Testing Ran full Alert integration test suite (`make dev-int FILE=alerts`) — **6 test suites, 150 tests passed** on slot 68 with dynamic ports.
2026-03-16 19:42:08 +00:00
- Uses separate Docker Compose configuration (`docker-compose.ci.yml`)
- Isolated test environment with unique `-p int-<slot>` project name
- Includes all necessary services (ClickHouse, MongoDB, OTel Collector)
- Tests run against real database instances for accurate integration testing
[HDX-3796] Isolate E2E test environment with slot-based port assignment (#1983) ## Summary - Adds worktree-aware port isolation for E2E tests, mirroring the existing `dev-int` slot mechanism so multiple agents/developers can run E2E tests in parallel without port conflicts - Fixes the navigation E2E test that was broken by Live Tail URL updates swallowing client-side navigation - Adds `dev-e2e` Makefile target for running specific tests with `FILE=` and `GREP=` filters, plus `REPORT=1` to open the HTML report after tests finish ## Port Isolation Each worktree gets a deterministic slot (0–99) computed from its directory name. All E2E service ports are offset by that slot in the **44000–50100** range, avoiding collisions with `dev` (4317–27017) and `dev-int` (14320–40098). | Service | Base + slot | Variable | |---|---|---| | ClickHouse HTTP | 48123 + slot | `HDX_E2E_CH_PORT` | | ClickHouse Native | 49000 + slot | `HDX_E2E_CH_NATIVE_PORT` | | MongoDB | 49998 + slot | `HDX_E2E_MONGO_PORT` | | API server | 49100 + slot | `HDX_E2E_API_PORT` | | App (fullstack) | 48081 + slot | `HDX_E2E_APP_PORT` | | App (local) | 48001 + slot | `HDX_E2E_APP_LOCAL_PORT` | | OpAMP | 44320 + slot | `HDX_E2E_OPAMP_PORT` | ## New Make Targets ```bash make dev-e2e FILE=navigation # Run specific test file make dev-e2e FILE=navigation GREP="help menu" # Filter by test name make dev-e2e GREP="should navigate" # Grep across all files make dev-e2e FILE=navigation REPORT=1 # Open HTML report after run make dev-e2e-clean # Remove test artifacts ``` ## Linear https://linear.app/hyperdx/issue/HDX-3796
2026-03-26 18:19:14 +00:00
### E2E Testing
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
E2E tests use the same slot-based isolation pattern as integration tests, with
their own dedicated port range (20320-21399) so they can run simultaneously with
both the dev stack and CI integration tests.
E2E port mapping (base + slot):
| Service | Base Port | Range | Env Variable |
| ----------------- | --------- | ------------- | ------------------------ |
| OpAMP | 20320 | 20320 - 20419 | `HDX_E2E_OPAMP_PORT` |
| ClickHouse HTTP | 20500 | 20500 - 20599 | `HDX_E2E_CH_PORT` |
| ClickHouse Native | 20600 | 20600 - 20699 | `HDX_E2E_CH_NATIVE_PORT` |
| API server | 21000 | 21000 - 21099 | `HDX_E2E_API_PORT` |
| MongoDB | 21100 | 21100 - 21199 | `HDX_E2E_MONGO_PORT` |
| App (local) | 21200 | 21200 - 21299 | `HDX_E2E_APP_LOCAL_PORT` |
| App (fullstack) | 21300 | 21300 - 21399 | `HDX_E2E_APP_PORT` |
[HDX-3796] Isolate E2E test environment with slot-based port assignment (#1983) ## Summary - Adds worktree-aware port isolation for E2E tests, mirroring the existing `dev-int` slot mechanism so multiple agents/developers can run E2E tests in parallel without port conflicts - Fixes the navigation E2E test that was broken by Live Tail URL updates swallowing client-side navigation - Adds `dev-e2e` Makefile target for running specific tests with `FILE=` and `GREP=` filters, plus `REPORT=1` to open the HTML report after tests finish ## Port Isolation Each worktree gets a deterministic slot (0–99) computed from its directory name. All E2E service ports are offset by that slot in the **44000–50100** range, avoiding collisions with `dev` (4317–27017) and `dev-int` (14320–40098). | Service | Base + slot | Variable | |---|---|---| | ClickHouse HTTP | 48123 + slot | `HDX_E2E_CH_PORT` | | ClickHouse Native | 49000 + slot | `HDX_E2E_CH_NATIVE_PORT` | | MongoDB | 49998 + slot | `HDX_E2E_MONGO_PORT` | | API server | 49100 + slot | `HDX_E2E_API_PORT` | | App (fullstack) | 48081 + slot | `HDX_E2E_APP_PORT` | | App (local) | 48001 + slot | `HDX_E2E_APP_LOCAL_PORT` | | OpAMP | 44320 + slot | `HDX_E2E_OPAMP_PORT` | ## New Make Targets ```bash make dev-e2e FILE=navigation # Run specific test file make dev-e2e FILE=navigation GREP="help menu" # Filter by test name make dev-e2e GREP="should navigate" # Grep across all files make dev-e2e FILE=navigation REPORT=1 # Open HTML report after run make dev-e2e-clean # Remove test artifacts ``` ## Linear https://linear.app/hyperdx/issue/HDX-3796
2026-03-26 18:19:14 +00:00
```bash
# Run all E2E tests
make e2e
# Run a specific test file (dev mode: hot reload, containers kept running)
make dev-e2e FILE=navigation
# Run a specific test by grep pattern
make dev-e2e FILE=navigation GREP="help menu"
# Grep across all files
make dev-e2e GREP="should navigate"
# Open HTML report after tests finish (screenshots, traces, step-by-step)
make dev-e2e FILE=navigation REPORT=1
# Or call the script directly for more control
./scripts/test-e2e.sh --ui --last-failed
# Override the slot manually
HDX_E2E_SLOT=5 ./scripts/test-e2e.sh
```
- A deterministic slot (0-99) is computed from the worktree directory name
- Each slot gets its own Docker Compose project name (`e2e-<slot>`) and port
range
- The slot and assigned ports are printed when E2E tests start
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
**Port range safety:** E2E has its own dedicated port range (20320-21399) that
does not overlap with CI integration tests (14320-40098) or the dev stack
(30100-31199), so all three can run simultaneously from the same worktree.
[HDX-3796] Isolate E2E test environment with slot-based port assignment (#1983) ## Summary - Adds worktree-aware port isolation for E2E tests, mirroring the existing `dev-int` slot mechanism so multiple agents/developers can run E2E tests in parallel without port conflicts - Fixes the navigation E2E test that was broken by Live Tail URL updates swallowing client-side navigation - Adds `dev-e2e` Makefile target for running specific tests with `FILE=` and `GREP=` filters, plus `REPORT=1` to open the HTML report after tests finish ## Port Isolation Each worktree gets a deterministic slot (0–99) computed from its directory name. All E2E service ports are offset by that slot in the **44000–50100** range, avoiding collisions with `dev` (4317–27017) and `dev-int` (14320–40098). | Service | Base + slot | Variable | |---|---|---| | ClickHouse HTTP | 48123 + slot | `HDX_E2E_CH_PORT` | | ClickHouse Native | 49000 + slot | `HDX_E2E_CH_NATIVE_PORT` | | MongoDB | 49998 + slot | `HDX_E2E_MONGO_PORT` | | API server | 49100 + slot | `HDX_E2E_API_PORT` | | App (fullstack) | 48081 + slot | `HDX_E2E_APP_PORT` | | App (local) | 48001 + slot | `HDX_E2E_APP_LOCAL_PORT` | | OpAMP | 44320 + slot | `HDX_E2E_OPAMP_PORT` | ## New Make Targets ```bash make dev-e2e FILE=navigation # Run specific test file make dev-e2e FILE=navigation GREP="help menu" # Filter by test name make dev-e2e GREP="should navigate" # Grep across all files make dev-e2e FILE=navigation REPORT=1 # Open HTML report after run make dev-e2e-clean # Remove test artifacts ``` ## Linear https://linear.app/hyperdx/issue/HDX-3796
2026-03-26 18:19:14 +00:00
## Common Development Tasks
### Adding New Features
1. **API First**: Define API endpoints and data models
2. **Database Models**: Create/update Mongoose schemas and ClickHouse queries
3. **Frontend Integration**: Build UI components and integrate with API
4. **Testing**: Add unit and integration tests
5. **Documentation**: Update relevant docs
### Debugging
- Check browser and server console output for errors, warnings, or relevant logs
- Add targeted logging to trace execution and variable states
- For persistent issues, check `fixes/` directory for documented solutions
- Document complex fixes in `fixes/` directory with descriptive filenames
## Code Quality
### Pre-commit Hooks
The project uses Husky + lint-staged to automatically run:
- Prettier for formatting
- ESLint for linting
- API doc generation (for external API changes)
These run automatically on `git commit` for staged files.
### Manual Linting (if needed)
If you need to manually lint:
```bash
# Per-package linting with auto-fix
cd packages/app && yarn run lint:fix
cd packages/api && yarn run lint:fix
cd packages/common-utils && yarn lint:fix
# Check all packages
yarn run lint
```
## File Locations Quick Reference
- **Config**: `packages/api/src/config.ts`, `packages/app/next.config.mjs`,
`docker-compose.dev.yml`
- **Models**: `packages/api/src/models/`
- **API Routes**: `packages/api/src/routers/`
- **Controllers**: `packages/api/src/controllers/`
- **Pages**: `packages/app/pages/`
- **Components**: `packages/app/src/`
- **Shared Utils**: `packages/common-utils/src/`