refactor: consolidate infra management into justfile + add mobile-dev (#797)

This commit is contained in:
Will Pfleger
2026-05-29 18:26:24 -04:00
committed by GitHub
parent 995189c223
commit 2a03851527
10 changed files with 100 additions and 137 deletions
+7 -1
View File
@@ -244,7 +244,7 @@ organized under `desktop/src/features/`. Biome handles linting and formatting.
```bash
just desktop-dev # web-only dev server (faster iteration)
just desktop-app # full Tauri app with native shell
just dev # full Tauri app with native shell
```
### Workspace Switching
@@ -316,6 +316,12 @@ flutter test
Or from repo root: `just mobile-fmt` (auto-fix), `just mobile-check` (lint + fmt check), `just mobile-test` (tests).
To run the app locally (starts Docker, relay, iOS simulator automatically):
```bash
just mobile-dev
```
### Testing Conventions
- Prefer **widget tests** over unit tests for UI components — test the
+4 -7
View File
@@ -23,16 +23,13 @@ Connect any NIP-29 client straight to the relay.
### Quick Start
```bash
# 1. Start infrastructure
docker compose up -d
# 2. (Optional) Enable pubkey allowlist — must be set BEFORE relay startup
# 1. (Optional) Enable pubkey allowlist — must be set BEFORE relay startup
export SPROUT_PUBKEY_ALLOWLIST=true
# 3. Start the relay (runs migrations automatically)
cargo run -p sprout-relay & # relay on :3000
# 2. Start the relay (auto-starts Docker services and runs migrations)
just relay & # relay on :3000
# 4. Add a pubkey to the allowlist (if enabled)
# 3. Add a pubkey to the allowlist (if enabled)
# Insert directly — there is no CLI command for this yet.
PGPASSWORD=sprout_dev psql -h localhost -U sprout -d sprout -c \
"INSERT INTO pubkey_allowlist (pubkey) VALUES (decode('<64-char-hex-pubkey>', 'hex'))"
+2 -2
View File
@@ -8,7 +8,7 @@ just test # unit + integration (starts Docker if needed)
```
`just test` runs unit tests plus integration tests against Postgres and Redis
(started via `docker compose`). Neither task runs the E2E suites in
(started automatically if not already running). Neither task runs the E2E suites in
`sprout-test-client` — those are marked `#[ignore]` and require a running relay:
```bash
@@ -264,7 +264,7 @@ Replies are kind:9 in the same channel; `sprout messages thread --channel <id>
## Configuration reference
The relay reads all configuration from environment variables. Defaults work
out of the box with `docker compose up`. Common overrides:
out of the box with `just setup` or `just relay`. Common overrides:
| Variable | Default | Notes |
|-----------------------------------|-----------------------------|-------|
+1 -2
View File
@@ -13,8 +13,7 @@ Supports any agent that speaks [ACP](https://agentclientprotocol.com/) over stdi
## Prerequisites
- A running Sprout relay (`just relay` or a hosted instance)
- Docker services up (`docker compose up -d`) if running locally
- A running Sprout relay (`just relay` starts Docker services automatically, or use a hosted instance)
- A Nostr keypair for the agent (see [Generating Keys](#generating-keys))
Build:
+1 -1
View File
@@ -17,7 +17,7 @@ docker compose ps
# sprout-typesense healthy
```
If not running: `./scripts/dev-setup.sh` from the repo root.
If not running: `just setup` from the repo root.
Tools: `jq`, `curl`, Rust toolchain.
+1 -2
View File
@@ -17,8 +17,7 @@ Client (NIP-28) ←→ sprout-proxy :4869 ←→ sprout-relay :3000
### 1. Start infrastructure and relay
```bash
just setup # Docker: Postgres + Redis
just relay # Relay on :3000
just relay # starts Docker services + migrations automatically
```
### 2. Mint a proxy API token
+73 -19
View File
@@ -122,6 +122,40 @@ _ensure-sidecar-stubs:
touch "desktop/src-tauri/binaries/${bin}-${TARGET}"
done
# Ensure Docker dev services (Postgres, Redis, etc.) are running and healthy
_ensure-services:
#!/usr/bin/env bash
set -euo pipefail
pg=$(docker inspect --format '{{"{{"}}.State.Health.Status{{"}}"}}' sprout-postgres 2>/dev/null || echo "not_found")
redis=$(docker inspect --format '{{"{{"}}.State.Health.Status{{"}}"}}' sprout-redis 2>/dev/null || echo "not_found")
if [[ "$pg" == "healthy" && "$redis" == "healthy" ]]; then
echo "Services already healthy"
exit 0
fi
echo "Starting services..."
docker compose up -d || true
echo -n "Waiting for services"
for i in $(seq 1 40); do
pg=$(docker inspect --format '{{"{{"}}.State.Health.Status{{"}}"}}' sprout-postgres 2>/dev/null || echo "not_found")
redis=$(docker inspect --format '{{"{{"}}.State.Health.Status{{"}}"}}' sprout-redis 2>/dev/null || echo "not_found")
if [[ "$pg" == "healthy" && "$redis" == "healthy" ]]; then
echo " ready"
exit 0
fi
echo -n "."
sleep 3
done
echo " timed out"
exit 1
# Apply database migrations if pgschema is available
_ensure-migrations: _ensure-services
#!/usr/bin/env bash
set -euo pipefail
if [[ -x bin/pgschema && -f schema/schema.sql ]]; then
bin/pgschema apply --file schema/schema.sql --auto-approve || true
fi
# Run clippy on the desktop Tauri Rust crate
desktop-tauri-clippy: _ensure-sidecar-stubs
cargo clippy --manifest-path {{desktop_tauri_manifest}} --all-targets -- -D warnings
@@ -153,7 +187,7 @@ desktop-release-build target="aarch64-apple-darwin":
desktop-ci: desktop-check desktop-test desktop-tauri-fmt-check desktop-build desktop-tauri-check desktop-tauri-test
# Seed deterministic channel data for desktop Playwright tests
desktop-e2e-seed:
desktop-e2e-seed: _ensure-migrations
./scripts/setup-desktop-test-data.sh
# Run desktop browser smoke tests
@@ -161,7 +195,7 @@ desktop-e2e-smoke:
cd {{desktop_dir}} && pnpm test:e2e:smoke
# Run desktop relay-backed e2e tests
desktop-e2e-integration:
desktop-e2e-integration: _ensure-migrations
cd {{desktop_dir}} && pnpm test:e2e:integration
# Run all checks suitable for CI / pre-push (no infra needed)
@@ -188,12 +222,12 @@ test-integration:
# ─── Run ──────────────────────────────────────────────────────────────────────
# Start the relay server
relay:
# Start the relay server (auto-starts Docker services if needed)
relay: _ensure-migrations
cargo run -p sprout-relay
# Start the relay with the built web UI served from it
relay-web:
relay-web: _ensure-migrations
#!/usr/bin/env bash
set -euo pipefail
[[ -d node_modules ]] || pnpm install
@@ -201,7 +235,7 @@ relay-web:
SPROUT_WEB_DIR=./web/dist cargo run -p sprout-relay
# Start the relay server in release mode
relay-release:
relay-release: _ensure-migrations
cargo run -p sprout-relay --release
# Start sprout-proxy (dev mode)
@@ -248,10 +282,6 @@ desktop-dev:
echo "Starting frontend dev server on Vite port ${SPROUT_VITE_PORT}, relay ${SPROUT_RELAY_URL}"
pnpm exec vite --port "${SPROUT_VITE_PORT}" --strictPort
# Run the desktop Tauri app (alias for dev)
desktop-app *ARGS:
just dev {{ARGS}}
# ─── Web ─────────────────────────────────────────────────────────────────────
# Run the web frontend dev server (port derived from worktree to avoid collisions)
@@ -266,14 +296,6 @@ web:
cd {{web_dir}}
pnpm exec vite --port "${VITE_PORT}" --strictPort
# Install web JS dependencies (pnpm workspace — installs all packages from root)
web-install:
pnpm install
# Install web JS dependencies reproducibly for CI (pnpm workspace)
web-install-ci:
pnpm install --frozen-lockfile
# Run web lint and format checks
web-check:
cd {{web_dir}} && pnpm check
@@ -318,10 +340,42 @@ mobile-check:
mobile-test:
unset GIT_DIR GIT_WORK_TREE; cd {{mobile_dir}} && flutter test
# Run the mobile app on iOS simulator (starts infra + relay automatically)
mobile-dev:
#!/usr/bin/env bash
set -euo pipefail
just _ensure-migrations
# Start relay in background if not already running
RELAY_PID=""
if ! lsof -i :3000 -sTCP:LISTEN -t &>/dev/null; then
echo "Starting relay in background (log: /tmp/sprout-relay.log)..."
cargo run -p sprout-relay &>/tmp/sprout-relay.log &
RELAY_PID=$!
trap 'if [[ -n "$RELAY_PID" ]]; then kill "$RELAY_PID" 2>/dev/null || true; fi' EXIT
echo -n "Waiting for relay"
for _ in $(seq 1 30); do
lsof -i :3000 -sTCP:LISTEN -t &>/dev/null && break
echo -n "."
sleep 3
done
echo " ready"
else
echo "Relay already running on :3000"
fi
# Open iOS simulator if not already running
if ! pgrep -x Simulator &>/dev/null; then
open -a Simulator
sleep 3
fi
# Run Flutter
cd {{mobile_dir}}
unset GIT_DIR GIT_WORK_TREE
flutter run
# ─── Database ─────────────────────────────────────────────────────────────────
# Apply schema migrations via pgschema
migrate:
migrate: _ensure-services
./bin/pgschema apply --file schema/schema.sql --auto-approve
# ─── Utilities ────────────────────────────────────────────────────────────────
+5 -1
View File
@@ -12,7 +12,11 @@ flutter pub get
## Run
```bash
flutter run
# From repo root (recommended — starts Docker, relay, and simulator):
just mobile-dev
# Direct (requires services and relay already running):
cd mobile && flutter run
```
## Checks
+3 -49
View File
@@ -11,7 +11,6 @@ set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
TIMEOUT=120 # seconds to wait for services to become healthy
# Colors
RED='\033[0;31m'
@@ -71,53 +70,8 @@ load_env
# ---- Start services ---------------------------------------------------------
log "Starting services..."
docker compose up -d
# ---- Wait for healthy -------------------------------------------------------
wait_healthy() {
local service="$1"
local container="$2"
local elapsed=0
local interval=3
log "Waiting for ${service} to be healthy..."
while true; do
local status
status=$(docker inspect --format='{{.State.Health.Status}}' "${container}" 2>/dev/null || echo "not_found")
case "${status}" in
healthy)
success "${service} is healthy"
return 0
;;
unhealthy)
error "${service} is unhealthy. Check logs: docker logs ${container}"
return 1
;;
not_found)
error "Container ${container} not found"
return 1
;;
esac
if [[ ${elapsed} -ge ${TIMEOUT} ]]; then
error "Timed out waiting for ${service} (${TIMEOUT}s). Check: docker logs ${container}"
return 1
fi
sleep "${interval}"
elapsed=$((elapsed + interval))
echo -n "."
done
}
echo ""
wait_healthy "Postgres" "sprout-postgres"
wait_healthy "Redis" "sprout-redis"
wait_healthy "Typesense" "sprout-typesense"
echo ""
log "Starting services and waiting for health..."
"${REPO_ROOT}/bin/just" _ensure-services
# ---- Run migrations ---------------------------------------------------------
@@ -204,7 +158,7 @@ if [[ -d "${WEB_DIR}" ]]; then
success "Web dependencies installed"
else
warn "pnpm not found — skipping web dependency install."
warn "Run '. ./bin/activate-hermit' to get pnpm, then 'just web-install'."
warn "Run '. ./bin/activate-hermit' to get pnpm, then 'just desktop-install'."
fi
else
warn "Web directory not found at ${WEB_DIR} — skipping."
+3 -53
View File
@@ -13,7 +13,6 @@ set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
MODE="${1:-all}"
TIMEOUT=60 # seconds to wait for services if starting them
# Colors
RED='\033[0;31m'
@@ -72,57 +71,8 @@ run_test_step() {
# ---- Check / start infra (for integration tests) ----------------------------
services_healthy() {
local pg_ok redis_ok
pg_ok=$(docker inspect --format='{{.State.Health.Status}}' sprout-postgres 2>/dev/null || echo "not_found")
redis_ok=$(docker inspect --format='{{.State.Health.Status}}' sprout-redis 2>/dev/null || echo "not_found")
[[ "${pg_ok}" == "healthy" && "${redis_ok}" == "healthy" ]]
}
ensure_services() {
if services_healthy; then
success "Services already healthy"
return 0
fi
warn "Services not running — starting them..."
docker compose up -d
local elapsed=0
local interval=3
while ! services_healthy; do
if [[ ${elapsed} -ge ${TIMEOUT} ]]; then
error "Timed out waiting for services (${TIMEOUT}s)"
return 1
fi
sleep "${interval}"
elapsed=$((elapsed + interval))
echo -n "."
done
echo ""
success "Services healthy"
# Ensure migrations are current
ensure_migrations
}
ensure_migrations() {
log "Ensuring migrations are current..."
local pgschema="${REPO_ROOT}/bin/pgschema"
local schema_file="${REPO_ROOT}/schema/schema.sql"
if [[ ! -f "${schema_file}" ]]; then
warn "No schema.sql. Skipping."
return 0
fi
if [[ -x "${pgschema}" ]]; then
"${pgschema}" apply --file "${schema_file}" --auto-approve 2>/dev/null \
&& success "Migrations current" \
|| warn "pgschema apply failed — DB may be out of date"
else
warn "pgschema not found at ${pgschema}. Schema may be out of date."
fi
ensure_infra() {
"${REPO_ROOT}/bin/just" _ensure-migrations
}
# ---- Unit tests (no infra needed) -------------------------------------------
@@ -142,7 +92,7 @@ run_unit_tests() {
run_integration_tests() {
section "Integration Tests (requires running services)"
ensure_services
ensure_infra
run_test_step "sprout-db tests" \
cargo test -p sprout-db -- --nocapture