From 5189a7c0cb21d782de39ade1e6cc4f54ac280b95 Mon Sep 17 00:00:00 2001 From: sandrawillow001-afk Date: Tue, 29 Sep 2026 00:27:07 +0000 Subject: [PATCH] feat(devtooling): local chain, debug configs and resource controls in devcontainer (#238) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The devcontainer covered Postgres and Redis but not the rest of the acceptance criteria: there was no local blockchain node, no debug configuration, no resource allocation controls, and chain state was lost on every restart. - docker-compose: add a `stellar` service (stellar-quickstart in local mode, mirroring docker-compose.sandbox.yml) and an opt-in `evm` Hardhat service; expose CPU/memory limits and reservations for every service, overridable via DEV_*_CPUS / DEV_*_MEMORY. - volumes: persist ledger state (`stellar-data`), Hardhat cache and the Rust contract build cache so deploys survive a restart. - devcontainer.json: forward the chain and debugger ports with labels, export STELLAR_RPC_URL / SOROBAN_RPC_URL / EVM_RPC_URL, and declare hostRequirements so an under-resourced host fails fast. - debug configs: tracked templates in .devcontainer/vscode/ (the .vscode directory is gitignored) installed on create, covering backend (tsx + inspector 9229), frontend, current test file, Soroban tests, attach mode and a full-stack compound, plus stack/chain tasks. - scripts/devcontainer.sh: add `infra`, `stellar`, `evm` and a guarded `reset`. - docs: document nodes, debug configs, resource knobs and volumes. 🤖 Generated with Codebuff Co-Authored-By: Codebuff --- .devcontainer/devcontainer.json | 26 +++++-- .devcontainer/docker-compose.yml | 116 ++++++++++++++++++++++++++++++- .devcontainer/post-create.sh | 15 ++++ .devcontainer/post-start.sh | 8 ++- .devcontainer/vscode/launch.json | 77 ++++++++++++++++++++ .devcontainer/vscode/tasks.json | 55 +++++++++++++++ docs/DEVCONTAINER.md | 107 +++++++++++++++++++++++++++- scripts/devcontainer.sh | 85 +++++++++++++++------- 8 files changed, 454 insertions(+), 35 deletions(-) create mode 100644 .devcontainer/vscode/launch.json create mode 100644 .devcontainer/vscode/tasks.json diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index cc0d3c75..a869e361 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -30,14 +30,27 @@ "OPENAI_API_KEY": "sk-dev-placeholder-replace-me", "JOBS_ENABLED": "false", "QUEUE_ENABLED": "false", - "CORS_ALLOWED_ORIGINS": "*" + "CORS_ALLOWED_ORIGINS": "*", + "STELLAR_RPC_URL": "http://stellar:8000/soroban/rpc", + "SOROBAN_RPC_URL": "http://stellar:8000/soroban/rpc", + "STELLAR_NETWORK": "local", + "EVM_RPC_URL": "http://evm:8545" }, - "forwardPorts": [3000, 3001, 5432, 6379], + "forwardPorts": [3000, 3001, 5432, 6379, 7001, 8000, 8545, 9229], "portsAttributes": { "3000": { "label": "Frontend", "onAutoForward": "notify" }, "3001": { "label": "Backend API", "onAutoForward": "silent" }, "5432": { "label": "PostgreSQL", "onAutoForward": "ignore" }, - "6379": { "label": "Redis", "onAutoForward": "ignore" } + "6379": { "label": "Redis", "onAutoForward": "ignore" }, + "7001": { "label": "Stellar Core", "onAutoForward": "ignore" }, + "8000": { "label": "Soroban RPC", "onAutoForward": "silent" }, + "8545": { "label": "EVM node (Hardhat)", "onAutoForward": "silent" }, + "9229": { "label": "Node debugger", "onAutoForward": "silent" } + }, + "hostRequirements": { + "cpus": 4, + "memory": "8gb", + "storage": "32gb" }, "postCreateCommand": "bash .devcontainer/post-create.sh", "postStartCommand": "bash .devcontainer/post-start.sh", @@ -54,13 +67,16 @@ "redhat.vscode-yaml", "42Crunch.vscode-openapi", "ms-azuretools.vscode-docker", - "github.vscode-github-actions" + "github.vscode-github-actions", + "vitest.explorer" ], "settings": { "editor.formatOnSave": true, "editor.defaultFormatter": "esbenp.prettier-vscode", "typescript.tsdk": "node_modules/typescript/lib", - "rust-analyzer.checkOnSave.command": "clippy" + "rust-analyzer.checkOnSave.command": "clippy", + "debug.javascript.autoAttachFilter": "smart", + "vitest.enable": true } } }, diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index 8fcf8d39..20208056 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -1,4 +1,4 @@ -# Devcontainer services: dev environment + Postgres + Redis. +# Devcontainer services: dev environment + Postgres + Redis + local chains. # Used by VS Code / Cursor "Reopen in Container". Root docker-compose.yml # provides the same Postgres/Redis stack for local (non-container) development. # @@ -9,6 +9,14 @@ # # scripts/devcontainer.sh up # # or: docker compose -f .devcontainer/docker-compose.yml --profile app up +# +# Resource allocation controls (issue #238) are env-driven so a machine under +# load can be dialled down without editing this file: +# +# DEV_POSTGRES_MEMORY=1G DEV_STELLAR_CPUS=2 docker compose ... up -d +# +# Apple Silicon: every image below publishes arm64 except the EVM node, which +# runs via Rosetta/QEMU emulation. Set DEV_EVM_PLATFORM=linux/arm64 to skip it. services: devcontainer: @@ -23,9 +31,18 @@ services: condition: service_healthy redis: condition: service_healthy + stellar: + condition: service_started environment: DATABASE_URL: postgresql://postgres:postgres@postgres:5432/agenticpay REDIS_URL: redis://redis:6379 + STELLAR_RPC_URL: http://stellar:8000/soroban/rpc + SOROBAN_RPC_URL: http://stellar:8000/soroban/rpc + deploy: + resources: + limits: + cpus: '${DEV_DEVCONTAINER_CPUS:-4.0}' + memory: ${DEV_DEVCONTAINER_MEMORY:-6G} postgres: image: postgres:16-alpine @@ -41,6 +58,14 @@ services: interval: 5s timeout: 5s retries: 10 + deploy: + resources: + limits: + cpus: '${DEV_POSTGRES_CPUS:-1.0}' + memory: ${DEV_POSTGRES_MEMORY:-512M} + reservations: + cpus: '${DEV_POSTGRES_CPUS_RESERVED:-0.25}' + memory: ${DEV_POSTGRES_MEMORY_RESERVED:-128M} redis: image: redis:7-alpine @@ -53,6 +78,76 @@ services: interval: 5s timeout: 3s retries: 10 + deploy: + resources: + limits: + cpus: '${DEV_REDIS_CPUS:-0.5}' + memory: ${DEV_REDIS_MEMORY:-256M} + reservations: + cpus: '${DEV_REDIS_CPUS_RESERVED:-0.1}' + memory: ${DEV_REDIS_MEMORY_RESERVED:-64M} + + # Local Stellar/Soroban chain (issue #238 — "Local blockchain node"). + # Mirrors the sandbox stack in docker-compose.sandbox.yml so contract + # behaviour is identical between sandbox and devcontainer workflows. + stellar: + image: stellar/stellar-quickstart:latest + restart: unless-stopped + ports: + - '${DEV_STELLAR_RPC_PORT:-8000}:8000' + - '${DEV_STELLAR_CORE_PORT:-7001}:7001' + environment: + SOROBAN_RPC_HOST: 0.0.0.0 + SOROBAN_RPC_PORT: 8000 + PUBNET: 'false' + TESTNET: 'false' + volumes: + # Ledger state survives `down`/`up` so deployed contracts are not lost. + - stellar-data:/opt/stellar + healthcheck: + test: ['CMD', 'curl', '--fail', 'http://localhost:8000/health'] + interval: 10s + timeout: 5s + retries: 10 + start_period: 30s + deploy: + resources: + limits: + cpus: '${DEV_STELLAR_CPUS:-2.0}' + memory: ${DEV_STELLAR_MEMORY:-2G} + reservations: + cpus: '${DEV_STELLAR_CPUS_RESERVED:-0.5}' + memory: ${DEV_STELLAR_MEMORY_RESERVED:-512M} + + # Local EVM chain for the Solidity contracts. Opt-in because the image is + # large and most work only needs Postgres/Redis/Soroban: + # scripts/devcontainer.sh evm + evm: + profiles: ['evm', 'app'] + image: node:22-bookworm-slim + working_dir: /workspaces/agenticpay/contracts + platform: ${DEV_EVM_PLATFORM:-linux/amd64} + command: sh -c "npm install --no-audit --no-fund && npx hardhat node --hostname 0.0.0.0" + ports: + - '${DEV_EVM_PORT:-8545}:8545' + environment: + NODE_ENV: development + HARDHAT_NETWORK: localhost + volumes: + - ..:/workspaces/agenticpay:cached + - node-modules:/workspaces/agenticpay/node_modules + - hardhat-cache:/workspaces/agenticpay/contracts/.hardhat + healthcheck: + test: ['CMD', 'node', '-e', 'require("net").connect(8545).end()'] + interval: 10s + timeout: 5s + retries: 10 + start_period: 60s + deploy: + resources: + limits: + cpus: '${DEV_EVM_CPUS:-1.0}' + memory: ${DEV_EVM_MEMORY:-1G} # One-time dependency install shared by the backend/frontend services. deps: @@ -76,6 +171,8 @@ services: volumes: - ..:/workspaces/agenticpay:cached - node-modules:/workspaces/agenticpay/node_modules + # Persist the Rust/Soroban build cache between restarts. + - contract-target:/workspaces/agenticpay/contracts/target environment: NODE_ENV: development PORT: '3001' @@ -86,8 +183,12 @@ services: QUEUE_ENABLED: 'false' OPENAI_API_KEY: sk-dev-placeholder-replace-me CORS_ALLOWED_ORIGINS: 'http://localhost:3000,http://localhost:3001' + STELLAR_RPC_URL: http://stellar:8000/soroban/rpc + SOROBAN_RPC_URL: http://stellar:8000/soroban/rpc + STELLAR_NETWORK: local ports: - '3001:3001' + - '${DEV_BACKEND_DEBUG_PORT:-9229}:9229' depends_on: deps: condition: service_completed_successfully @@ -95,6 +196,11 @@ services: condition: service_healthy redis: condition: service_healthy + deploy: + resources: + limits: + cpus: '${DEV_BACKEND_CPUS:-2.0}' + memory: ${DEV_BACKEND_MEMORY:-2G} frontend: profiles: ['app'] @@ -118,8 +224,16 @@ services: condition: service_completed_successfully backend: condition: service_started + deploy: + resources: + limits: + cpus: '${DEV_FRONTEND_CPUS:-2.0}' + memory: ${DEV_FRONTEND_MEMORY:-2G} volumes: postgres-data: redis-data: node-modules: + stellar-data: + hardhat-cache: + contract-target: diff --git a/.devcontainer/post-create.sh b/.devcontainer/post-create.sh index e0fa3700..4ee8237c 100755 --- a/.devcontainer/post-create.sh +++ b/.devcontainer/post-create.sh @@ -7,6 +7,21 @@ cd "$ROOT" echo "==> AgenticPay devcontainer post-create" +# Debug configurations and tasks (Issue #238). `.vscode/` is gitignored, so the +# templates live in `.devcontainer/vscode/` and are copied in on create. Existing +# user files are never overwritten. +mkdir -p "$ROOT/.vscode" +for template in "$ROOT"/.devcontainer/vscode/*.json; do + [ -e "$template" ] || continue + target="$ROOT/.vscode/$(basename "$template")" + if [ -e "$target" ]; then + echo "==> Keeping existing .vscode/$(basename "$template")" + else + cp "$template" "$target" + echo "==> Installed .vscode/$(basename "$template")" + fi +done + # Rust WASM target (Soroban contracts) if command -v rustup >/dev/null 2>&1; then echo "==> Adding wasm32-unknown-unknown target" diff --git a/.devcontainer/post-start.sh b/.devcontainer/post-start.sh index a9a4fe36..e65f581c 100755 --- a/.devcontainer/post-start.sh +++ b/.devcontainer/post-start.sh @@ -3,5 +3,9 @@ set -euo pipefail echo "==> Devcontainer ready" -echo " Postgres: postgresql://postgres:postgres@localhost:5432/agenticpay" -echo " Redis: redis://localhost:6379" +echo " Postgres: postgresql://postgres:postgres@localhost:5432/agenticpay" +echo " Redis: redis://localhost:6379" +echo " Soroban RPC: http://localhost:8000/soroban/rpc" +echo " Stellar Core: localhost:7001" +echo " EVM (opt-in): http://localhost:8545 (scripts/devcontainer.sh evm)" +echo " Debug: press F5 (configurations in .vscode/launch.json)" diff --git a/.devcontainer/vscode/launch.json b/.devcontainer/vscode/launch.json new file mode 100644 index 00000000..3bf5fc4c --- /dev/null +++ b/.devcontainer/vscode/launch.json @@ -0,0 +1,77 @@ +{ + // Debug configurations for the devcontainer / local setup — Issue #238. + // Ports 3000/3001/9229 are forwarded by .devcontainer/devcontainer.json. + "version": "0.2.0", + "configurations": [ + { + "name": "Backend: API (debug)", + "type": "node", + "request": "launch", + "runtimeExecutable": "npx", + "runtimeArgs": ["tsx", "watch", "--inspect=0.0.0.0:9229", "src/index.ts"], + "cwd": "${workspaceFolder}/backend", + "console": "integratedTerminal", + "internalConsoleOptions": "neverOpen", + "skipFiles": ["/**"] + }, + { + "name": "Backend: API (no watch)", + "type": "node", + "request": "launch", + "runtimeExecutable": "npx", + "runtimeArgs": ["tsx", "--inspect=0.0.0.0:9229", "src/index.ts"], + "cwd": "${workspaceFolder}/backend", + "console": "integratedTerminal", + "internalConsoleOptions": "neverOpen", + "skipFiles": ["/**"] + }, + { + "name": "Backend: current test file", + "type": "node", + "request": "launch", + "runtimeExecutable": "npx", + "runtimeArgs": ["vitest", "run", "${relativeFile}"], + "cwd": "${workspaceFolder}/backend", + "console": "integratedTerminal", + "internalConsoleOptions": "neverOpen", + "skipFiles": ["/**"] + }, + { + "name": "Frontend: Next.js (debug)", + "type": "node", + "request": "launch", + "runtimeExecutable": "npm", + "runtimeArgs": ["run", "dev", "--workspace=frontend"], + "cwd": "${workspaceFolder}", + "console": "integratedTerminal", + "internalConsoleOptions": "neverOpen", + "autoAttachChildProcesses": true, + "skipFiles": ["/**"] + }, + { + "name": "Contracts: Soroban tests", + "type": "node", + "request": "launch", + "runtimeExecutable": "cargo", + "runtimeArgs": ["test", "--manifest-path", "${workspaceFolder}/contracts/Cargo.toml"], + "cwd": "${workspaceFolder}/contracts", + "console": "integratedTerminal", + "internalConsoleOptions": "neverOpen" + }, + { + "name": "Attach to backend (9229)", + "type": "node", + "request": "attach", + "port": 9229, + "restart": true, + "skipFiles": ["/**"] + } + ], + "compounds": [ + { + "name": "Full stack (backend + frontend)", + "configurations": ["Backend: API (debug)", "Frontend: Next.js (debug)"], + "stopAll": true + } + ] +} diff --git a/.devcontainer/vscode/tasks.json b/.devcontainer/vscode/tasks.json new file mode 100644 index 00000000..e2282786 --- /dev/null +++ b/.devcontainer/vscode/tasks.json @@ -0,0 +1,55 @@ +{ + // Devcontainer stack tasks — Issue #238. + "version": "2.0.0", + "tasks": [ + { + "label": "stack: up", + "type": "shell", + "command": "scripts/devcontainer.sh up", + "problemMatcher": [], + "presentation": { "reveal": "always", "panel": "shared" } + }, + { + "label": "stack: down", + "type": "shell", + "command": "scripts/devcontainer.sh down", + "problemMatcher": [], + "presentation": { "reveal": "always", "panel": "shared" } + }, + { + "label": "stack: status", + "type": "shell", + "command": "scripts/devcontainer.sh ps", + "problemMatcher": [], + "presentation": { "reveal": "always", "panel": "shared" } + }, + { + "label": "stack: logs", + "type": "shell", + "command": "scripts/devcontainer.sh logs", + "problemMatcher": [], + "presentation": { "reveal": "always", "panel": "shared" } + }, + { + "label": "chain: local stellar node", + "type": "shell", + "command": "scripts/devcontainer.sh stellar", + "problemMatcher": [], + "presentation": { "reveal": "always", "panel": "shared" } + }, + { + "label": "chain: local EVM node", + "type": "shell", + "command": "scripts/devcontainer.sh evm", + "problemMatcher": [], + "presentation": { "reveal": "always", "panel": "shared" } + }, + { + "label": "test: backend", + "type": "shell", + "command": "npm run test --workspace=backend", + "problemMatcher": [], + "presentation": { "reveal": "always", "panel": "shared" } + } + ] +} diff --git a/docs/DEVCONTAINER.md b/docs/DEVCONTAINER.md index ea9c60f6..b609a215 100644 --- a/docs/DEVCONTAINER.md +++ b/docs/DEVCONTAINER.md @@ -18,15 +18,21 @@ One-click development environment for AgenticPay with Node.js, Rust, Soroban CLI | Soroban CLI | 21.x | Contract build & deploy | | PostgreSQL | 16 | Application database | | Redis | 7 | Cache & job queues | +| Stellar Quickstart | latest | Local Soroban RPC + Stellar Core | +| Hardhat | local | Local EVM chain (opt-in `evm` profile) | Recommended VS Code extensions are installed automatically (ESLint, Prettier, Tailwind, Playwright, Rust Analyzer, Prisma, OpenAPI, Docker). ## Services -Inside the devcontainer, Postgres and Redis are reachable on `localhost` via Docker Compose networking: +Inside the devcontainer, Postgres, Redis and the local chain are reachable on +`localhost` via Docker Compose networking: - **Postgres:** `postgresql://postgres:postgres@localhost:5432/agenticpay` - **Redis:** `redis://localhost:6379` +- **Soroban RPC:** `http://localhost:8000/soroban/rpc` +- **Stellar Core:** `localhost:7001` +- **EVM (Hardhat):** `http://localhost:8545` (after `scripts/devcontainer.sh evm`) On the host machine (without devcontainer), start the same stack: @@ -58,10 +64,104 @@ docker compose -f .devcontainer/docker-compose.yml --profile app up -d --build | Backend API | http://localhost:3001/api/v1 | | Postgres | `localhost:5432` (postgres/postgres) | | Redis | `localhost:6379` | +| Soroban RPC | http://localhost:8000/soroban/rpc | +| Stellar Core | `localhost:7001` | +| EVM (Hardhat) | http://localhost:8545 | -`scripts/devcontainer.sh` also supports `down`, `logs [service]`, `ps`, +`scripts/devcontainer.sh` also supports `infra` (Postgres + Redis + local chain +only), `stellar`, `evm`, `down`, `reset`, `logs [service]`, `ps`, `restart [service]`, `shell`, and `config` (validate the Compose file). +## Local Blockchain Nodes + +Two chains are available locally so contract work never needs a testnet: + +**Soroban / Stellar (started by default).** The `stellar` service runs +`stellar/stellar-quickstart` in local mode, matching the sandbox stack in +`docker-compose.sandbox.yml` so behaviour is identical whichever workflow you +use. It is a dependency of the devcontainer, and the backend receives +`STELLAR_RPC_URL` / `SOROBAN_RPC_URL` pointing at it. + +```bash +scripts/devcontainer.sh stellar # start just this service +curl http://localhost:8000/health # readiness probe +``` + +**EVM / Hardhat (opt-in).** The `evm` service is behind the `evm` profile +because its image is large and most work does not need it: + +```bash +scripts/devcontainer.sh evm +curl -X POST http://localhost:8545 -H 'Content-Type: application/json' \ + -d '{"jsonrpc":"2.0","id":1,"method":"eth_chainId","params":[]}' +``` + +## Debug Configurations + +Debug configurations ship as tracked templates in `.devcontainer/vscode/`; +`post-create.sh` copies them into `.vscode/` on create (the directory is +gitignored, and existing user files are never overwritten). Press **F5** to use +them: + +| Configuration | What it does | +|---------------|--------------| +| Backend: API (debug) | `tsx watch` with the inspector on port 9229 | +| Backend: API (no watch) | Same, without file watching (better breakpoints) | +| Backend: current test file | Runs the open Vitest file under the debugger | +| Frontend: Next.js (debug) | Next dev server with child-process auto-attach | +| Contracts: Soroban tests | `cargo test` for `contracts/` | +| Attach to backend (9229) | Attach to an already-running backend | + +A **Full stack (backend + frontend)** compound starts both at once. Port 9229 +is forwarded by `devcontainer.json`, so breakpoints also work from the host. +The same directory provides `tasks.json`, exposing the stack and chain commands +as VS Code tasks. Re-run `bash .devcontainer/post-create.sh` to reinstall the +templates after changing them. + +## Resource Allocation Controls + +Every service has CPU/memory limits and reservations in +`.devcontainer/docker-compose.yml`, all overridable by environment variable so +constrained machines can be dialled down without editing the file: + +```bash +DEV_POSTGRES_MEMORY=256M DEV_REDIS_MEMORY=128M \ +DEV_STELLAR_CPUS=1 DEV_BACKEND_MEMORY=1G \ + scripts/devcontainer.sh up +``` + +| Variable | Default | +|----------|---------| +| `DEV_DEVCONTAINER_CPUS` / `DEV_DEVCONTAINER_MEMORY` | `4.0` / `6G` | +| `DEV_POSTGRES_CPUS` / `DEV_POSTGRES_MEMORY` | `1.0` / `512M` | +| `DEV_REDIS_CPUS` / `DEV_REDIS_MEMORY` | `0.5` / `256M` | +| `DEV_STELLAR_CPUS` / `DEV_STELLAR_MEMORY` | `2.0` / `2G` | +| `DEV_BACKEND_CPUS` / `DEV_BACKEND_MEMORY` | `2.0` / `2G` | +| `DEV_FRONTEND_CPUS` / `DEV_FRONTEND_MEMORY` | `2.0` / `2G` | + +`devcontainer.json` also declares `hostRequirements` (4 CPUs / 8 GB RAM / +32 GB disk) so Dev Containers refuses to start on a host that cannot run the +stack instead of failing halfway through. + +## Volume Persistence + +Named volumes keep state across `scripts/devcontainer.sh down` / `up`: + +| Volume | Holds | +|--------|-------| +| `postgres-data` | Database | +| `redis-data` | Cache / queue AOF | +| `stellar-data` | Ledger state — deployed contracts survive restarts | +| `hardhat-cache` | Hardhat compilation cache | +| `node-modules` | Shared install across backend/frontend/deps | +| `contract-target` | Rust build cache for Soroban contracts | + +To wipe everything and start clean (destructive — also drops the database): + +```bash +scripts/devcontainer.sh reset --yes +``` + ## Environment Variables The devcontainer sets safe defaults in `devcontainer.json`. Copy and customize for secrets: @@ -82,6 +182,7 @@ cp backend/.env.example backend/.env # if present 5. Builds Soroban contracts (`contracts/`) 6. Generates OpenAPI documentation 7. Installs Playwright Chromium for E2E tests +8. Installs the `.vscode/` debug + task templates from `.devcontainer/vscode/` Re-run manually if needed: @@ -91,7 +192,7 @@ bash .devcontainer/post-create.sh ## ARM (Apple Silicon) & Windows Notes -- **ARM/M1:** Images use multi-arch bases (`bookworm` Node image). Soroban CLI compiles from source on first create; allow extra time. +- **ARM/M1:** Images use multi-arch bases (`bookworm` Node image). Soroban CLI compiles from source on first create; allow extra time. `postgres`, `redis` and `stellar` are arm64-native; the EVM node defaults to `linux/amd64` (emulated) and can be pinned with `DEV_EVM_PLATFORM=linux/arm64`. - **Windows:** Use WSL2 backend for Docker. Open the repo from the WSL filesystem (`\\wsl$\...`) to avoid slow bind mounts. If file watching is unreliable, set `"mountType": "delegated"` in devcontainer overrides. ## Running the App diff --git a/scripts/devcontainer.sh b/scripts/devcontainer.sh index d2f1b4ec..e61048bd 100755 --- a/scripts/devcontainer.sh +++ b/scripts/devcontainer.sh @@ -1,19 +1,24 @@ #!/usr/bin/env bash -# Devcontainer orchestrator — Issue #794 +# Devcontainer orchestrator — Issue #794, extended in Issue #238. # -# Brings up the full local stack (Postgres, Redis, backend, frontend) with a -# single command, without opening VS Code. For the IDE-driven flow use -# "Dev Containers: Reopen in Container" and then run the dev servers inside. +# Brings up the full local stack (Postgres, Redis, local chains, backend, +# frontend) with a single command, without opening VS Code. For the IDE-driven +# flow use "Dev Containers: Reopen in Container" and then run the dev servers +# inside (or press F5 for the debug configurations in .vscode/launch.json). set -euo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" cd "$ROOT" COMPOSE_FILE=".devcontainer/docker-compose.yml" -PROFILE="app" +INFRA_SERVICES="postgres redis stellar" compose() { - docker compose -f "$COMPOSE_FILE" --profile "$PROFILE" "$@" + docker compose -f "$COMPOSE_FILE" "$@" +} + +compose_app() { + docker compose -f "$COMPOSE_FILE" --profile app "$@" } usage() { @@ -21,19 +26,29 @@ usage() { Devcontainer stack orchestrator Usage: - scripts/devcontainer.sh up Build and start Postgres, Redis, backend, frontend - scripts/devcontainer.sh down Stop and remove the stack - scripts/devcontainer.sh logs [svc] Tail logs (optionally for one service) - scripts/devcontainer.sh ps Show service status + scripts/devcontainer.sh up Start Postgres, Redis, local chain, backend, frontend + scripts/devcontainer.sh infra Start only Postgres, Redis and the local Stellar node + scripts/devcontainer.sh stellar Start just the local Soroban/Stellar node + scripts/devcontainer.sh evm Start the local Hardhat EVM node (opt-in profile) + scripts/devcontainer.sh down Stop and remove the stack (keeps volumes) + scripts/devcontainer.sh reset Stop and delete the stack AND its volumes (destructive) + scripts/devcontainer.sh logs [svc] Tail logs (optionally for one service) + scripts/devcontainer.sh ps Show service status scripts/devcontainer.sh restart [svc] - scripts/devcontainer.sh shell Open a shell in the devcontainer service - scripts/devcontainer.sh config Validate the compose file + scripts/devcontainer.sh shell Open a shell in the devcontainer service + scripts/devcontainer.sh config Validate the compose file + +Resource allocation controls (issue #238) — override per service before running: + DEV_POSTGRES_MEMORY=1G DEV_STELLAR_CPUS=2 DEV_BACKEND_MEMORY=4G scripts/devcontainer.sh up After `up`: - Frontend : http://localhost:3000 - Backend : http://localhost:3001/api/v1 - Postgres : localhost:5432 (postgres/postgres) - Redis : localhost:6379 + Frontend : http://localhost:3000 + Backend : http://localhost:3001/api/v1 + Postgres : localhost:5432 (postgres/postgres) + Redis : localhost:6379 + Soroban RPC: http://localhost:8000/soroban/rpc + Stellar Core: localhost:7001 + EVM (Hardhat): http://localhost:8545 (after `scripts/devcontainer.sh evm`) EOF } @@ -42,30 +57,52 @@ shift || true case "$cmd" in up) - compose up -d --build - echo "Stack is up. Frontend: http://localhost:3000 Backend: http://localhost:3001/api/v1" + compose_app up -d --build + echo "Stack is up." + echo " Frontend : http://localhost:3000" + echo " Backend : http://localhost:3001/api/v1" + echo " Soroban RPC: http://localhost:8000/soroban/rpc" + ;; + infra) + compose up -d $INFRA_SERVICES + ;; + stellar) + compose up -d stellar + echo "Local Soroban RPC: http://localhost:8000/soroban/rpc" + ;; + evm) + compose_app --profile evm up -d evm deps + echo "Local EVM RPC: http://localhost:8545" ;; down) - compose down + compose_app down + ;; + reset) + if [ "${1:-}" != "--yes" ]; then + echo "This deletes Postgres, Redis, Stellar and build-cache volumes." + echo "Re-run with: scripts/devcontainer.sh reset --yes" + exit 1 + fi + compose_app --profile evm down -v ;; logs) - compose logs -f "${1:-}" + compose_app logs -f "${1:-}" ;; ps) - compose ps + compose_app --profile evm ps ;; restart) if [ -n "${1:-}" ]; then - compose restart "$1" + compose_app restart "$1" else - compose restart + compose_app restart fi ;; shell) compose exec devcontainer bash ;; config) - compose config + compose_app --profile evm config ;; *) usage