From c4df866bcf672777cc9ba0fde8e5222863d8a6b5 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Mon, 25 May 2026 18:28:47 +0530 Subject: [PATCH] feat: add devcontainer based setup docs --- .vscode/launch.json | 24 +++ api/conftest.py | 5 + docs/contribution/devcontainer.mdx | 101 ++++++++++++ docs/contribution/fork-workflow.mdx | 41 +++++ docs/contribution/host-managed-setup.mdx | 67 ++++++++ docs/contribution/setup.mdx | 149 ++++-------------- docs/docs.json | 9 +- scripts/setup_requirements.ps1 | 16 ++ scripts/setup_requirements.sh | 20 +++ .../src/dograh_sdk/_generated_models.py | 4 +- 10 files changed, 311 insertions(+), 125 deletions(-) create mode 100644 docs/contribution/devcontainer.mdx create mode 100644 docs/contribution/fork-workflow.mdx create mode 100644 docs/contribution/host-managed-setup.mdx diff --git a/.vscode/launch.json b/.vscode/launch.json index 8493ec6..9826cbf 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -49,6 +49,30 @@ }, "justMyCode": false }, + { + "name": "API: Campaign orchestrator", + "type": "debugpy", + "request": "launch", + "module": "api.services.campaign.campaign_orchestrator", + "cwd": "${workspaceFolder}", + "envFile": "${workspaceFolder}/api/.env", + "env": { + "PYTHONPATH": "${workspaceFolder}" + }, + "justMyCode": false + }, + { + "name": "API: ARI manager", + "type": "debugpy", + "request": "launch", + "module": "api.services.telephony.ari_manager", + "cwd": "${workspaceFolder}", + "envFile": "${workspaceFolder}/api/.env", + "env": { + "PYTHONPATH": "${workspaceFolder}" + }, + "justMyCode": false + }, { "name": "Tests: API (pytest, full suite)", "type": "debugpy", diff --git a/api/conftest.py b/api/conftest.py index ab47760..68a8aef 100644 --- a/api/conftest.py +++ b/api/conftest.py @@ -30,6 +30,11 @@ import sys import loguru import pytest +REPO_ROOT = Path(__file__).resolve().parents[1] +SDK_PY_SRC = REPO_ROOT / "sdk" / "python" / "src" +if str(SDK_PY_SRC) not in sys.path: + sys.path.insert(0, str(SDK_PY_SRC)) + from api.constants import APP_ROOT_DIR # noqa: E402 diff --git a/docs/contribution/devcontainer.mdx b/docs/contribution/devcontainer.mdx new file mode 100644 index 0000000..a0ae211 --- /dev/null +++ b/docs/contribution/devcontainer.mdx @@ -0,0 +1,101 @@ +--- +title: Devcontainer Workflow +description: Details for running and maintaining the Dograh devcontainer. +--- + +The checked-in `.devcontainer/` follows the Dev Containers specification, so it should also work in Cursor, JetBrains IDEs, and other Dev Container-compatible editors. Only the VS Code path is actively tested. If something breaks elsewhere, please open a [GitHub issue](https://github.com/dograh-hq/dograh/issues). + +### What the Bootstrap Does + +While the container starts, the devcontainer will: + +- Initialize the `pipecat` git submodule on the host through `initializeCommand` +- Bring up `postgres`, `redis`, and `minio` through Docker Compose and wait for them to be healthy +- Seed the `venv` named volume from the image-baked Python 3.13 venv +- Reinstall `pipecat` as editable from the bind-mounted submodule so source edits take effect +- Create `api/.env`, `api/.env.test`, and `ui/.env` from their `*.example` templates if they do not already exist +- Run `npm ci` for `ui/` and `api/mcp_server/ts_validator/` + +In the API env files, `localhost` for Postgres, Redis, and MinIO is rewritten to the docker network aliases `postgres`, `redis`, and `minio`. `MINIO_PUBLIC_ENDPOINT` deliberately stays on `localhost` because the browser on your host loads from it. + + +If you already had an `api/.env` or `api/.env.test` from host-managed development with `localhost` hosts for Postgres, Redis, or MinIO, the bootstrap leaves it untouched. Edit those URLs to the docker network aliases before starting the backend inside the devcontainer, or delete the file and let the bootstrap recreate it on the next rebuild. + + +### Dev Container CLI + +Install the CLI once on your host: + +```bash +npm install -g @devcontainers/cli +``` + +Start or rebuild the container from the repository root: + +```bash +devcontainer up --workspace-folder . +``` + +Open a shell in the running workspace container: + +```bash +devcontainer exec --workspace-folder . bash +``` + +Run a one-off command from the host: + +```bash +devcontainer exec --workspace-folder . bash scripts/start_services_dev.sh +``` + +### Backend Logs + +Tail backend logs from inside the container: + +```bash +tail -f logs/latest/*.log +``` + +### Restarting the Backend + +Re-run the same start script to restart. It reads the PID files under `run/`, terminates the previous services along with their descendants, and starts fresh ones. + +```bash +bash scripts/start_services_dev.sh +``` + + +`uvicorn` runs with `--reload --reload-dir api`, so edits under `api/` are picked up automatically. The other services (`ari_manager`, `campaign_orchestrator`, `arq`) do not auto-reload; re-run the start script after changing code they execute. + + +### When to Rebuild the Container + +The workspace bind mount and the `venv` / `node_modules` named volumes persist across container restarts, so you rarely need to rebuild. Rebuild only when one of these changes: + +- `.devcontainer/Dockerfile` or `.devcontainer/devcontainer.json` +- `api/requirements.txt` or `api/requirements.dev.txt` +- The `pipecat/` submodule + +Plain source edits, `ui/package.json`, and the `.env.example` templates do **not** require a rebuild. After a `git pull`, a quick check: + +```bash +git diff HEAD@{1} HEAD -- .devcontainer api/requirements.txt api/requirements.dev.txt pipecat +``` + +If the diff is empty, you can keep your current container. + +### Personal Install Hook + +Anything you install inside the container outside the named volumes, notably under `/home/vscode`, is wiped on rebuild. This includes `npm i -g` packages and tools like the Claude or Codex CLIs. + +To reinstall personal tooling automatically on every rebuild, drop an executable script at `.devcontainer/install.local.sh`. It is gitignored and runs at the tail of the post-create bootstrap. Example: + +```bash +#!/usr/bin/env bash +set -euo pipefail + +command -v claude >/dev/null 2>&1 || curl -fsSL https://claude.ai/install.sh | bash +command -v codex >/dev/null 2>&1 || npm i -g @openai/codex +``` + +Keep entries idempotent with `command -v` or a marker file so re-runs are cheap and safe. diff --git a/docs/contribution/fork-workflow.mdx b/docs/contribution/fork-workflow.mdx new file mode 100644 index 0000000..22e7fc5 --- /dev/null +++ b/docs/contribution/fork-workflow.mdx @@ -0,0 +1,41 @@ +--- +title: Fork Workflow +description: Keep your Dograh fork connected to upstream. +--- + +The contributor bootstrap script configures two remotes: + +- `origin`: your fork, where you push +- `upstream`: `dograh-hq/dograh`, where new commits land + +If you cloned `dograh-hq/dograh` directly instead of your fork, run this once inside the devcontainer after it boots: + +```bash +bash scripts/setup_fork.sh +``` + +To pull in upstream changes: + +```bash +git fetch upstream +git checkout main +git merge upstream/main +git push origin main +``` + +Check your remotes any time with: + +```bash +git remote -v +``` + +You should see: + +```bash +origin https://github.com//dograh.git (fetch/push) +upstream https://github.com/dograh-hq/dograh.git (fetch/push) +``` + + +Always push feature branches to **`origin`** (your fork), then open a pull request against `dograh-hq/dograh:main`. Never push directly to `upstream`. + diff --git a/docs/contribution/host-managed-setup.mdx b/docs/contribution/host-managed-setup.mdx new file mode 100644 index 0000000..25dd5d9 --- /dev/null +++ b/docs/contribution/host-managed-setup.mdx @@ -0,0 +1,67 @@ +--- +title: Host-managed Setup +description: Set up Dograh directly on your host without the devcontainer. +--- + +Use this only if you do not want to use the devcontainer. + +### System Requirements + +- Git +- Node.js 24 to run the UI +- Python 3.13 to run the backend +- Docker to run Postgres, Redis, and MinIO locally + +1. Run the contributor bootstrap. It configures `origin` as your fork and `upstream` as `dograh-hq/dograh`, initializes the pipecat submodule, creates the Python venv, and copies the `.env` templates. + +```bash macOS/Linux +bash scripts/setup_fork.sh +``` +```powershell Windows +.\scripts\setup_fork.ps1 +``` + +2. Activate the virtual environment: + +```bash macOS/Linux +source venv/bin/activate +``` +```powershell Windows +.\venv\Scripts\Activate.ps1 +``` + +3. Ensure your local Node version is 24: +```bash +nvm use 24 +``` +4. Install UI dependencies: +```bash +cd ui && npm install && cd .. +``` +5. Start the local Docker services: +```bash +docker compose -f docker-compose-local.yaml up -d +``` +6. Install Python requirements: + +```bash macOS/Linux +bash scripts/setup_requirements.sh --dev +``` +```powershell Windows +.\scripts\setup_requirements.ps1 -Dev +``` + +7. Start the backend services: + +```bash macOS/Linux +bash scripts/start_services_dev.sh +``` +```powershell Windows +.\scripts\start_services_dev.ps1 +``` + +8. Start the UI: +```bash +cd ui && npm run dev +``` +9. Open the application on `http://localhost:3000`. diff --git a/docs/contribution/setup.mdx b/docs/contribution/setup.mdx index 8e8a21e..a2ed249 100644 --- a/docs/contribution/setup.mdx +++ b/docs/contribution/setup.mdx @@ -1,21 +1,18 @@ --- title: Setup -description: Use this page to set up the Dograh contributor environment, with a devcontainer-first workflow. +description: Set up the Dograh contributor environment with the devcontainer-first workflow. --- If the steps below do not work for you, please open an issue on [GitHub](https://github.com/dograh-hq/dograh/issues). -### Recommended: Devcontainer setup +### Recommended: Devcontainer Setup #### System Requirements - Git - Docker Desktop or another local Docker engine -- A Dev Container-compatible editor. The most tested path is VS Code with the [Dev Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers). - - -The checked-in `.devcontainer/` follows the Dev Containers specification. VS Code is the default recommendation because its support is the most mature and best documented, but the same setup should also work in tools like Cursor and JetBrains IDEs that support Dev Containers. - +- For the IDE path: VS Code with the [Dev Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) +- For the terminal-only path: Node.js on your host so you can install the Dev Container CLI 1. Fork the Dograh repository at https://github.com/dograh-hq/dograh 2. Clone **your fork**: @@ -23,25 +20,35 @@ The checked-in `.devcontainer/` follows the Dev Containers specification. VS Cod git clone https://github.com//dograh cd dograh ``` -If you cloned `dograh-hq/dograh` directly instead of your fork, run `bash scripts/setup_fork.sh` once inside the container after it boots to reset `origin` and `upstream`. +3. Start the devcontainer. -3. Open the repository in your Dev Container-compatible editor and start the devcontainer. -If you are using VS Code, run **Dev Containers: Reopen in Container**. -4. Wait for the first container boot to finish. The post-create bootstrap will: -- initialize the `pipecat` submodule -- create `venv/` with Python 3.13 -- install backend dependencies with `scripts/setup_requirements.sh --dev` -- install `ui/` dependencies and `api/mcp_server/ts_validator` dependencies -- create `api/.env` and `ui/.env` if they do not already exist (rewriting docker network hostnames in `api/.env`) -- start `postgres`, `redis`, and `minio` via Docker Compose + In VS Code, open the repository and run **Dev Containers: Reopen in Container**. + + Without an IDE, use the Dev Container CLI: +```bash +npm install -g @devcontainers/cli +devcontainer up --workspace-folder . +devcontainer exec --workspace-folder . bash +``` +4. Wait for the first build to finish. The first build takes several minutes; subsequent opens are much faster. 5. Start the backend from a terminal inside the container: ```bash bash scripts/start_services_dev.sh +``` + + Without an IDE, run the same command from your host: +```bash +devcontainer exec --workspace-folder . bash scripts/start_services_dev.sh ``` 6. Start the UI from another terminal inside the container: ```bash cd ui npm run dev -- --hostname 0.0.0.0 +``` + + Without an IDE, use another host terminal: +```bash +devcontainer exec --workspace-folder . bash -lc 'cd ui && npm run dev -- --hostname 0.0.0.0' ``` 7. Verify that the backend is healthy: ```bash @@ -49,108 +56,8 @@ curl -X GET localhost:8000/api/v1/health ``` 8. Open the app at `http://localhost:3000`. -You can tail backend logs from inside the container with: +### More Setup Options -```bash -tail -f logs/latest/*.log -``` - -The backend reads `api/.env` both on the host and inside the devcontainer. The post-create bootstrap rewrites `DATABASE_URL`, `REDIS_URL`, and `MINIO_ENDPOINT` to docker network aliases (`postgres`, `redis`, `minio`) when it creates the file. If you already had an `api/.env` from host development with `localhost` hosts for those, edit it before starting the backend inside the devcontainer. - -#### Restarting the backend -Re-run the same start script to restart. It reads the PID files under `run/`, terminates the previous services along with their descendants, and starts fresh ones. - -```bash -bash scripts/start_services_dev.sh -``` - - -`uvicorn` runs with `--reload --reload-dir api`, so edits under `api/` are picked up automatically. The other services (`ari_manager`, `campaign_orchestrator`, `arq`) do not auto-reload; re-run the start script after changing code they execute. - - -### Fallback: host-managed setup -Use this only if you do not want to use the devcontainer. - -#### System Requirements -- Git -- Node.js 24 to run the UI -- Python 3.13 to run the backend -- Docker to run Postgres, Redis, and MinIO locally - -1. Run the contributor bootstrap. It configures `origin` (your fork) and `upstream` (`dograh-hq/dograh`), initializes the pipecat submodule, creates the Python venv, and copies the `.env` templates. - -```bash macOS/Linux -bash scripts/setup_fork.sh -``` -```powershell Windows -.\scripts\setup_fork.ps1 -``` - -2. Activate the virtual environment: - -```bash macOS/Linux -source venv/bin/activate -``` -```powershell Windows -.\venv\Scripts\Activate.ps1 -``` - -3. Ensure your local Node version is 24: -```bash -nvm use 24 -``` -4. Install UI dependencies: -```bash -cd ui && npm install && cd .. -``` -5. Start the local Docker services: -```bash -docker compose -f docker-compose-local.yaml up -d -``` -6. Install Python requirements: - -```bash macOS/Linux -bash scripts/setup_requirements.sh --dev -``` -```powershell Windows -.\scripts\setup_requirements.ps1 -Dev -``` - -7. Start the backend services: - -```bash macOS/Linux -bash scripts/start_services_dev.sh -``` -```powershell Windows -.\scripts\start_services_dev.ps1 -``` - -8. Start the UI: -```bash -cd ui && npm run dev -``` -9. Open the application on `http://localhost:3000`. - -### Keeping your fork in sync with upstream -The bootstrap script configures two remotes: `origin` (your fork, where you push) and `upstream` (`dograh-hq/dograh`, where new commits land). To pull in upstream changes: - -```bash -git fetch upstream -git checkout main -git merge upstream/main -git push origin main -``` - -Check your remotes any time with `git remote -v`. You should see: - -```bash -origin https://github.com//dograh.git (fetch/push) -upstream https://github.com/dograh-hq/dograh.git (fetch/push) -``` - - -Always push feature branches to **`origin`** (your fork), then open a pull request against `dograh-hq/dograh:main`. Never push directly to `upstream`. - - -### Next Steps -The repository ships with `AGENTS.md` and `CLAUDE.md` so coding agents can navigate the codebase quickly. Adjust them locally if you need agent-specific guidance for your workflow. +- For what the devcontainer bootstrap does, rebuild guidance, logs, and personal install hooks, see [Devcontainer Workflow](/contribution/devcontainer). +- If you cloned `dograh-hq/dograh` directly instead of your fork, see [Fork Workflow](/contribution/fork-workflow) to reset `origin` and `upstream`. +- If you do not want to use the devcontainer, see [Host-managed Setup](/contribution/host-managed-setup). diff --git a/docs/docs.json b/docs/docs.json index 446adf6..717e90c 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -129,7 +129,10 @@ "group": "Contribution", "pages": [ "contribution/introduction", - "contribution/setup" + "contribution/setup", + "contribution/devcontainer", + "contribution/host-managed-setup", + "contribution/fork-workflow" ] }, { @@ -292,7 +295,6 @@ "search": { "prompt": "Search for Tools, Webhook, Deployment, etc..." }, - "openapi": "/api-reference/openapi.json", "customCSS": "/custom.css", "contextual": { "options": [ @@ -311,5 +313,8 @@ "github": "https://github.com/dograh-hq", "linkedin": "https://linkedin.com/company/dograh" } + }, + "api": { + "openapi": "api-reference/openapi.json" } } diff --git a/scripts/setup_requirements.ps1 b/scripts/setup_requirements.ps1 index 6c80542..21f5359 100644 --- a/scripts/setup_requirements.ps1 +++ b/scripts/setup_requirements.ps1 @@ -18,6 +18,22 @@ $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path $BaseDir = Split-Path -Parent $ScriptDir Set-Location $BaseDir +# Fail early if the active Python is not 3.12 or 3.13. uv pip installs into +# whichever interpreter resolves here (the active venv, or PATH python), so a +# mismatch surfaces as confusing wheel/build errors much later. +$PythonBin = if ($env:PYTHON) { $env:PYTHON } else { 'python' } +if (-not (Get-Command $PythonBin -ErrorAction SilentlyContinue)) { + Write-Error "'$PythonBin' not found on PATH. Activate the project venv (or set `$env:PYTHON) and retry." + exit 1 +} + +$PyMajMin = & $PythonBin -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")' +if ($PyMajMin -ne '3.12' -and $PyMajMin -ne '3.13') { + $PyPath = (Get-Command $PythonBin).Source + Write-Error "Python 3.12 or 3.13 required, found $PyMajMin at $PyPath. Activate a venv built with python3.12 or python3.13 and retry." + exit 1 +} + Write-Host "Setting up pipecat as a git submodule..." if (-not $Dev) { diff --git a/scripts/setup_requirements.sh b/scripts/setup_requirements.sh index 1bd905b..f744a2f 100755 --- a/scripts/setup_requirements.sh +++ b/scripts/setup_requirements.sh @@ -32,6 +32,26 @@ DOGRAH_DIR="$(dirname "$SCRIPT_DIR")" cd "$DOGRAH_DIR" +# Fail early if the active Python is not 3.12 or 3.13. uv pip installs into +# whichever interpreter resolves here (the active venv, or PATH python3), so a +# mismatch surfaces as confusing wheel/build errors much later. +PYTHON_BIN="${PYTHON:-python3}" +if ! command -v "$PYTHON_BIN" >/dev/null 2>&1; then + echo "Error: '$PYTHON_BIN' not found on PATH." >&2 + echo "Activate the project venv (or set PYTHON=/path/to/python) and retry." >&2 + exit 1 +fi + +PY_MAJ_MIN=$("$PYTHON_BIN" -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")') +case "$PY_MAJ_MIN" in + 3.12|3.13) ;; + *) + echo "Error: Python 3.12 or 3.13 required, found $PY_MAJ_MIN at $(command -v "$PYTHON_BIN")." >&2 + echo "Activate a venv built with python3.12 or python3.13 and retry." >&2 + exit 1 + ;; +esac + echo "Setting up pipecat as a git submodule..." if [ "$DEV_MODE" -eq 0 ]; then diff --git a/sdk/python/src/dograh_sdk/_generated_models.py b/sdk/python/src/dograh_sdk/_generated_models.py index 95a3a28..d4dbeea 100644 --- a/sdk/python/src/dograh_sdk/_generated_models.py +++ b/sdk/python/src/dograh_sdk/_generated_models.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: -# filename: dograh-openapi-XXXXXX.json.N8gRI5v3bD -# timestamp: 2026-05-23T09:14:22+00:00 +# filename: dograh-openapi-T200ed.json +# timestamp: 2026-05-25T12:42:12+00:00 from __future__ import annotations