#!/bin/bash # # Dataflow Deploy Script # First run: creates DB user/database, deploys schema, builds UI, installs service # Subsequent runs: updates functions, rebuilds UI, restarts service # set -e SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cd "$SCRIPT_DIR" echo "Dataflow Deploy" echo "===============" echo "" # ── First-time setup ────────────────────────────────────────────────────────── if [ ! -f .env ]; then echo "No .env found — running first-time setup." echo "" # Admin credentials (needed to create user/database) echo "PostgreSQL Admin Credentials" read -p " Admin username [postgres]: " ADMIN_USER; ADMIN_USER=${ADMIN_USER:-postgres} read -s -p " Admin password: " ADMIN_PASS; echo "" echo "" # App credentials echo "Application Database" read -p " Host [localhost]: " DB_HOST; DB_HOST=${DB_HOST:-localhost} read -p " Port [5432]: " DB_PORT; DB_PORT=${DB_PORT:-5432} read -p " Database name [dataflow]: " DB_NAME; DB_NAME=${DB_NAME:-dataflow} read -p " App username [dataflow]: " DB_USER; DB_USER=${DB_USER:-dataflow} read -s -p " App password: " DB_PASSWORD; echo "" echo "" # API config echo "API Configuration" read -p " Port [3020]: " API_PORT; API_PORT=${API_PORT:-3020} read -p " Environment [production]: " NODE_ENV; NODE_ENV=${NODE_ENV:-production} echo "" # Install Node dependencies echo "Installing Node.js dependencies..." npm install --prefix . --omit=dev -q cd ui && npm install -q && cd .. echo "✓ Dependencies installed" echo "" # Test admin connection echo "Testing admin connection..." export PGPASSWORD="$ADMIN_PASS" if ! psql -U "$ADMIN_USER" -h "$DB_HOST" -p "$DB_PORT" -d postgres -c '\q' 2>/dev/null; then echo "✗ Cannot connect as $ADMIN_USER — check credentials" exit 1 fi echo "✓ Admin connection OK" # Create app user if psql -U "$ADMIN_USER" -h "$DB_HOST" -p "$DB_PORT" -d postgres -tAc \ "SELECT 1 FROM pg_roles WHERE rolname='$DB_USER'" | grep -q 1; then echo "✓ User '$DB_USER' already exists" else psql -U "$ADMIN_USER" -h "$DB_HOST" -p "$DB_PORT" -d postgres \ -c "CREATE USER $DB_USER WITH PASSWORD '$DB_PASSWORD';" > /dev/null echo "✓ User '$DB_USER' created" fi # Create database if psql -U "$ADMIN_USER" -h "$DB_HOST" -p "$DB_PORT" -lqt \ | cut -d'|' -f1 | grep -qw "$DB_NAME"; then echo "✓ Database '$DB_NAME' already exists" else psql -U "$ADMIN_USER" -h "$DB_HOST" -p "$DB_PORT" -d postgres \ -c "CREATE DATABASE $DB_NAME OWNER $DB_USER;" > /dev/null echo "✓ Database '$DB_NAME' created" fi unset PGPASSWORD # Write .env cat > .env << ENVEOF # Database Configuration DB_HOST=$DB_HOST DB_PORT=$DB_PORT DB_NAME=$DB_NAME DB_USER=$DB_USER DB_PASSWORD=$DB_PASSWORD # API Configuration API_PORT=$API_PORT NODE_ENV=$NODE_ENV ENVEOF echo "✓ .env written" echo "" # Deploy schema (first time only) export PGPASSWORD="$DB_PASSWORD" echo "Deploying schema..." psql -U "$DB_USER" -h "$DB_HOST" -p "$DB_PORT" -d "$DB_NAME" -f database/schema.sql -q echo "✓ Schema deployed" DEPLOY_FN=y BUILD_UI=y INSTALL_SERVICE=y RESTART=y # ── Update mode ─────────────────────────────────────────────────────────────── else export $(cat .env | grep -v '^#' | xargs) echo "Current database: ${DB_USER}@${DB_HOST}:${DB_PORT}/${DB_NAME}" read -p "Change database target? [y/N]: " IN if [[ "$IN" =~ ^[Yy]$ ]]; then echo "" read -p " Host [${DB_HOST}]: " IN; DB_HOST=${IN:-$DB_HOST} read -p " Port [${DB_PORT}]: " IN; DB_PORT=${IN:-$DB_PORT} read -p " Database name [${DB_NAME}]: " IN; DB_NAME=${IN:-$DB_NAME} read -p " User [${DB_USER}]: " IN; DB_USER=${IN:-$DB_USER} read -s -p " Password (blank = keep current): " IN; echo "" if [ -n "$IN" ]; then DB_PASSWORD=$IN; fi cat > .env << ENVEOF # Database Configuration DB_HOST=$DB_HOST DB_PORT=$DB_PORT DB_NAME=$DB_NAME DB_USER=$DB_USER DB_PASSWORD=$DB_PASSWORD # API Configuration API_PORT=${API_PORT:-3020} NODE_ENV=${NODE_ENV:-production} ENVEOF echo "✓ .env updated" fi echo "" export PGPASSWORD="$DB_PASSWORD" echo "Testing database connection..." if ! psql -U "$DB_USER" -h "$DB_HOST" -p "$DB_PORT" -d "$DB_NAME" -c '\q' 2>/dev/null; then echo "✗ Cannot connect — check credentials" exit 1 fi echo "✓ Connected to ${DB_NAME} on ${DB_HOST}:${DB_PORT}" echo "" read -p "Redeploy SQL functions? [Y/n]: " DEPLOY_FN read -p "Rebuild UI? [Y/n]: " BUILD_UI read -p "Restart API server? [Y/n]: " RESTART INSTALL_SERVICE=n fi # ── Shared steps ────────────────────────────────────────────────────────────── if [[ ! "$DEPLOY_FN" =~ ^[Nn]$ ]]; then echo "" echo "Deploying SQL functions..." export PGPASSWORD="$DB_PASSWORD" psql -U "$DB_USER" -h "$DB_HOST" -p "$DB_PORT" -d "$DB_NAME" -f database/functions.sql -q echo "✓ Functions deployed" fi if [[ ! "$BUILD_UI" =~ ^[Nn]$ ]]; then echo "" echo "Building UI..." cd ui && npm run build && cd .. echo "✓ UI built" fi # Systemd service echo "" SERVICE_FILE="/etc/systemd/system/dataflow.service" if [ ! -f "$SERVICE_FILE" ] && [[ "$INSTALL_SERVICE" =~ ^[Yy]$ ]]; then read -p "Install systemd service? (requires sudo) [Y/n]: " IN if [[ ! "$IN" =~ ^[Nn]$ ]]; then sudo cp "$SCRIPT_DIR/dataflow.service" "$SERVICE_FILE" sudo systemctl daemon-reload sudo systemctl enable dataflow echo "✓ Service installed and enabled" fi fi if [[ ! "$RESTART" =~ ^[Nn]$ ]]; then echo "" if [ -f "$SERVICE_FILE" ]; then sudo systemctl restart dataflow sleep 1 if systemctl is-active --quiet dataflow; then echo "✓ Service restarted and running" else echo "✗ Service failed — check: journalctl -u dataflow -n 30" fi else echo " Systemd service not installed. Start manually: node api/server.js" fi fi echo "" echo "✓ Done — http://localhost:${API_PORT}"