#!/bin/bash # Deploy LinkML Schema to PostgreSQL Database # # This script: # 1. Runs the SQL migration to create LinkML tables # 2. Syncs the LinkML schema files to the server # 3. Runs the Python loader to populate the database # 4. Restarts the Postgres API service # # Usage: ./deploy-linkml.sh [--skip-migration] [--skip-sync] [--skip-load] set -e # Configuration SERVER="91.98.224.44" REMOTE_USER="root" PROJECT_ROOT="$(cd "$(dirname "$0")/.." && pwd)" LINKML_DIR="$PROJECT_ROOT/schemas/20251121/linkml" SQL_DIR="$PROJECT_ROOT/infrastructure/sql" SCRIPTS_DIR="$PROJECT_ROOT/scripts" # Parse arguments SKIP_MIGRATION=false SKIP_SYNC=false SKIP_LOAD=false for arg in "$@"; do case $arg in --skip-migration) SKIP_MIGRATION=true ;; --skip-sync) SKIP_SYNC=true ;; --skip-load) SKIP_LOAD=true ;; --help|-h) echo "Usage: $0 [--skip-migration] [--skip-sync] [--skip-load]" echo "" echo "Options:" echo " --skip-migration Skip running SQL migration" echo " --skip-sync Skip syncing LinkML files to server" echo " --skip-load Skip running Python loader" exit 0 ;; esac done echo "═══════════════════════════════════════════════════════════════" echo " LinkML Schema Deployment to PostgreSQL" echo "═══════════════════════════════════════════════════════════════" echo "" echo "Server: $SERVER" echo "LinkML Source: $LINKML_DIR" echo "" # Check SSH connectivity echo "🔗 Testing SSH connection..." if ! ssh -o ConnectTimeout=5 "$REMOTE_USER@$SERVER" "echo 'Connected'" 2>/dev/null; then echo "❌ Cannot connect to $SERVER" exit 1 fi echo " ✅ Connected" echo "" # Step 1: Run SQL migration if [ "$SKIP_MIGRATION" = false ]; then echo "📦 Step 1: Running SQL migration..." if [ -f "$SQL_DIR/001_linkml_schema.sql" ]; then # Copy migration file to server scp "$SQL_DIR/001_linkml_schema.sql" "$REMOTE_USER@$SERVER:/tmp/" # Run migration ssh "$REMOTE_USER@$SERVER" "sudo -u postgres psql -d glam -f /tmp/001_linkml_schema.sql" echo " ✅ Migration complete" else echo " ⚠️ Migration file not found: $SQL_DIR/001_linkml_schema.sql" fi echo "" else echo "⏭️ Skipping SQL migration" echo "" fi # Step 2: Sync LinkML files if [ "$SKIP_SYNC" = false ]; then echo "📁 Step 2: Syncing LinkML schema files..." rsync -avz --progress --delete \ --include="*.yaml" \ --include="*/" \ --exclude="__pycache__" \ --exclude=".DS_Store" \ "$LINKML_DIR/" \ "$REMOTE_USER@$SERVER:/mnt/data/linkml/" echo " ✅ Sync complete" echo "" else echo "⏭️ Skipping LinkML file sync" echo "" fi # Step 3: Sync and run Python loader if [ "$SKIP_LOAD" = false ]; then echo "🐍 Step 3: Running Python loader..." # Copy loader script to server scp "$SCRIPTS_DIR/load_linkml_to_postgres.py" "$REMOTE_USER@$SERVER:/tmp/" # Install dependencies if needed and run loader ssh "$REMOTE_USER@$SERVER" << 'EOF' cd /var/lib/glam/api # Activate virtual environment source venv/bin/activate # Install dependencies if needed pip install pyyaml asyncpg --quiet # Run loader export DATABASE_URL="postgresql://glam_api:glam_secret_2025@localhost:5432/glam" python /tmp/load_linkml_to_postgres.py \ --version 20251121 \ --schema-dir /mnt/data/linkml \ --schema-name heritage_custodian EOF echo " ✅ Loader complete" echo "" else echo "⏭️ Skipping Python loader" echo "" fi # Step 4: Sync updated API code and restart service echo "🔄 Step 4: Updating Postgres API..." # Copy updated main.py to the correct location scp "$PROJECT_ROOT/backend/postgres/main.py" "$REMOTE_USER@$SERVER:/opt/glam-backend/postgres/main.py" # Restart the service ssh "$REMOTE_USER@$SERVER" "systemctl restart glam-postgres-api" echo " ✅ API updated" echo "" # Step 5: Verify deployment echo "🔍 Step 5: Verifying deployment..." # Check if tables exist TABLES=$(ssh "$REMOTE_USER@$SERVER" "sudo -u postgres psql -d glam -t -c \"SELECT COUNT(*) FROM information_schema.tables WHERE table_name LIKE 'linkml_%'\"" | tr -d ' ') echo " LinkML tables: $TABLES" # Check if data is loaded CLASSES=$(ssh "$REMOTE_USER@$SERVER" "sudo -u postgres psql -d glam -t -c \"SELECT COUNT(*) FROM linkml_classes\" 2>/dev/null || echo '0'" | tr -d ' ') SLOTS=$(ssh "$REMOTE_USER@$SERVER" "sudo -u postgres psql -d glam -t -c \"SELECT COUNT(*) FROM linkml_slots\" 2>/dev/null || echo '0'" | tr -d ' ') ENUMS=$(ssh "$REMOTE_USER@$SERVER" "sudo -u postgres psql -d glam -t -c \"SELECT COUNT(*) FROM linkml_enums\" 2>/dev/null || echo '0'" | tr -d ' ') echo " Classes loaded: $CLASSES" echo " Slots loaded: $SLOTS" echo " Enums loaded: $ENUMS" echo "" echo "═══════════════════════════════════════════════════════════════" echo " Deployment Complete!" echo "═══════════════════════════════════════════════════════════════" echo "" echo "API Endpoints:" echo " https://bronhouder.nl/api/postgres/linkml/versions" echo " https://bronhouder.nl/api/postgres/linkml/classes" echo " https://bronhouder.nl/api/postgres/linkml/slots" echo " https://bronhouder.nl/api/postgres/linkml/enums" echo " https://bronhouder.nl/api/postgres/linkml/search?q=Custodian" echo " https://bronhouder.nl/api/postgres/linkml/hierarchy" echo "" echo "Test with:" echo " curl https://bronhouder.nl/api/postgres/linkml/versions" echo ""