Single deploy.sh for server — frontend build via Node Docker container
- deploy.sh runs entirely on server, no local Mac needed - docker-compose: add 'frontend' service (node:20-alpine, profile=build) builds frontend and copies dist/ to /var/www/html/semblance - Remove server-deploy.sh Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
f63608cff0
commit
b481f616cb
3 changed files with 53 additions and 130 deletions
95
deploy.sh
95
deploy.sh
|
|
@ -2,22 +2,10 @@
|
|||
set -e
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# Semblance — deploy script
|
||||
# Builds frontend locally, rsyncs dist/ to server, restarts Docker services.
|
||||
#
|
||||
# Server: optical-dev.oliver.solution (Ubuntu 24.04, Apache2, Docker)
|
||||
# SSH alias: optical-dev (see ~/.ssh/config)
|
||||
#
|
||||
# First-time setup on server (run once manually):
|
||||
# ssh optical-dev
|
||||
# sudo mkdir -p /opt/semblance && sudo chown vadym.samoilenko:vadym.samoilenko /opt/semblance
|
||||
# git clone git@bitbucket.org:zlalani/semblance-dev.git /opt/semblance
|
||||
# cp /opt/semblance/backend/.env.example /opt/semblance/backend/.env
|
||||
# nano /opt/semblance/backend/.env # fill in real values
|
||||
# cd /opt/semblance && docker compose up -d --build
|
||||
# Semblance — deploy script (run directly on server)
|
||||
# /opt/semblance/deploy.sh
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
SSH_HOST="optical-dev"
|
||||
DEPLOY_DIR="/opt/semblance"
|
||||
FRONTEND_DEST="/var/www/html/semblance"
|
||||
|
||||
|
|
@ -25,78 +13,63 @@ echo "======================================"
|
|||
echo "Semblance — starting deployment"
|
||||
echo "======================================"
|
||||
|
||||
# ── Pre-flight: backend/.env must exist on server ────────────────────────────
|
||||
cd "$DEPLOY_DIR"
|
||||
|
||||
# ── Pre-flight ────────────────────────────────────────────────────────────────
|
||||
echo ""
|
||||
echo "[pre-flight] Checking backend/.env on server..."
|
||||
if ! ssh "$SSH_HOST" "test -f $DEPLOY_DIR/backend/.env"; then
|
||||
echo ""
|
||||
echo "ERROR: $DEPLOY_DIR/backend/.env not found on server."
|
||||
echo "Run on server:"
|
||||
echo " cp $DEPLOY_DIR/backend/.env.example $DEPLOY_DIR/backend/.env"
|
||||
echo " nano $DEPLOY_DIR/backend/.env"
|
||||
echo "[pre-flight] Checking backend/.env..."
|
||||
if [ ! -f backend/.env ]; then
|
||||
echo "ERROR: backend/.env not found."
|
||||
echo " cp backend/.env.example backend/.env && nano backend/.env"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for VAR in SECRET_KEY JWT_SECRET_KEY OPENAI_API_KEY GEMINI_API_KEY; do
|
||||
if ! ssh "$SSH_HOST" "grep -q '^${VAR}=.\+' $DEPLOY_DIR/backend/.env 2>/dev/null"; then
|
||||
echo "ERROR: $VAR is not set in backend/.env on server"
|
||||
if ! grep -q "^${VAR}=.\+" backend/.env 2>/dev/null; then
|
||||
echo "ERROR: $VAR is not set in backend/.env"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
echo "✓ backend/.env present and required vars set"
|
||||
echo "✓ backend/.env OK"
|
||||
|
||||
# ── Step 1: Pull latest code on server ───────────────────────────────────────
|
||||
# ── Step 1: Pull latest code ──────────────────────────────────────────────────
|
||||
echo ""
|
||||
echo "[1/5] Pulling latest code on server..."
|
||||
ssh "$SSH_HOST" "cd $DEPLOY_DIR && git pull"
|
||||
echo "[1/4] Pulling latest code..."
|
||||
git pull
|
||||
|
||||
# ── Step 2: Build frontend locally ───────────────────────────────────────────
|
||||
# ── Step 2: Build frontend (Node in Docker) ───────────────────────────────────
|
||||
echo ""
|
||||
echo "[2/5] Building frontend locally..."
|
||||
cp .env.production .env
|
||||
npm install --silent
|
||||
npm run build
|
||||
echo "✓ Frontend built (dist/)"
|
||||
|
||||
# ── Step 3: Deploy frontend to server ────────────────────────────────────────
|
||||
echo ""
|
||||
echo "[3/5] Deploying frontend to server..."
|
||||
ssh "$SSH_HOST" "sudo mkdir -p $FRONTEND_DEST"
|
||||
rsync -az --delete dist/ "$SSH_HOST:$FRONTEND_DEST/"
|
||||
ssh "$SSH_HOST" "sudo chown -R www-data:www-data $FRONTEND_DEST"
|
||||
echo "[2/4] Building frontend..."
|
||||
sudo mkdir -p "$FRONTEND_DEST"
|
||||
docker compose --profile build run --rm frontend
|
||||
sudo chown -R www-data:www-data "$FRONTEND_DEST"
|
||||
echo "✓ Frontend deployed to $FRONTEND_DEST"
|
||||
|
||||
# ── Step 4: Ensure Apache proxy config for semblance ─────────────────────────
|
||||
# ── Step 3: Ensure Apache proxy config ───────────────────────────────────────
|
||||
echo ""
|
||||
echo "[4/5] Ensuring Apache proxy config..."
|
||||
ssh "$SSH_HOST" "
|
||||
CONF='/etc/apache2/sites-enabled/optical-dev.oliver.solutions.conf'
|
||||
echo "[3/4] Ensuring Apache proxy config..."
|
||||
CONF="/etc/apache2/sites-enabled/optical-dev.oliver.solutions.conf"
|
||||
|
||||
if grep -q 'semblance_back' \"\$CONF\" 2>/dev/null; then
|
||||
echo '✓ Apache semblance config already present'
|
||||
if sudo grep -q "semblance_back" "$CONF" 2>/dev/null; then
|
||||
echo "✓ Apache semblance config already present"
|
||||
else
|
||||
echo 'Adding semblance blocks to Apache config...'
|
||||
sudo sed -i 's|</VirtualHost>| # ----------------------------------------------------------------\n # Semblance — Quart/Hypercorn backend at :5137\n # ----------------------------------------------------------------\n\n # WebSocket (Socket.IO)\n RewriteCond %{HTTP:Upgrade} websocket [NC]\n RewriteCond %{HTTP:Connection} upgrade [NC]\n RewriteRule ^/semblance_back/socket.io/(.*) ws://127.0.0.1:5137/socket.io/\$1 [P,L]\n\n # REST API\n ProxyPass /semblance_back/api/ http://127.0.0.1:5137/api/\n ProxyPassReverse /semblance_back/api/ http://127.0.0.1:5137/api/\n\n # Socket.IO HTTP polling fallback\n ProxyPass /semblance_back/socket.io/ http://127.0.0.1:5137/socket.io/\n ProxyPassReverse /semblance_back/socket.io/ http://127.0.0.1:5137/socket.io/\n\n # Semblance SPA — served at /semblance/\n Alias /semblance $FRONTEND_DEST\n <Directory $FRONTEND_DEST>\n Options -Indexes +FollowSymLinks\n AllowOverride None\n Require all granted\n RewriteEngine On\n RewriteBase /semblance/\n RewriteCond %{REQUEST_FILENAME} !-f\n RewriteCond %{REQUEST_FILENAME} !-d\n RewriteRule ^ index.html [L]\n </Directory>\n\n</VirtualHost>|' \"\$CONF\"
|
||||
echo "Adding semblance blocks to Apache config..."
|
||||
sudo sed -i "s|</VirtualHost>| # ----------------------------------------------------------------\n # Semblance — Quart/Hypercorn backend at :5137\n # ----------------------------------------------------------------\n\n # WebSocket (Socket.IO)\n RewriteCond %{HTTP:Upgrade} websocket [NC]\n RewriteCond %{HTTP:Connection} upgrade [NC]\n RewriteRule ^/semblance_back/socket.io/(.*) ws://127.0.0.1:5137/socket.io/\$1 [P,L]\n\n # REST API\n ProxyPass /semblance_back/api/ http://127.0.0.1:5137/api/\n ProxyPassReverse /semblance_back/api/ http://127.0.0.1:5137/api/\n\n # Socket.IO HTTP polling fallback\n ProxyPass /semblance_back/socket.io/ http://127.0.0.1:5137/socket.io/\n ProxyPassReverse /semblance_back/socket.io/ http://127.0.0.1:5137/socket.io/\n\n # Semblance SPA\n Alias /semblance $FRONTEND_DEST\n <Directory $FRONTEND_DEST>\n Options -Indexes +FollowSymLinks\n AllowOverride None\n Require all granted\n RewriteEngine On\n RewriteBase /semblance/\n RewriteCond %{REQUEST_FILENAME} !-f\n RewriteCond %{REQUEST_FILENAME} !-d\n RewriteRule ^ index.html [L]\n </Directory>\n\n</VirtualHost>|" "$CONF"
|
||||
sudo apache2ctl configtest && sudo systemctl reload apache2
|
||||
echo '✓ Apache config updated and reloaded'
|
||||
echo "✓ Apache config updated and reloaded"
|
||||
fi
|
||||
"
|
||||
|
||||
# ── Step 5: Rebuild and restart Docker services ───────────────────────────────
|
||||
# ── Step 4: Rebuild and restart backend + mongo ───────────────────────────────
|
||||
echo ""
|
||||
echo "[5/5] Rebuilding and restarting Docker services..."
|
||||
ssh "$SSH_HOST" "
|
||||
cd $DEPLOY_DIR
|
||||
docker compose pull mongo 2>/dev/null || true
|
||||
echo "[4/4] Rebuilding and restarting Docker services..."
|
||||
docker compose up -d --build
|
||||
echo ''
|
||||
echo 'Container status:'
|
||||
|
||||
echo ""
|
||||
echo "Container status:"
|
||||
docker compose ps
|
||||
"
|
||||
|
||||
echo ""
|
||||
echo "======================================"
|
||||
echo "Deployment complete!"
|
||||
echo " Frontend: https://optical-dev.oliver.solution/semblance/"
|
||||
echo " API: https://optical-dev.oliver.solution/semblance_back/api/"
|
||||
echo " https://optical-dev.oliver.solution/semblance/"
|
||||
echo "======================================"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,18 @@
|
|||
services:
|
||||
frontend:
|
||||
image: node:20-alpine
|
||||
working_dir: /app
|
||||
volumes:
|
||||
- .:/app
|
||||
- /var/www/html/semblance:/app/dist-out
|
||||
command: >
|
||||
sh -c "cp .env.production .env &&
|
||||
npm ci --silent &&
|
||||
npm run build &&
|
||||
cp -r dist/* /app/dist-out/"
|
||||
profiles:
|
||||
- build
|
||||
|
||||
mongo:
|
||||
image: mongo:7
|
||||
restart: unless-stopped
|
||||
|
|
|
|||
|
|
@ -1,64 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# Semblance — server-side deploy script
|
||||
# Run this DIRECTLY ON THE SERVER: /opt/semblance/server-deploy.sh
|
||||
#
|
||||
# Does NOT build the frontend (Node not on server).
|
||||
# Frontend must be deployed from local Mac via: ./deploy.sh
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
DEPLOY_DIR="/opt/semblance"
|
||||
FRONTEND_DEST="/var/www/html/semblance"
|
||||
|
||||
echo "======================================"
|
||||
echo "Semblance — server-side deployment"
|
||||
echo "======================================"
|
||||
|
||||
cd "$DEPLOY_DIR"
|
||||
|
||||
# ── Pre-flight ────────────────────────────────────────────────────────────────
|
||||
if [ ! -f backend/.env ]; then
|
||||
echo "ERROR: backend/.env not found."
|
||||
echo " cp backend/.env.example backend/.env && nano backend/.env"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for VAR in SECRET_KEY JWT_SECRET_KEY OPENAI_API_KEY GEMINI_API_KEY; do
|
||||
if ! grep -q "^${VAR}=.\+" backend/.env 2>/dev/null; then
|
||||
echo "ERROR: $VAR is not set in backend/.env"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
echo "✓ backend/.env OK"
|
||||
|
||||
# ── Step 1: Pull latest code ──────────────────────────────────────────────────
|
||||
echo ""
|
||||
echo "[1/3] Pulling latest code..."
|
||||
git pull
|
||||
|
||||
# ── Step 2: Ensure frontend dir exists ───────────────────────────────────────
|
||||
echo ""
|
||||
echo "[2/3] Ensuring frontend directory..."
|
||||
sudo mkdir -p "$FRONTEND_DEST"
|
||||
sudo chown -R www-data:www-data "$FRONTEND_DEST"
|
||||
echo "✓ $FRONTEND_DEST ready"
|
||||
|
||||
# ── Step 3: Rebuild and restart Docker services ───────────────────────────────
|
||||
echo ""
|
||||
echo "[3/3] Rebuilding and restarting Docker services..."
|
||||
docker compose up -d --build
|
||||
|
||||
echo ""
|
||||
echo "Container status:"
|
||||
docker compose ps
|
||||
|
||||
echo ""
|
||||
echo "======================================"
|
||||
echo "Server deployment complete!"
|
||||
echo " Backend: http://127.0.0.1:5137"
|
||||
echo ""
|
||||
echo "NOTE: Frontend not deployed (requires local build)."
|
||||
echo " Run ./deploy.sh from your Mac to deploy the frontend."
|
||||
echo "======================================"
|
||||
Loading…
Add table
Reference in a new issue