Local dev stack improvements
- Extend docker-compose.dev.yml with optional monitoring profile (Prometheus, Grafana, Loki) via --profile monitoring - Align dev PostgreSQL with production: pg_stat_statements + init scripts - Add scripts/seed.ts with idempotent Berlin test data (user, route, activity) - Add pnpm db:seed and pnpm dev:reset scripts - Simplify CI e2e job: replace manual docker run + BRouter setup with docker compose up --wait; add db:seed step - Improve scripts/dev.sh: Docker check, --wait health checks, --monitoring flag, seed step - Add scripts/reset-dev.sh to wipe and restart the local stack - Add .env.development.example with documented local defaults Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
d7b3c7c1a5
commit
10e0a8d41a
10 changed files with 209 additions and 105 deletions
|
|
@ -6,50 +6,59 @@ PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
|
|||
|
||||
cd "$PROJECT_DIR"
|
||||
|
||||
# Parse flags
|
||||
MONITORING=false
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--monitoring) MONITORING=true ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Check Docker is running
|
||||
if ! docker info > /dev/null 2>&1; then
|
||||
echo "Error: Docker is not running. Please start Docker and try again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "=== trails.cool dev environment ==="
|
||||
echo ""
|
||||
|
||||
# 1. Start Docker services
|
||||
echo "Starting Docker services..."
|
||||
docker compose -f docker-compose.dev.yml up -d
|
||||
if [ "$MONITORING" = "true" ]; then
|
||||
echo "Starting Docker services (with monitoring)..."
|
||||
docker compose -f docker-compose.dev.yml --profile monitoring up -d --wait
|
||||
else
|
||||
echo "Starting Docker services..."
|
||||
docker compose -f docker-compose.dev.yml up -d --wait
|
||||
fi
|
||||
echo "✓ Services are ready"
|
||||
|
||||
# 2. Wait for PostgreSQL
|
||||
echo "Waiting for PostgreSQL..."
|
||||
until docker compose -f docker-compose.dev.yml exec -T postgres pg_isready -U trails > /dev/null 2>&1; do
|
||||
sleep 1
|
||||
done
|
||||
echo "✓ PostgreSQL is ready"
|
||||
|
||||
# 3. Push database schema
|
||||
# 2. Push database schema
|
||||
echo "Pushing database schema..."
|
||||
pnpm db:push 2>&1 | tail -3
|
||||
echo "✓ Database schema up to date"
|
||||
|
||||
# 3. Seed database
|
||||
echo "Seeding database..."
|
||||
pnpm db:seed
|
||||
echo "✓ Database seeded"
|
||||
|
||||
# 4. Download BRouter segments if needed
|
||||
echo "Checking BRouter segments..."
|
||||
"$SCRIPT_DIR/download-dev-segments.sh"
|
||||
|
||||
# 5. Wait for BRouter (if segments are available)
|
||||
if docker compose -f docker-compose.dev.yml ps brouter --format '{{.State}}' 2>/dev/null | grep -q "running"; then
|
||||
echo "Waiting for BRouter..."
|
||||
for i in $(seq 1 30); do
|
||||
if curl -sf http://localhost:17777/brouter?lonlats=13.4,52.5\|13.5,52.5\&profile=trekking\&format=geojson > /dev/null 2>&1; then
|
||||
echo "✓ BRouter is ready"
|
||||
break
|
||||
fi
|
||||
if [ "$i" = "30" ]; then
|
||||
echo "⚠ BRouter not responding (segments may still be loading). Continuing..."
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=== Starting apps ==="
|
||||
echo " Journal: http://localhost:3000"
|
||||
echo " Planner: http://localhost:3001"
|
||||
echo " BRouter: http://localhost:17777"
|
||||
if [ "$MONITORING" = "true" ]; then
|
||||
echo " Grafana: http://localhost:3002"
|
||||
echo " Prometheus: http://localhost:9090"
|
||||
fi
|
||||
echo ""
|
||||
echo " Tip: pnpm dev:reset to wipe all data and start fresh"
|
||||
echo ""
|
||||
|
||||
# 6. Start both apps with turbo
|
||||
# 5. Start both apps with turbo
|
||||
exec pnpm dev
|
||||
|
|
|
|||
26
scripts/reset-dev.sh
Executable file
26
scripts/reset-dev.sh
Executable file
|
|
@ -0,0 +1,26 @@
|
|||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
PROJECT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
cd "$PROJECT_DIR"
|
||||
|
||||
if ! docker info > /dev/null 2>&1; then
|
||||
echo "Error: Docker is not running. Please start Docker and try again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "=== Resetting dev environment ==="
|
||||
echo "This will stop all containers and wipe all local data volumes."
|
||||
echo ""
|
||||
|
||||
read -r -p "Are you sure? [y/N] " confirm
|
||||
if [[ "$confirm" != "y" && "$confirm" != "Y" ]]; then
|
||||
echo "Aborted."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Stopping containers and removing volumes..."
|
||||
docker compose -f docker-compose.dev.yml --profile monitoring down -v 2>/dev/null || \
|
||||
docker compose -f docker-compose.dev.yml down -v
|
||||
|
||||
echo "✓ Done. Run 'pnpm dev:full' to start fresh."
|
||||
72
scripts/seed.ts
Normal file
72
scripts/seed.ts
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
import { createDb } from "../packages/db/src/index.ts";
|
||||
import { users, routes, activities } from "../packages/db/src/schema/journal.ts";
|
||||
|
||||
const db = createDb();
|
||||
|
||||
const SEED_USER_ID = "seed-user-dev";
|
||||
const SEED_ROUTE_ID = "seed-route-berlin";
|
||||
const SEED_ACTIVITY_ID = "seed-activity-berlin";
|
||||
|
||||
// Minimal GPX for a short Berlin route (Tiergarten area)
|
||||
const BERLIN_GPX = `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gpx version="1.1" creator="trails.cool" xmlns="http://www.topografix.com/GPX/1/1">
|
||||
<trk>
|
||||
<name>Tiergarten Loop</name>
|
||||
<trkseg>
|
||||
<trkpt lat="52.5145" lon="13.3501"><ele>34</ele></trkpt>
|
||||
<trkpt lat="52.5150" lon="13.3560"><ele>35</ele></trkpt>
|
||||
<trkpt lat="52.5170" lon="13.3620"><ele>35</ele></trkpt>
|
||||
<trkpt lat="52.5190" lon="13.3580"><ele>36</ele></trkpt>
|
||||
<trkpt lat="52.5200" lon="13.3510"><ele>35</ele></trkpt>
|
||||
<trkpt lat="52.5145" lon="13.3501"><ele>34</ele></trkpt>
|
||||
</trkseg>
|
||||
</trk>
|
||||
</gpx>`;
|
||||
|
||||
await db
|
||||
.insert(users)
|
||||
.values({
|
||||
id: SEED_USER_ID,
|
||||
email: "dev@trails.cool",
|
||||
username: "devuser",
|
||||
displayName: "Dev User",
|
||||
domain: "localhost:3000",
|
||||
profileVisibility: "public",
|
||||
})
|
||||
.onConflictDoNothing();
|
||||
|
||||
await db
|
||||
.insert(routes)
|
||||
.values({
|
||||
id: SEED_ROUTE_ID,
|
||||
ownerId: SEED_USER_ID,
|
||||
name: "Tiergarten Loop",
|
||||
description: "A short loop through Tiergarten for local dev testing.",
|
||||
gpx: BERLIN_GPX,
|
||||
routingProfile: "trekking",
|
||||
distance: 1200,
|
||||
elevationGain: 5,
|
||||
elevationLoss: 5,
|
||||
visibility: "public",
|
||||
})
|
||||
.onConflictDoNothing();
|
||||
|
||||
await db
|
||||
.insert(activities)
|
||||
.values({
|
||||
id: SEED_ACTIVITY_ID,
|
||||
ownerId: SEED_USER_ID,
|
||||
routeId: SEED_ROUTE_ID,
|
||||
name: "Morning walk in Tiergarten",
|
||||
gpx: BERLIN_GPX,
|
||||
startedAt: new Date("2024-06-01T08:00:00Z"),
|
||||
duration: 1800,
|
||||
distance: 1200,
|
||||
elevationGain: 5,
|
||||
elevationLoss: 5,
|
||||
visibility: "public",
|
||||
})
|
||||
.onConflictDoNothing();
|
||||
|
||||
console.log("✓ Seed complete");
|
||||
process.exit(0);
|
||||
Loading…
Add table
Add a link
Reference in a new issue