dataflow/deploy.sh
Paul Trowbridge 619e83acb6 Add unified deploy.sh and systemd service unit
- Merge setup.sh and deploy.sh into single deploy.sh
- First run (no .env): creates DB user/database, deploys schema +
  functions, builds UI, installs systemd service
- Subsequent runs: optionally change DB target, redeploy functions,
  rebuild UI, restart service
- Add dataflow.service systemd unit for process management
- Remove setup.sh

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 15:53:02 -04:00

200 lines
6.5 KiB
Bash
Executable File

#!/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}"