feat: Server deployment scripts + Database init
Some checks failed
CI / Frontend Lint & Type Check (push) Has been cancelled
CI / Frontend Build (push) Has been cancelled
CI / Backend Lint (push) Has been cancelled
CI / Backend Tests (push) Has been cancelled
CI / Docker Build (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
Deploy / Build & Push Images (push) Has been cancelled
Deploy / Deploy to Server (push) Has been cancelled
Deploy / Notify (push) Has been cancelled
Some checks failed
CI / Frontend Lint & Type Check (push) Has been cancelled
CI / Frontend Build (push) Has been cancelled
CI / Backend Lint (push) Has been cancelled
CI / Backend Tests (push) Has been cancelled
CI / Docker Build (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
Deploy / Build & Push Images (push) Has been cancelled
Deploy / Deploy to Server (push) Has been cancelled
Deploy / Notify (push) Has been cancelled
NEW FILES: - deploy.sh: One-command setup script (installs deps, creates venv, init db) - start.sh: Quick start script (launches both backend & frontend) - backend/scripts/init_db.py: Database initialization with schema + seed data CHANGES: - README: Added one-command setup instructions - All scripts made executable SERVER DEPLOYMENT: 1. git pull 2. chmod +x deploy.sh && ./deploy.sh 3. ./start.sh (or use PM2/Docker) The init_db.py script: - Creates all database tables - Seeds basic TLD info (com, net, org, io, etc.) - Works with both SQLite and PostgreSQL
This commit is contained in:
37
README.md
37
README.md
@ -204,14 +204,34 @@ pounce/
|
|||||||
- Node.js 18+
|
- Node.js 18+
|
||||||
- npm or yarn
|
- npm or yarn
|
||||||
|
|
||||||
### 1. Clone Repository
|
### 🚀 One-Command Setup (Recommended)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Clone repository
|
||||||
|
git clone https://git.6bit.ch/yvg/pounce.git
|
||||||
|
cd pounce
|
||||||
|
|
||||||
|
# Run deployment script (sets up everything)
|
||||||
|
chmod +x deploy.sh
|
||||||
|
./deploy.sh
|
||||||
|
|
||||||
|
# Start both services
|
||||||
|
chmod +x start.sh
|
||||||
|
./start.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
That's it! Open http://localhost:3000
|
||||||
|
|
||||||
|
### Manual Setup
|
||||||
|
|
||||||
|
#### 1. Clone Repository
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://git.6bit.ch/yvg/pounce.git
|
git clone https://git.6bit.ch/yvg/pounce.git
|
||||||
cd pounce
|
cd pounce
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. Backend Setup
|
#### 2. Backend Setup
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd backend
|
cd backend
|
||||||
@ -229,13 +249,10 @@ cp env.example .env
|
|||||||
|
|
||||||
# Generate secret key and add to .env
|
# Generate secret key and add to .env
|
||||||
python -c "import secrets; print(f'SECRET_KEY={secrets.token_hex(32)}')"
|
python -c "import secrets; print(f'SECRET_KEY={secrets.token_hex(32)}')"
|
||||||
```
|
# Edit .env with your SECRET_KEY
|
||||||
|
|
||||||
Edit `.env`:
|
# Initialize database
|
||||||
```env
|
python scripts/init_db.py
|
||||||
DATABASE_URL=sqlite+aiosqlite:///./domainwatch.db
|
|
||||||
SECRET_KEY=your-generated-secret-key
|
|
||||||
CORS_ORIGINS=http://localhost:3000,http://127.0.0.1:3000
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Start backend:
|
Start backend:
|
||||||
@ -243,7 +260,7 @@ Start backend:
|
|||||||
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
|
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. Frontend Setup
|
#### 3. Frontend Setup
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd frontend
|
cd frontend
|
||||||
@ -258,7 +275,7 @@ echo "NEXT_PUBLIC_API_URL=http://localhost:8000" > .env.local
|
|||||||
npm run dev
|
npm run dev
|
||||||
```
|
```
|
||||||
|
|
||||||
### 4. Access Application
|
#### 4. Access Application
|
||||||
|
|
||||||
- **Frontend:** http://localhost:3000
|
- **Frontend:** http://localhost:3000
|
||||||
- **Backend API:** http://localhost:8000
|
- **Backend API:** http://localhost:8000
|
||||||
|
|||||||
105
backend/scripts/init_db.py
Executable file
105
backend/scripts/init_db.py
Executable file
@ -0,0 +1,105 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Database initialization script.
|
||||||
|
Creates all tables and seeds initial data.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
python scripts/init_db.py
|
||||||
|
"""
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
# Add parent directory to path
|
||||||
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
|
|
||||||
|
from app.database import engine, Base
|
||||||
|
|
||||||
|
# Import all models to register them with SQLAlchemy
|
||||||
|
from app.models import user, domain, tld_price, newsletter, portfolio, price_alert
|
||||||
|
|
||||||
|
|
||||||
|
async def init_database():
|
||||||
|
"""Initialize database tables."""
|
||||||
|
print("🔧 Initializing database...")
|
||||||
|
|
||||||
|
async with engine.begin() as conn:
|
||||||
|
# Create all tables
|
||||||
|
await conn.run_sync(Base.metadata.create_all)
|
||||||
|
|
||||||
|
print("✅ Database tables created successfully!")
|
||||||
|
print("")
|
||||||
|
print("Tables created:")
|
||||||
|
for table in Base.metadata.tables.keys():
|
||||||
|
print(f" - {table}")
|
||||||
|
|
||||||
|
|
||||||
|
async def seed_tld_data():
|
||||||
|
"""Seed initial TLD data."""
|
||||||
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
|
from sqlalchemy.orm import sessionmaker
|
||||||
|
from app.models.tld_price import TLDInfo
|
||||||
|
from sqlalchemy import select
|
||||||
|
|
||||||
|
AsyncSessionLocal = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
|
||||||
|
|
||||||
|
# Basic TLD data
|
||||||
|
tld_data = [
|
||||||
|
{"tld": "com", "type": "generic", "description": "Commercial", "popularity_rank": 1},
|
||||||
|
{"tld": "net", "type": "generic", "description": "Network", "popularity_rank": 2},
|
||||||
|
{"tld": "org", "type": "generic", "description": "Organization", "popularity_rank": 3},
|
||||||
|
{"tld": "io", "type": "country", "description": "Tech startups", "popularity_rank": 4},
|
||||||
|
{"tld": "co", "type": "country", "description": "Company/Colombia", "popularity_rank": 5},
|
||||||
|
{"tld": "ai", "type": "country", "description": "AI/Anguilla", "popularity_rank": 6},
|
||||||
|
{"tld": "dev", "type": "generic", "description": "Developers", "popularity_rank": 7},
|
||||||
|
{"tld": "app", "type": "generic", "description": "Applications", "popularity_rank": 8},
|
||||||
|
{"tld": "xyz", "type": "generic", "description": "Generation XYZ", "popularity_rank": 9},
|
||||||
|
{"tld": "me", "type": "country", "description": "Personal/Montenegro", "popularity_rank": 10},
|
||||||
|
{"tld": "ch", "type": "country", "description": "Switzerland", "popularity_rank": 11},
|
||||||
|
{"tld": "de", "type": "country", "description": "Germany", "popularity_rank": 12},
|
||||||
|
{"tld": "uk", "type": "country", "description": "United Kingdom", "popularity_rank": 13},
|
||||||
|
{"tld": "fr", "type": "country", "description": "France", "popularity_rank": 14},
|
||||||
|
{"tld": "nl", "type": "country", "description": "Netherlands", "popularity_rank": 15},
|
||||||
|
]
|
||||||
|
|
||||||
|
async with AsyncSessionLocal() as session:
|
||||||
|
for data in tld_data:
|
||||||
|
# Check if exists
|
||||||
|
result = await session.execute(
|
||||||
|
select(TLDInfo).where(TLDInfo.tld == data["tld"])
|
||||||
|
)
|
||||||
|
existing = result.scalar_one_or_none()
|
||||||
|
|
||||||
|
if not existing:
|
||||||
|
tld_info = TLDInfo(**data)
|
||||||
|
session.add(tld_info)
|
||||||
|
print(f" Added: .{data['tld']}")
|
||||||
|
|
||||||
|
await session.commit()
|
||||||
|
|
||||||
|
print("✅ TLD data seeded!")
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
"""Run all initialization steps."""
|
||||||
|
print("=" * 50)
|
||||||
|
print("POUNCE Database Initialization")
|
||||||
|
print("=" * 50)
|
||||||
|
print("")
|
||||||
|
|
||||||
|
await init_database()
|
||||||
|
print("")
|
||||||
|
|
||||||
|
print("🌱 Seeding initial data...")
|
||||||
|
await seed_tld_data()
|
||||||
|
print("")
|
||||||
|
|
||||||
|
print("=" * 50)
|
||||||
|
print("✅ Database initialization complete!")
|
||||||
|
print("=" * 50)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
asyncio.run(main())
|
||||||
|
|
||||||
156
deploy.sh
Executable file
156
deploy.sh
Executable file
@ -0,0 +1,156 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# POUNCE Deployment Script
|
||||||
|
# Usage: ./deploy.sh [dev|prod]
|
||||||
|
#
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
MODE=${1:-dev}
|
||||||
|
echo "================================================"
|
||||||
|
echo " POUNCE Deployment - Mode: $MODE"
|
||||||
|
echo "================================================"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Colors
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# Functions
|
||||||
|
log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
|
||||||
|
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
||||||
|
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# 1. Check prerequisites
|
||||||
|
# ============================================
|
||||||
|
log_info "Checking prerequisites..."
|
||||||
|
|
||||||
|
if ! command -v python3 &> /dev/null; then
|
||||||
|
log_error "Python3 not found. Please install Python 3.10+"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! command -v node &> /dev/null; then
|
||||||
|
log_error "Node.js not found. Please install Node.js 18+"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! command -v npm &> /dev/null; then
|
||||||
|
log_error "npm not found. Please install npm"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "Prerequisites OK!"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# 2. Setup Backend
|
||||||
|
# ============================================
|
||||||
|
log_info "Setting up Backend..."
|
||||||
|
|
||||||
|
cd backend
|
||||||
|
|
||||||
|
# Create virtual environment if not exists
|
||||||
|
if [ ! -d "venv" ]; then
|
||||||
|
log_info "Creating Python virtual environment..."
|
||||||
|
python3 -m venv venv
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Activate venv
|
||||||
|
source venv/bin/activate
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
log_info "Installing Python dependencies..."
|
||||||
|
pip install -q --upgrade pip
|
||||||
|
pip install -q -r requirements.txt
|
||||||
|
|
||||||
|
# Create .env if not exists
|
||||||
|
if [ ! -f ".env" ]; then
|
||||||
|
log_warn ".env file not found, copying from env.example..."
|
||||||
|
if [ -f "env.example" ]; then
|
||||||
|
cp env.example .env
|
||||||
|
log_warn "Please edit backend/.env with your settings!"
|
||||||
|
else
|
||||||
|
log_error "env.example not found!"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Initialize database
|
||||||
|
log_info "Initializing database..."
|
||||||
|
python scripts/init_db.py
|
||||||
|
|
||||||
|
cd ..
|
||||||
|
log_info "Backend setup complete!"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# 3. Setup Frontend
|
||||||
|
# ============================================
|
||||||
|
log_info "Setting up Frontend..."
|
||||||
|
|
||||||
|
cd frontend
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
log_info "Installing npm dependencies..."
|
||||||
|
npm install --silent
|
||||||
|
|
||||||
|
# Create .env.local if not exists
|
||||||
|
if [ ! -f ".env.local" ]; then
|
||||||
|
log_warn ".env.local not found, creating..."
|
||||||
|
echo "NEXT_PUBLIC_API_URL=http://localhost:8000" > .env.local
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Build for production
|
||||||
|
if [ "$MODE" == "prod" ]; then
|
||||||
|
log_info "Building for production..."
|
||||||
|
npm run build
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd ..
|
||||||
|
log_info "Frontend setup complete!"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# 4. Start Services
|
||||||
|
# ============================================
|
||||||
|
if [ "$MODE" == "dev" ]; then
|
||||||
|
echo ""
|
||||||
|
echo "================================================"
|
||||||
|
echo " Development Setup Complete!"
|
||||||
|
echo "================================================"
|
||||||
|
echo ""
|
||||||
|
echo "To start the services:"
|
||||||
|
echo ""
|
||||||
|
echo " Backend (Terminal 1):"
|
||||||
|
echo " cd backend && source venv/bin/activate"
|
||||||
|
echo " uvicorn app.main:app --reload --host 0.0.0.0 --port 8000"
|
||||||
|
echo ""
|
||||||
|
echo " Frontend (Terminal 2):"
|
||||||
|
echo " cd frontend && npm run dev"
|
||||||
|
echo ""
|
||||||
|
echo "Then open: http://localhost:3000"
|
||||||
|
echo ""
|
||||||
|
else
|
||||||
|
echo ""
|
||||||
|
echo "================================================"
|
||||||
|
echo " Production Setup Complete!"
|
||||||
|
echo "================================================"
|
||||||
|
echo ""
|
||||||
|
echo "To start with PM2:"
|
||||||
|
echo ""
|
||||||
|
echo " # Backend"
|
||||||
|
echo " cd backend && source venv/bin/activate"
|
||||||
|
echo " pm2 start 'uvicorn app.main:app --host 0.0.0.0 --port 8000' --name pounce-backend"
|
||||||
|
echo ""
|
||||||
|
echo " # Frontend"
|
||||||
|
echo " cd frontend"
|
||||||
|
echo " pm2 start 'npm start' --name pounce-frontend"
|
||||||
|
echo ""
|
||||||
|
echo "Or use Docker:"
|
||||||
|
echo " docker-compose up -d"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
65
start.sh
Executable file
65
start.sh
Executable file
@ -0,0 +1,65 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# POUNCE Quick Start Script
|
||||||
|
# Starts both backend and frontend for development
|
||||||
|
#
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "🐆 Starting POUNCE..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check if backend venv exists
|
||||||
|
if [ ! -d "backend/venv" ]; then
|
||||||
|
echo "❌ Backend not set up. Run ./deploy.sh first!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Kill any existing processes on our ports
|
||||||
|
echo "🔧 Cleaning up old processes..."
|
||||||
|
lsof -ti:8000 | xargs kill -9 2>/dev/null || true
|
||||||
|
lsof -ti:3000 | xargs kill -9 2>/dev/null || true
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
# Start Backend
|
||||||
|
echo "🚀 Starting Backend on port 8000..."
|
||||||
|
cd backend
|
||||||
|
source venv/bin/activate
|
||||||
|
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000 &
|
||||||
|
BACKEND_PID=$!
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
# Wait for backend to start
|
||||||
|
sleep 3
|
||||||
|
|
||||||
|
# Check if backend is running
|
||||||
|
if curl -s http://localhost:8000/health > /dev/null 2>&1; then
|
||||||
|
echo "✅ Backend running!"
|
||||||
|
else
|
||||||
|
echo "❌ Backend failed to start. Check logs."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Start Frontend
|
||||||
|
echo "🚀 Starting Frontend on port 3000..."
|
||||||
|
cd frontend
|
||||||
|
npm run dev &
|
||||||
|
FRONTEND_PID=$!
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "================================================"
|
||||||
|
echo " POUNCE is starting..."
|
||||||
|
echo "================================================"
|
||||||
|
echo ""
|
||||||
|
echo " Backend: http://localhost:8000"
|
||||||
|
echo " Frontend: http://localhost:3000"
|
||||||
|
echo " API Docs: http://localhost:8000/docs"
|
||||||
|
echo ""
|
||||||
|
echo " Press Ctrl+C to stop all services"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Wait for both processes
|
||||||
|
trap "kill $BACKEND_PID $FRONTEND_PID 2>/dev/null" EXIT
|
||||||
|
wait
|
||||||
|
|
||||||
Reference in New Issue
Block a user