Scans storage/amazon/tm/ and storage/amazon/ref/, creates DB registry entries for each JSON file so they appear in the TM Registry and Reference Library pages. Extracts channel from TM filenames, locale from ref filenames, counts JSONL segments. Idempotent (skips duplicates). Also added to deploy.sh --init flow. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
265 lines
9.3 KiB
Bash
Executable file
265 lines
9.3 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# ============================================================
|
|
# Amazon Transcreation Platform — Deploy Script
|
|
# ============================================================
|
|
# Usage:
|
|
# First time: ./deploy.sh --init
|
|
# Updates: ./deploy.sh
|
|
# Full rebuild: ./deploy.sh --rebuild
|
|
#
|
|
# Location: /opt/amazon-transcreation
|
|
# URL: https://optical-dev.oliver.solutions/amazon-transcreation
|
|
# ============================================================
|
|
|
|
set -euo pipefail
|
|
|
|
APP_DIR="/opt/amazon-transcreation"
|
|
COMPOSE_FILE="docker-compose.prod.yml"
|
|
COMPOSE="docker compose -f $COMPOSE_FILE"
|
|
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m'
|
|
|
|
log() { echo -e "${GREEN}[DEPLOY]${NC} $1"; }
|
|
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
|
error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; }
|
|
|
|
cd "$APP_DIR" || error "Directory $APP_DIR not found. Clone the repo first."
|
|
|
|
# ---------------------------------------------------------------
|
|
# Parse arguments
|
|
# ---------------------------------------------------------------
|
|
INIT=false
|
|
REBUILD=false
|
|
|
|
for arg in "$@"; do
|
|
case $arg in
|
|
--init) INIT=true ;;
|
|
--rebuild) REBUILD=true ;;
|
|
--help)
|
|
echo "Usage: $0 [--init] [--rebuild]"
|
|
echo " --init First-time setup (create .env, run migrations, seed data, configure Apache)"
|
|
echo " --rebuild Force rebuild all Docker images (no cache)"
|
|
echo " (no args) Pull latest code, rebuild changed images, restart"
|
|
exit 0
|
|
;;
|
|
*) error "Unknown argument: $arg" ;;
|
|
esac
|
|
done
|
|
|
|
# ---------------------------------------------------------------
|
|
# Pre-flight checks
|
|
# ---------------------------------------------------------------
|
|
log "Running pre-flight checks..."
|
|
|
|
command -v docker >/dev/null 2>&1 || error "Docker is not installed"
|
|
command -v git >/dev/null 2>&1 || error "Git is not installed"
|
|
docker info >/dev/null 2>&1 || error "Docker daemon is not running"
|
|
|
|
# ---------------------------------------------------------------
|
|
# First-time init
|
|
# ---------------------------------------------------------------
|
|
if [ "$INIT" = true ]; then
|
|
log "=== FIRST-TIME SETUP ==="
|
|
|
|
# Create .env if it doesn't exist
|
|
if [ ! -f .env ]; then
|
|
if [ -f .env.production.example ]; then
|
|
cp .env.production.example .env
|
|
# Generate a real JWT secret
|
|
JWT_SECRET=$(python3 -c "import secrets; print(secrets.token_hex(32))" 2>/dev/null || openssl rand -hex 32)
|
|
sed -i "s/CHANGE_ME_GENERATE_WITH.*/$JWT_SECRET/" .env
|
|
# Generate a real DB password
|
|
DB_PASS=$(python3 -c "import secrets; print(secrets.token_hex(16))" 2>/dev/null || openssl rand -hex 16)
|
|
sed -i "s/CHANGE_ME_DB_PASSWORD/$DB_PASS/g" .env
|
|
warn ".env created from template. You MUST edit it to set:"
|
|
warn " - ANTHROPIC_API_KEY (your Claude API key)"
|
|
warn ""
|
|
warn "Auto-generated values:"
|
|
warn " - JWT_SECRET_KEY"
|
|
warn " - DB_PASSWORD"
|
|
echo ""
|
|
read -p "Edit .env now? [Y/n] " -n 1 -r
|
|
echo
|
|
if [[ ! $REPLY =~ ^[Nn]$ ]]; then
|
|
${EDITOR:-nano} .env
|
|
fi
|
|
else
|
|
error ".env.production.example not found. Is this the right directory?"
|
|
fi
|
|
else
|
|
log ".env already exists, skipping creation"
|
|
fi
|
|
|
|
# Storage directories are now tracked in git (storage/amazon/tm + ref)
|
|
# Just ensure the base directory exists for runtime uploads
|
|
mkdir -p storage
|
|
|
|
# Build all images
|
|
log "Building all Docker images (this may take a few minutes)..."
|
|
$COMPOSE build
|
|
|
|
# Start database and redis first
|
|
log "Starting database and redis..."
|
|
$COMPOSE up -d db redis
|
|
log "Waiting for database to be healthy..."
|
|
sleep 5
|
|
|
|
# Start backend for migrations
|
|
log "Starting backend..."
|
|
$COMPOSE up -d backend
|
|
sleep 5
|
|
|
|
# Wait for backend to be ready
|
|
log "Waiting for backend to start..."
|
|
for i in $(seq 1 30); do
|
|
if curl -sf http://127.0.0.1:8040/health >/dev/null 2>&1; then
|
|
break
|
|
fi
|
|
sleep 2
|
|
done
|
|
|
|
# Run migrations
|
|
log "Running database migrations..."
|
|
$COMPOSE exec -T backend alembic upgrade head
|
|
|
|
# TM and reference files are now tracked in git — no import step needed.
|
|
# Verify they arrived via git pull:
|
|
TM_COUNT=$(find storage/amazon/tm -name '*.json' 2>/dev/null | wc -l)
|
|
REF_COUNT=$(find storage/amazon/ref -name '*.json' 2>/dev/null | wc -l)
|
|
log "Found $TM_COUNT TM files and $REF_COUNT reference files in storage/amazon/"
|
|
if [ "$TM_COUNT" -eq 0 ]; then
|
|
warn "No TM files found! Check that git pulled storage/amazon/tm/ correctly."
|
|
fi
|
|
|
|
# Seed database
|
|
log "Seeding database (default client + test users)..."
|
|
$COMPOSE exec -T backend python -m seed.create_default_client
|
|
$COMPOSE exec -T backend python -m seed.create_test_users
|
|
|
|
# Register existing TM + reference files in the database
|
|
log "Registering storage files in database..."
|
|
$COMPOSE exec -T backend python -m seed.register_storage_files
|
|
|
|
# Start all remaining services
|
|
log "Starting all services..."
|
|
$COMPOSE up -d --remove-orphans
|
|
|
|
# ---------------------------------------------------------------
|
|
# Apache configuration
|
|
# ---------------------------------------------------------------
|
|
log "Configuring Apache reverse proxy..."
|
|
|
|
# Enable required modules
|
|
a2enmod proxy proxy_http proxy_wstunnel rewrite headers 2>/dev/null || true
|
|
|
|
# Find the SSL vhost for optical-dev.oliver.solutions
|
|
VHOST_FILE=$(grep -rl "optical-dev.oliver.solutions" /etc/apache2/sites-enabled/ 2>/dev/null | head -1 || true)
|
|
|
|
if [ -n "$VHOST_FILE" ]; then
|
|
# Check if already configured
|
|
if grep -q "amazon-transcreation" "$VHOST_FILE" 2>/dev/null; then
|
|
log "Apache already has amazon-transcreation config in $VHOST_FILE"
|
|
else
|
|
warn "Found vhost at: $VHOST_FILE"
|
|
warn ""
|
|
warn "Add the following INSIDE the <VirtualHost *:443> block, before </VirtualHost>:"
|
|
warn ""
|
|
warn " Include /opt/amazon-transcreation/apache/amazon-transcreation.conf"
|
|
warn ""
|
|
warn "Then run: sudo systemctl reload apache2"
|
|
echo ""
|
|
read -p "Want me to add it automatically? [y/N] " -n 1 -r
|
|
echo
|
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
|
# Insert Include line before </VirtualHost>
|
|
sed -i "/<\/VirtualHost>/i\\ Include /opt/amazon-transcreation/apache/amazon-transcreation.conf" "$VHOST_FILE"
|
|
systemctl reload apache2
|
|
log "Apache config added and reloaded."
|
|
fi
|
|
fi
|
|
else
|
|
warn "Could not find Apache vhost for optical-dev.oliver.solutions"
|
|
warn "Manually add this to your SSL vhost:"
|
|
warn " Include /opt/amazon-transcreation/apache/amazon-transcreation.conf"
|
|
warn "Then: sudo systemctl reload apache2"
|
|
fi
|
|
|
|
# Health check
|
|
sleep 3
|
|
if curl -sf http://127.0.0.1:8040/health >/dev/null 2>&1; then
|
|
log "Backend health check passed"
|
|
else
|
|
warn "Backend health check failed — check logs: $COMPOSE logs backend"
|
|
fi
|
|
|
|
echo ""
|
|
log "=== SETUP COMPLETE ==="
|
|
log ""
|
|
log "URL: https://optical-dev.oliver.solutions/amazon-transcreation"
|
|
log ""
|
|
log "Services running:"
|
|
$COMPOSE ps --format "table {{.Name}}\t{{.Status}}\t{{.Ports}}"
|
|
log ""
|
|
log "Test credentials:"
|
|
log " admin@amazon.com / admin123!"
|
|
log " manager@amazon.com / manager123!"
|
|
log " reviewer@amazon.com / reviewer123!"
|
|
log ""
|
|
log "Next steps:"
|
|
log " 1. Verify ANTHROPIC_API_KEY is set in .env"
|
|
log " 2. Ensure Apache config is loaded (see above)"
|
|
log " 3. Change default passwords via admin panel"
|
|
exit 0
|
|
fi
|
|
|
|
# ---------------------------------------------------------------
|
|
# Standard deploy (git pull + rebuild + restart)
|
|
# ---------------------------------------------------------------
|
|
[ -f .env ] || error ".env not found. Run './deploy.sh --init' first."
|
|
|
|
# Pull latest code
|
|
log "Pulling latest code..."
|
|
git pull --ff-only || error "Git pull failed. Resolve conflicts manually."
|
|
|
|
# Build images
|
|
# Frontend always gets --no-cache to avoid stale Next.js builds from Docker layer cache
|
|
if [ "$REBUILD" = true ]; then
|
|
log "Rebuilding all images (no cache)..."
|
|
$COMPOSE build --no-cache
|
|
else
|
|
log "Building backend..."
|
|
$COMPOSE build backend celery_worker
|
|
log "Building frontend (no cache)..."
|
|
$COMPOSE build --no-cache frontend
|
|
fi
|
|
|
|
# Run migrations (safe to run even if nothing changed)
|
|
log "Running database migrations..."
|
|
$COMPOSE up -d db redis
|
|
sleep 3
|
|
$COMPOSE up -d backend
|
|
sleep 5
|
|
$COMPOSE exec -T backend alembic upgrade head
|
|
|
|
# Restart all services (remove orphans to avoid stale containers)
|
|
log "Restarting all services..."
|
|
$COMPOSE down --remove-orphans
|
|
$COMPOSE up -d
|
|
|
|
# Health check
|
|
log "Waiting for services..."
|
|
sleep 5
|
|
|
|
if curl -sf http://127.0.0.1:8040/health >/dev/null 2>&1; then
|
|
log "Health check passed"
|
|
else
|
|
warn "Health check failed — check: $COMPOSE logs --tail 50"
|
|
fi
|
|
|
|
echo ""
|
|
$COMPOSE ps --format "table {{.Name}}\t{{.Status}}\t{{.Ports}}"
|
|
echo ""
|
|
log "Deploy complete. URL: https://optical-dev.oliver.solutions/amazon-transcreation"
|