mirror of
https://github.com/thecyberlearn/quantumtaskai-caprover.git
synced 2026-08-18 08:52:57 +00:00
Remove non-essential files and reduce project bloat
Remove 29 unused files including: - Dokploy and Railway deployment configs - Multiple unused Dockerfiles - Debug/development scripts - Documentation and test files - Generated static files and logs Keep only files essential for CapRover deployment. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
200e8015e5
commit
2612019a61
@ -1,24 +0,0 @@
|
|||||||
# Required Environment Variables for Dokploy Deployment
|
|
||||||
|
|
||||||
# Django Core
|
|
||||||
SECRET_KEY=your-secret-key-here-generate-a-new-one
|
|
||||||
DEBUG=false
|
|
||||||
ALLOWED_HOSTS=yourdomain.com,www.yourdomain.com
|
|
||||||
|
|
||||||
# Database (PostgreSQL recommended for production)
|
|
||||||
DATABASE_URL=postgres://username:password@hostname:5432/database_name
|
|
||||||
|
|
||||||
# Optional - Email Configuration
|
|
||||||
EMAIL_HOST_USER=your-email@gmail.com
|
|
||||||
EMAIL_HOST_PASSWORD=your-app-password
|
|
||||||
|
|
||||||
# Optional - Stripe Payments
|
|
||||||
STRIPE_PUBLISHABLE_KEY=pk_test_your_stripe_publishable_key
|
|
||||||
STRIPE_SECRET_KEY=sk_test_your_stripe_secret_key
|
|
||||||
STRIPE_WEBHOOK_SECRET=whsec_your_webhook_secret
|
|
||||||
|
|
||||||
# Optional - Static Files (for custom S3/CDN)
|
|
||||||
# AWS_ACCESS_KEY_ID=your-aws-access-key
|
|
||||||
# AWS_SECRET_ACCESS_KEY=your-aws-secret-key
|
|
||||||
# AWS_STORAGE_BUCKET_NAME=your-bucket-name
|
|
||||||
# AWS_S3_REGION_NAME=us-east-1
|
|
||||||
@ -1,86 +0,0 @@
|
|||||||
# 🔐 Production Environment Variables Template
|
|
||||||
# Copy this file and replace placeholder values with your actual production values
|
|
||||||
# NEVER commit this file with real values to version control
|
|
||||||
|
|
||||||
# ========================================
|
|
||||||
# 🔒 CORE SECURITY SETTINGS
|
|
||||||
# ========================================
|
|
||||||
SECRET_KEY=django-insecure-REPLACE-WITH-50-RANDOM-CHARACTERS-FOR-PRODUCTION
|
|
||||||
DEBUG=False
|
|
||||||
ALLOWED_HOSTS=your-project-name.railway.app,quantumtaskai.com,www.quantumtaskai.com
|
|
||||||
CSRF_TRUSTED_ORIGINS=https://your-project-name.railway.app,https://quantumtaskai.com,https://www.quantumtaskai.com
|
|
||||||
|
|
||||||
# ========================================
|
|
||||||
# 📧 EMAIL CONFIGURATION
|
|
||||||
# ========================================
|
|
||||||
EMAIL_BACKEND=django.core.mail.backends.smtp.EmailBackend
|
|
||||||
EMAIL_HOST=smtp.gmail.com
|
|
||||||
EMAIL_PORT=587
|
|
||||||
EMAIL_USE_TLS=True
|
|
||||||
EMAIL_HOST_USER=your-email@gmail.com
|
|
||||||
EMAIL_HOST_PASSWORD=your-16-character-app-password
|
|
||||||
DEFAULT_FROM_EMAIL=Quantum Tasks AI <noreply@quantumtaskai.com>
|
|
||||||
|
|
||||||
# ========================================
|
|
||||||
# 💳 STRIPE PAYMENT CONFIGURATION
|
|
||||||
# ========================================
|
|
||||||
STRIPE_SECRET_KEY=sk_live_your_stripe_secret_key_here
|
|
||||||
STRIPE_WEBHOOK_SECRET=whsec_your_webhook_endpoint_secret
|
|
||||||
|
|
||||||
# ========================================
|
|
||||||
# 🤖 N8N AI AGENT WEBHOOKS (External Server)
|
|
||||||
# ========================================
|
|
||||||
# IMPORTANT: These URLs point to your SEPARATE N8N instance
|
|
||||||
# Replace with your actual N8N webhook URLs
|
|
||||||
|
|
||||||
# Option A: N8N Cloud
|
|
||||||
N8N_WEBHOOK_DATA_ANALYZER=https://yourworkspace.app.n8n.cloud/webhook/data-analyzer
|
|
||||||
N8N_WEBHOOK_FIVE_WHYS=https://yourworkspace.app.n8n.cloud/webhook/five-whys
|
|
||||||
N8N_WEBHOOK_JOB_POSTING=https://yourworkspace.app.n8n.cloud/webhook/job-posting
|
|
||||||
N8N_WEBHOOK_SOCIAL_ADS=https://yourworkspace.app.n8n.cloud/webhook/social-ads
|
|
||||||
|
|
||||||
# Option B: Self-hosted N8N (comment out Option A if using this)
|
|
||||||
# N8N_WEBHOOK_DATA_ANALYZER=https://your-n8n-server.com/webhook/data-analyzer
|
|
||||||
# N8N_WEBHOOK_FIVE_WHYS=https://your-n8n-server.com/webhook/five-whys
|
|
||||||
# N8N_WEBHOOK_JOB_POSTING=https://your-n8n-server.com/webhook/job-posting
|
|
||||||
# N8N_WEBHOOK_SOCIAL_ADS=https://your-n8n-server.com/webhook/social-ads
|
|
||||||
|
|
||||||
# ========================================
|
|
||||||
# 🌤️ EXTERNAL API KEYS
|
|
||||||
# ========================================
|
|
||||||
OPENWEATHER_API_KEY=your_openweather_api_key_here
|
|
||||||
|
|
||||||
# ========================================
|
|
||||||
# ⚡ PERFORMANCE & CACHING (Optional)
|
|
||||||
# ========================================
|
|
||||||
# Redis URL - Automatically set by Railway Redis service
|
|
||||||
# REDIS_URL=redis://default:password@host:port
|
|
||||||
|
|
||||||
# ========================================
|
|
||||||
# 🔍 MONITORING & DEBUGGING
|
|
||||||
# ========================================
|
|
||||||
# Optional: Set to your admin email for notifications
|
|
||||||
ADMIN_EMAIL=abhay@quantumtaskai.com
|
|
||||||
|
|
||||||
# ========================================
|
|
||||||
# 📊 ANALYTICS (Optional)
|
|
||||||
# ========================================
|
|
||||||
# Add analytics service keys if needed
|
|
||||||
# GOOGLE_ANALYTICS_ID=your_ga_id_here
|
|
||||||
|
|
||||||
# ========================================
|
|
||||||
# NOTES FOR SETUP
|
|
||||||
# ========================================
|
|
||||||
# 1. Generate SECRET_KEY using: python -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())"
|
|
||||||
# 2. EMAIL_HOST_PASSWORD should be Gmail App Password (16 characters), not regular password
|
|
||||||
# 3. Use LIVE Stripe keys for production (sk_live_... and whsec_...)
|
|
||||||
# 4. N8N webhooks must be on external server accessible via HTTPS
|
|
||||||
# 5. Test all variables before deploying to production
|
|
||||||
|
|
||||||
# ========================================
|
|
||||||
# RAILWAY AUTOMATIC VARIABLES
|
|
||||||
# ========================================
|
|
||||||
# These are automatically set by Railway - DO NOT SET MANUALLY:
|
|
||||||
# - DATABASE_URL (PostgreSQL connection string)
|
|
||||||
# - PORT (Application port)
|
|
||||||
# - RAILWAY_* (Railway-specific variables)
|
|
||||||
@ -1,43 +0,0 @@
|
|||||||
# Railway Environment Variables Template
|
|
||||||
# Copy this to Railway dashboard for environment-specific deployments
|
|
||||||
|
|
||||||
# Django Settings
|
|
||||||
DEBUG=False
|
|
||||||
SECRET_KEY=your-production-secret-key-here
|
|
||||||
ALLOWED_HOSTS=your-domain.railway.app,www.quantumtaskai.com
|
|
||||||
|
|
||||||
# Database
|
|
||||||
DATABASE_URL=postgresql://user:password@host:port/database
|
|
||||||
|
|
||||||
# Stripe Configuration
|
|
||||||
STRIPE_PUBLISHABLE_KEY=pk_live_your_publishable_key
|
|
||||||
STRIPE_SECRET_KEY=sk_live_your_secret_key
|
|
||||||
STRIPE_WEBHOOK_SECRET=whsec_your_webhook_secret
|
|
||||||
|
|
||||||
# Email Configuration
|
|
||||||
EMAIL_HOST=smtp.gmail.com
|
|
||||||
EMAIL_PORT=587
|
|
||||||
EMAIL_USE_TLS=True
|
|
||||||
EMAIL_HOST_USER=your-email@gmail.com
|
|
||||||
EMAIL_HOST_PASSWORD=your-app-password
|
|
||||||
|
|
||||||
# Admin Configuration
|
|
||||||
DJANGO_SUPERUSER_USERNAME=admin
|
|
||||||
DJANGO_SUPERUSER_EMAIL=admin@quantumtaskai.com
|
|
||||||
DJANGO_SUPERUSER_PASSWORD=your-secure-admin-password
|
|
||||||
|
|
||||||
# N8N Webhook URLs (Production)
|
|
||||||
N8N_WEBHOOK_DATA_ANALYZER=https://your-n8n-instance.com/webhook/data-analyzer
|
|
||||||
N8N_WEBHOOK_SOCIAL_ADS=https://your-n8n-instance.com/webhook/social-ads
|
|
||||||
N8N_WEBHOOK_JOB_POSTING=https://your-n8n-instance.com/webhook/job-posting
|
|
||||||
N8N_WEBHOOK_FIVE_WHYS=https://your-n8n-instance.com/webhook/five-whys
|
|
||||||
|
|
||||||
# Security Settings
|
|
||||||
SECURE_SSL_REDIRECT=True
|
|
||||||
SECURE_HSTS_SECONDS=31536000
|
|
||||||
SECURE_HSTS_INCLUDE_SUBDOMAINS=True
|
|
||||||
SECURE_FRAME_DENY=True
|
|
||||||
|
|
||||||
# Deployment Control
|
|
||||||
DEPLOYMENT_ENVIRONMENT=production # production, staging, development
|
|
||||||
BRANCH_NAME=main # Track which branch is deployed
|
|
||||||
@ -1,172 +0,0 @@
|
|||||||
# CapRover Deployment Guide - Quantum Tasks AI
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
Step-by-step guide for deploying the Quantum Tasks AI Django application on CapRover.
|
|
||||||
|
|
||||||
## Prerequisites
|
|
||||||
- CapRover installed and running on your VPS
|
|
||||||
- GitHub repository with the project
|
|
||||||
- Basic understanding of Django and CapRover
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Part 1: Project Setup
|
|
||||||
|
|
||||||
### Required Files
|
|
||||||
Your repository contains these CapRover-ready files:
|
|
||||||
```
|
|
||||||
quantumtaskai-caprover/
|
|
||||||
├── captain-definition # CapRover configuration
|
|
||||||
├── Dockerfile.captain # Production Docker setup
|
|
||||||
├── requirements.txt # Essential Python dependencies
|
|
||||||
├── .dockerignore # Docker build optimization
|
|
||||||
└── netcop_hub/settings.py # Django settings with production support
|
|
||||||
```
|
|
||||||
|
|
||||||
### Key Features
|
|
||||||
- **Database**: Supports SQLite (dev), PostgreSQL (production)
|
|
||||||
- **Static Files**: WhiteNoise for production serving
|
|
||||||
- **Environment Variables**: Production-ready configuration
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Part 2: CapRover Deployment
|
|
||||||
|
|
||||||
### Step 1: Create New App
|
|
||||||
1. **Open CapRover Dashboard**
|
|
||||||
2. **Apps → Create New App**
|
|
||||||
3. **App Name**: `quantumtaskai` (or your preferred name)
|
|
||||||
4. **Click "Create New App"**
|
|
||||||
|
|
||||||
### Step 2: Configure GitHub Deployment
|
|
||||||
1. **Go to**: App → Deployment Tab
|
|
||||||
2. **Method**: Deploy from GitHub
|
|
||||||
3. **Repository**: `https://github.com/thecyberlearn/quantumtaskai-caprover.git`
|
|
||||||
4. **Branch**: `main`
|
|
||||||
5. **Authentication**: Use GitHub Personal Access Token
|
|
||||||
|
|
||||||
### Step 3: Environment Variables
|
|
||||||
**Go to**: App Configs → Environment Variables → Bulk Edit
|
|
||||||
|
|
||||||
**Essential Variables:**
|
|
||||||
```env
|
|
||||||
SECRET_KEY=your-unique-secret-key-here
|
|
||||||
DEBUG=false
|
|
||||||
ALLOWED_HOSTS=yourapp.yourdomain.com
|
|
||||||
DATABASE_URL=postgres://user:password@host:5432/database
|
|
||||||
```
|
|
||||||
|
|
||||||
**Optional Variables:**
|
|
||||||
```env
|
|
||||||
# Email Configuration (for notifications)
|
|
||||||
EMAIL_HOST_USER=your-email@gmail.com
|
|
||||||
EMAIL_HOST_PASSWORD=your-app-password
|
|
||||||
|
|
||||||
# Stripe Configuration (for payments)
|
|
||||||
STRIPE_SECRET_KEY=sk_test_your_stripe_key
|
|
||||||
STRIPE_WEBHOOK_SECRET=whsec_your_webhook_secret
|
|
||||||
```
|
|
||||||
|
|
||||||
### Step 4: Deploy Application
|
|
||||||
1. **Deployment Tab** → **Deploy Now**
|
|
||||||
2. **Monitor build logs** for successful completion
|
|
||||||
3. **Check App URL** after deployment completes
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Part 3: Database Setup (Optional)
|
|
||||||
|
|
||||||
If you need PostgreSQL database:
|
|
||||||
|
|
||||||
### Option A: CapRover PostgreSQL
|
|
||||||
1. **One-Click Apps** → **PostgreSQL**
|
|
||||||
2. **Create database instance**
|
|
||||||
3. **Get connection details** from app configs
|
|
||||||
4. **Add DATABASE_URL** to your app environment variables
|
|
||||||
|
|
||||||
### Option B: External Database
|
|
||||||
1. **Use Railway, Neon, or other PostgreSQL provider**
|
|
||||||
2. **Get connection string**
|
|
||||||
3. **Add to environment variables**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Part 4: Custom Domain (Optional)
|
|
||||||
|
|
||||||
1. **App Settings** → **HTTP Settings**
|
|
||||||
2. **Add your domain**: `yourdomain.com`
|
|
||||||
3. **Enable HTTPS**: Force HTTPS redirect
|
|
||||||
4. **Update DNS**: Point your domain to CapRover server IP
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Part 5: Post-Deployment
|
|
||||||
|
|
||||||
### Create Admin User
|
|
||||||
1. **App → Web Terminal**
|
|
||||||
2. **Run commands**:
|
|
||||||
```bash
|
|
||||||
python manage.py migrate
|
|
||||||
python manage.py createsuperuser
|
|
||||||
```
|
|
||||||
|
|
||||||
### Verify Deployment
|
|
||||||
1. **Visit your app URL**
|
|
||||||
2. **Check admin panel**: `/admin/`
|
|
||||||
3. **Test agent marketplace**: `/agents/`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### Build Failures
|
|
||||||
- **Check logs** in Deployment tab
|
|
||||||
- **Verify environment variables** are set
|
|
||||||
- **Ensure SECRET_KEY** is properly set
|
|
||||||
|
|
||||||
### Runtime Issues
|
|
||||||
- **Check App Logs** in CapRover dashboard
|
|
||||||
- **Verify DATABASE_URL** format
|
|
||||||
- **Check ALLOWED_HOSTS** includes your domain
|
|
||||||
|
|
||||||
### Database Issues
|
|
||||||
- **Run migrations**: `python manage.py migrate`
|
|
||||||
- **Check database connectivity**
|
|
||||||
- **Verify PostgreSQL is running** (if using)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Environment Variable Reference
|
|
||||||
|
|
||||||
| Variable | Required | Description |
|
|
||||||
|----------|----------|-------------|
|
|
||||||
| `SECRET_KEY` | Yes | Django secret key |
|
|
||||||
| `DEBUG` | Yes | Set to `false` for production |
|
|
||||||
| `ALLOWED_HOSTS` | Yes | Your domain name |
|
|
||||||
| `DATABASE_URL` | Optional | PostgreSQL connection string |
|
|
||||||
| `EMAIL_HOST_USER` | Optional | SMTP email username |
|
|
||||||
| `EMAIL_HOST_PASSWORD` | Optional | SMTP email password |
|
|
||||||
| `STRIPE_SECRET_KEY` | Optional | Stripe API key |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Success Checklist
|
|
||||||
|
|
||||||
- [ ] App builds successfully in CapRover
|
|
||||||
- [ ] Environment variables configured
|
|
||||||
- [ ] Database migrations completed
|
|
||||||
- [ ] Admin user created
|
|
||||||
- [ ] App accessible via URL
|
|
||||||
- [ ] Static files loading correctly
|
|
||||||
- [ ] Agent marketplace functional
|
|
||||||
|
|
||||||
Your Quantum Tasks AI application should now be live and ready to use!
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Support
|
|
||||||
|
|
||||||
For issues with:
|
|
||||||
- **CapRover deployment**: Check CapRover documentation
|
|
||||||
- **Django configuration**: Review `netcop_hub/settings.py`
|
|
||||||
- **Agent system**: See `agents/` directory structure
|
|
||||||
@ -1,32 +0,0 @@
|
|||||||
FROM python:3.11-slim
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# Install system dependencies
|
|
||||||
RUN apt-get update && apt-get install -y \
|
|
||||||
gcc \
|
|
||||||
libpq-dev \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# Copy and install Python dependencies
|
|
||||||
COPY requirements.txt .
|
|
||||||
RUN pip install --no-cache-dir -r requirements.txt
|
|
||||||
|
|
||||||
# Copy application code
|
|
||||||
COPY . .
|
|
||||||
|
|
||||||
# Set environment variables
|
|
||||||
ENV PYTHONUNBUFFERED=1 \
|
|
||||||
SECRET_KEY="build-time-dummy-key-change-in-production"
|
|
||||||
|
|
||||||
# Collect static files
|
|
||||||
RUN python manage.py collectstatic --noinput --settings=production_https_settings
|
|
||||||
|
|
||||||
# Make startup script executable
|
|
||||||
RUN chmod +x start-dokploy.sh
|
|
||||||
|
|
||||||
# Expose port 3000 for Dokploy
|
|
||||||
EXPOSE 3000
|
|
||||||
|
|
||||||
# Use startup script
|
|
||||||
CMD ["./start-dokploy.sh"]
|
|
||||||
@ -1,57 +0,0 @@
|
|||||||
FROM python:3.11-slim
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# Install system dependencies
|
|
||||||
RUN apt-get update && apt-get install -y \
|
|
||||||
gcc \
|
|
||||||
libpq-dev \
|
|
||||||
curl \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# Copy and install Python dependencies
|
|
||||||
COPY requirements.txt .
|
|
||||||
RUN pip install --no-cache-dir -r requirements.txt
|
|
||||||
|
|
||||||
# Copy application code
|
|
||||||
COPY . .
|
|
||||||
|
|
||||||
# Set environment variables
|
|
||||||
ENV PYTHONUNBUFFERED=1 \
|
|
||||||
DEBUG=true \
|
|
||||||
SECRET_KEY="build-time-dummy-key-change-in-production" \
|
|
||||||
ALLOWED_HOSTS="*"
|
|
||||||
|
|
||||||
# Collect static files
|
|
||||||
RUN python manage.py collectstatic --noinput --settings=debug_settings || true
|
|
||||||
|
|
||||||
# Make startup script executable
|
|
||||||
RUN chmod +x start-dokploy.sh
|
|
||||||
|
|
||||||
# Expose port 3000 for Dokploy
|
|
||||||
EXPOSE 3000
|
|
||||||
|
|
||||||
# Debug: Print Django info
|
|
||||||
RUN python manage.py --version
|
|
||||||
RUN python manage.py check --settings=debug_settings || true
|
|
||||||
|
|
||||||
# Start with debug info
|
|
||||||
CMD echo "🐛 Debug Mode - Django $(python manage.py --version)" && \
|
|
||||||
echo "🔍 Environment:" && \
|
|
||||||
echo " - DEBUG: $DEBUG" && \
|
|
||||||
echo " - ALLOWED_HOSTS: $ALLOWED_HOSTS" && \
|
|
||||||
echo " - SECRET_KEY: $(echo $SECRET_KEY | cut -c1-10)..." && \
|
|
||||||
echo "🌐 Testing Django config..." && \
|
|
||||||
python manage.py check --settings=debug_settings && \
|
|
||||||
echo "✅ Django config OK" && \
|
|
||||||
echo "🧪 Testing URL patterns..." && \
|
|
||||||
python manage.py show_urls --settings=debug_settings || echo "show_urls not available" && \
|
|
||||||
echo "🚀 Starting server with detailed logging..." && \
|
|
||||||
DJANGO_SETTINGS_MODULE=debug_settings gunicorn netcop_hub.wsgi:application
|
|
||||||
--bind 0.0.0.0:3000 \
|
|
||||||
--workers 1 \
|
|
||||||
--timeout 120 \
|
|
||||||
--log-level debug \
|
|
||||||
--access-logfile - \
|
|
||||||
--error-logfile - \
|
|
||||||
--capture-output
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
FROM python:3.11-slim
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# Create a simple test file
|
|
||||||
RUN echo "<h1>🚀 Container is Running!</h1><p>Port 3000 is accessible</p><p>Time: $(date)</p>" > index.html
|
|
||||||
|
|
||||||
# Expose port 3000
|
|
||||||
EXPOSE 3000
|
|
||||||
|
|
||||||
# Start simple HTTP server
|
|
||||||
CMD echo "🧪 Simple HTTP Server Test" && \
|
|
||||||
echo "📋 Container Details:" && \
|
|
||||||
echo " - Time: $(date)" && \
|
|
||||||
echo " - Port: 3000" && \
|
|
||||||
echo " - Files: $(ls -la)" && \
|
|
||||||
echo "🌐 Starting HTTP server on port 3000..." && \
|
|
||||||
python -m http.server 3000
|
|
||||||
@ -1,39 +0,0 @@
|
|||||||
FROM python:3.11-slim
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# Install system dependencies
|
|
||||||
RUN apt-get update && apt-get install -y \
|
|
||||||
gcc \
|
|
||||||
libpq-dev \
|
|
||||||
curl \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# Copy and install Python dependencies
|
|
||||||
COPY requirements.txt .
|
|
||||||
RUN pip install --no-cache-dir -r requirements.txt
|
|
||||||
|
|
||||||
# Copy application code
|
|
||||||
COPY . .
|
|
||||||
|
|
||||||
# Set minimal environment variables
|
|
||||||
ENV PYTHONUNBUFFERED=1 \
|
|
||||||
DEBUG=true \
|
|
||||||
SECRET_KEY="test-secret-key-123456789" \
|
|
||||||
ALLOWED_HOSTS="*"
|
|
||||||
|
|
||||||
# Expose port 3000
|
|
||||||
EXPOSE 3000
|
|
||||||
|
|
||||||
# Very simple test - just run a basic HTTP server
|
|
||||||
CMD echo "🧪 TEST MODE - Container is running!" && \
|
|
||||||
echo "📋 Environment Check:" && \
|
|
||||||
echo " - Python: $(python --version)" && \
|
|
||||||
echo " - Django: $(python -c 'import django; print(django.get_version())')" && \
|
|
||||||
echo " - Working directory: $(pwd)" && \
|
|
||||||
echo " - Files: $(ls -la | head -10)" && \
|
|
||||||
echo "" && \
|
|
||||||
echo "🌐 Testing Django..." && \
|
|
||||||
python manage.py check --settings=netcop_hub.settings && \
|
|
||||||
echo "✅ Django OK - Starting simple HTTP server on port 3000" && \
|
|
||||||
python -m http.server 3000
|
|
||||||
212
WARP.md
212
WARP.md
@ -1,212 +0,0 @@
|
|||||||
# WARP.md
|
|
||||||
|
|
||||||
This file provides guidance to WARP (warp.dev) when working with code in this repository.
|
|
||||||
|
|
||||||
## Project Overview
|
|
||||||
|
|
||||||
**Quantum Tasks AI** is a Django-based AI agent marketplace that allows users to browse, execute, and interact with various AI-powered tools and services. The application is designed for deployment on container platforms like CapRover and Dokploy.
|
|
||||||
|
|
||||||
### Core Architecture
|
|
||||||
|
|
||||||
- **Framework**: Django 5.2.4 with Django REST Framework
|
|
||||||
- **Database**: SQLite (development) / PostgreSQL (production)
|
|
||||||
- **Static Files**: WhiteNoise for production serving
|
|
||||||
- **Agent System**: File-based JSON configuration system
|
|
||||||
- **Authentication**: Custom User model with email verification
|
|
||||||
- **Payments**: Stripe integration for agent execution fees
|
|
||||||
- **Deployment**: Containerized with Docker, optimized for CapRover/Dokploy
|
|
||||||
|
|
||||||
### Application Structure
|
|
||||||
|
|
||||||
```
|
|
||||||
├── agents/ # AI agent marketplace and execution system
|
|
||||||
├── authentication/ # User management and authentication
|
|
||||||
├── core/ # Homepage, health checks, and utilities
|
|
||||||
├── wallet/ # Stripe payment integration
|
|
||||||
├── netcop_hub/ # Django project settings and configuration
|
|
||||||
├── static/ # Static assets (CSS, JS, images)
|
|
||||||
├── templates/ # Django HTML templates
|
|
||||||
└── agents/configs/ # File-based agent configurations
|
|
||||||
├── agents/ # Individual agent JSON files
|
|
||||||
└── categories/ # Agent categories configuration
|
|
||||||
```
|
|
||||||
|
|
||||||
## Development Commands
|
|
||||||
|
|
||||||
### Local Development Setup
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Install dependencies
|
|
||||||
pip install -r requirements.txt
|
|
||||||
|
|
||||||
# Database setup
|
|
||||||
python manage.py migrate
|
|
||||||
python manage.py createsuperuser
|
|
||||||
|
|
||||||
# Development server
|
|
||||||
python manage.py runserver
|
|
||||||
# OR use the development script
|
|
||||||
./run_dev.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
### Testing and Quality
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Run Django checks
|
|
||||||
python manage.py check
|
|
||||||
|
|
||||||
# Test database connection
|
|
||||||
python manage.py check --database default
|
|
||||||
|
|
||||||
# Clear agent cache (useful during development)
|
|
||||||
python manage.py shell -c "from agents.services import AgentFileService; AgentFileService.clear_cache()"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Static Files and Assets
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Collect static files for production
|
|
||||||
python manage.py collectstatic --noinput
|
|
||||||
|
|
||||||
# Clear cache table
|
|
||||||
python manage.py createcachetable
|
|
||||||
```
|
|
||||||
|
|
||||||
## Agent System Architecture
|
|
||||||
|
|
||||||
### File-Based Configuration
|
|
||||||
The application uses a file-based agent system instead of database models for agent configurations:
|
|
||||||
|
|
||||||
- **Agent configs**: `agents/configs/agents/*.json`
|
|
||||||
- **Categories**: `agents/configs/categories/categories.json`
|
|
||||||
- **Service class**: `AgentFileService` handles loading and caching
|
|
||||||
|
|
||||||
### Agent Configuration Format
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"slug": "agent-identifier",
|
|
||||||
"name": "Human Readable Name",
|
|
||||||
"description": "Detailed description",
|
|
||||||
"category": "category-slug",
|
|
||||||
"price": 0.0,
|
|
||||||
"agent_type": "form",
|
|
||||||
"system_type": "webhook",
|
|
||||||
"webhook_url": "https://external-service.com/webhook",
|
|
||||||
"form_schema": {
|
|
||||||
"fields": [
|
|
||||||
{"name": "input", "type": "text", "label": "Input Field"}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Agent Execution Flow
|
|
||||||
1. User selects agent from marketplace (`/agents/`)
|
|
||||||
2. Fills out dynamic form based on `form_schema`
|
|
||||||
3. Payment processed via Stripe (if price > 0)
|
|
||||||
4. Request sent to agent's `webhook_url`
|
|
||||||
5. Response stored in `AgentExecution` model
|
|
||||||
6. Results displayed to user
|
|
||||||
|
|
||||||
## Deployment Configurations
|
|
||||||
|
|
||||||
### CapRover Deployment
|
|
||||||
- **Docker file**: `Dockerfile.captain`
|
|
||||||
- **Configuration**: `captain-definition`
|
|
||||||
- **Port**: 80
|
|
||||||
- **Startup**: Direct gunicorn execution
|
|
||||||
|
|
||||||
### Dokploy Deployment
|
|
||||||
- **Docker file**: `Dockerfile.dokploy`
|
|
||||||
- **Configuration**: `dokploy.json`
|
|
||||||
- **Port**: 3000
|
|
||||||
- **Startup**: `start-dokploy.sh` script with migrations
|
|
||||||
|
|
||||||
### Environment Variables
|
|
||||||
|
|
||||||
**Required for Production:**
|
|
||||||
```env
|
|
||||||
SECRET_KEY=your-secret-key-here
|
|
||||||
DEBUG=false
|
|
||||||
ALLOWED_HOSTS=yourdomain.com,www.yourdomain.com
|
|
||||||
```
|
|
||||||
|
|
||||||
**Optional:**
|
|
||||||
```env
|
|
||||||
DATABASE_URL=postgres://user:pass@host:5432/db
|
|
||||||
EMAIL_HOST_USER=your-email@gmail.com
|
|
||||||
EMAIL_HOST_PASSWORD=your-app-password
|
|
||||||
STRIPE_SECRET_KEY=sk_live_your_stripe_key
|
|
||||||
```
|
|
||||||
|
|
||||||
**Platform-Specific:**
|
|
||||||
```env
|
|
||||||
# CapRover auto-detection
|
|
||||||
CAPROVER_GIT_COMMIT_SHA=auto-set-by-caprover
|
|
||||||
|
|
||||||
# Dokploy auto-detection
|
|
||||||
DOKPLOY_PROJECT_NAME=your-project-name
|
|
||||||
```
|
|
||||||
|
|
||||||
## Key Application Features
|
|
||||||
|
|
||||||
### Authentication System
|
|
||||||
- Custom User model with email verification
|
|
||||||
- Password reset functionality
|
|
||||||
- User wallet balance tracking
|
|
||||||
- Session management with security headers
|
|
||||||
|
|
||||||
### Payment Integration
|
|
||||||
- Stripe checkout for agent executions
|
|
||||||
- Wallet balance system
|
|
||||||
- Transaction logging
|
|
||||||
- Webhook handling for payment confirmations
|
|
||||||
|
|
||||||
### Agent Marketplace
|
|
||||||
- Category-based organization
|
|
||||||
- Search and filtering capabilities
|
|
||||||
- Dynamic form generation based on agent schemas
|
|
||||||
- Execution history tracking
|
|
||||||
|
|
||||||
### Security Features
|
|
||||||
- CSRF protection with trusted origins
|
|
||||||
- Rate limiting on critical endpoints
|
|
||||||
- Security headers (CSP, XSS protection)
|
|
||||||
- Input validation and sanitization
|
|
||||||
- Error handling with custom error pages
|
|
||||||
|
|
||||||
## Troubleshooting Common Issues
|
|
||||||
|
|
||||||
### Dokploy 404 Errors
|
|
||||||
If getting 404 errors on Dokploy:
|
|
||||||
1. Ensure `ALLOWED_HOSTS` includes the Dokploy domain
|
|
||||||
2. Check that port 3000 is correctly configured
|
|
||||||
3. Verify health check endpoint `/health/` is accessible
|
|
||||||
4. Use debug configuration temporarily: `Dockerfile.dokploy.debug`
|
|
||||||
|
|
||||||
### Database Issues
|
|
||||||
- SQLite is used for development (no setup required)
|
|
||||||
- PostgreSQL for production (requires `DATABASE_URL`)
|
|
||||||
- Run migrations after deployment: `python manage.py migrate`
|
|
||||||
|
|
||||||
### Static Files Problems
|
|
||||||
- Ensure `python manage.py collectstatic` runs during build
|
|
||||||
- WhiteNoise handles static file serving in production
|
|
||||||
- Check `STATIC_ROOT` and `STATICFILES_DIRS` configuration
|
|
||||||
|
|
||||||
### Agent Loading Issues
|
|
||||||
- Agent configs are cached for performance
|
|
||||||
- Clear cache during development: `AgentFileService.clear_cache()`
|
|
||||||
- Check JSON syntax in agent configuration files
|
|
||||||
- Ensure required fields are present in agent schemas
|
|
||||||
|
|
||||||
## Important File Locations
|
|
||||||
|
|
||||||
- **Main settings**: `netcop_hub/settings.py`
|
|
||||||
- **URL configuration**: `netcop_hub/urls.py`
|
|
||||||
- **Agent service**: `agents/services.py`
|
|
||||||
- **Health check**: `core/views.py` (health_check_view)
|
|
||||||
- **Error handlers**: `core/error_views.py`
|
|
||||||
- **Production startup**: `start-dokploy.sh`
|
|
||||||
|
|
||||||
This Django application is optimized for containerized deployment with focus on AI agent marketplace functionality, file-based configuration management, and production-ready security features.
|
|
||||||
@ -1,210 +0,0 @@
|
|||||||
"""
|
|
||||||
Brand Digital Presence Analyzer
|
|
||||||
|
|
||||||
Python implementation for analyzing brand presence across 14 major digital platforms
|
|
||||||
using Groq for fast and cost-effective AI analysis.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import json
|
|
||||||
import logging
|
|
||||||
from groq import Groq
|
|
||||||
from datetime import datetime
|
|
||||||
from typing import Dict, Any, Optional
|
|
||||||
from django.conf import settings
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
class BrandPresenceAnalyzer:
|
|
||||||
"""
|
|
||||||
Analyzes brand digital presence across major platforms using Groq AI.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
"""Initialize the analyzer with Groq configuration."""
|
|
||||||
self.client = None
|
|
||||||
if settings.GROQ_API_KEY:
|
|
||||||
self.client = Groq(api_key=settings.GROQ_API_KEY)
|
|
||||||
else:
|
|
||||||
logger.warning("Groq API key not configured")
|
|
||||||
|
|
||||||
def analyze_brand_presence(self, brand_name: str, website_url: str) -> Dict[str, Any]:
|
|
||||||
"""
|
|
||||||
Analyze brand presence across 14 digital platforms.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
brand_name: The brand name to search for
|
|
||||||
website_url: The brand's official website URL
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Dictionary containing analysis results in structured format
|
|
||||||
"""
|
|
||||||
if not self.client:
|
|
||||||
return self._create_error_response("Groq API key not configured")
|
|
||||||
|
|
||||||
if not brand_name or not website_url:
|
|
||||||
return self._create_error_response("Brand name and website URL are required")
|
|
||||||
|
|
||||||
try:
|
|
||||||
logger.info(f"Starting brand presence analysis for: {brand_name}")
|
|
||||||
|
|
||||||
# Create the analysis prompt
|
|
||||||
prompt = self._create_analysis_prompt(brand_name, website_url)
|
|
||||||
|
|
||||||
# Call Groq API
|
|
||||||
response = self.client.chat.completions.create(
|
|
||||||
model="llama-3.1-8b-instant", # Fast and current model
|
|
||||||
messages=[
|
|
||||||
{
|
|
||||||
"role": "system",
|
|
||||||
"content": "You are a digital marketing analyst. Return only valid JSON with no additional text or formatting."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"role": "user",
|
|
||||||
"content": prompt
|
|
||||||
}
|
|
||||||
],
|
|
||||||
temperature=0.3,
|
|
||||||
max_tokens=2500
|
|
||||||
)
|
|
||||||
|
|
||||||
# Extract and parse the response
|
|
||||||
ai_response = response.choices[0].message.content.strip()
|
|
||||||
logger.info(f"Received AI response for {brand_name}")
|
|
||||||
|
|
||||||
# Parse JSON response
|
|
||||||
try:
|
|
||||||
result = json.loads(ai_response)
|
|
||||||
return self._format_success_response(result, brand_name, website_url)
|
|
||||||
except json.JSONDecodeError as e:
|
|
||||||
logger.error(f"Failed to parse AI response as JSON: {e}")
|
|
||||||
logger.error(f"Raw response: {ai_response}")
|
|
||||||
return self._create_error_response("Invalid response format from AI")
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Error during brand presence analysis: {e}")
|
|
||||||
return self._create_error_response(f"Analysis failed: {str(e)}")
|
|
||||||
|
|
||||||
def _create_analysis_prompt(self, brand_name: str, website_url: str) -> str:
|
|
||||||
"""Create the detailed analysis prompt for the AI."""
|
|
||||||
return f"""
|
|
||||||
You are a digital marketing analyst specializing in brand presence research. Analyze the given brand's presence across 14 major digital platforms.
|
|
||||||
|
|
||||||
BRAND INFORMATION:
|
|
||||||
Brand Name: {brand_name}
|
|
||||||
Website: {website_url}
|
|
||||||
|
|
||||||
PLATFORMS TO ANALYZE:
|
|
||||||
1. Google Business
|
|
||||||
2. LinkedIn (Company Pages)
|
|
||||||
3. YouTube
|
|
||||||
4. TikTok
|
|
||||||
5. Instagram
|
|
||||||
6. Pinterest
|
|
||||||
7. X (Twitter)
|
|
||||||
8. Facebook (Business Pages)
|
|
||||||
9. Medium
|
|
||||||
10. Tumblr
|
|
||||||
11. Threads
|
|
||||||
12. Quora
|
|
||||||
13. Reddit
|
|
||||||
14. Blue Sky
|
|
||||||
|
|
||||||
SEARCH METHODOLOGY:
|
|
||||||
- Search for exact brand name matches
|
|
||||||
- Try variations (official, verified, brand + industry terms)
|
|
||||||
- Cross-reference with the provided website URL
|
|
||||||
- Look for verification badges and official indicators
|
|
||||||
- Assess account activity and authenticity
|
|
||||||
|
|
||||||
RETURN ONLY THIS JSON FORMAT (no additional text):
|
|
||||||
|
|
||||||
{{
|
|
||||||
"platforms": [
|
|
||||||
{{
|
|
||||||
"name": "Google Business",
|
|
||||||
"found": true,
|
|
||||||
"verified": true,
|
|
||||||
"profile_url": "https://example.com/profile",
|
|
||||||
"confidence": "high",
|
|
||||||
"notes": "Verified business listing with reviews"
|
|
||||||
}},
|
|
||||||
{{
|
|
||||||
"name": "LinkedIn",
|
|
||||||
"found": false,
|
|
||||||
"verified": null,
|
|
||||||
"profile_url": null,
|
|
||||||
"confidence": null,
|
|
||||||
"notes": "No official company page found"
|
|
||||||
}}
|
|
||||||
],
|
|
||||||
"summary": {{
|
|
||||||
"total_platforms_checked": 14,
|
|
||||||
"platforms_found": 8,
|
|
||||||
"platforms_missing": 6,
|
|
||||||
"completion_percentage": 57
|
|
||||||
}},
|
|
||||||
"recommendations": [
|
|
||||||
{{
|
|
||||||
"platform": "LinkedIn",
|
|
||||||
"priority": "high",
|
|
||||||
"reason": "Essential for B2B networking and credibility"
|
|
||||||
}}
|
|
||||||
]
|
|
||||||
}}
|
|
||||||
|
|
||||||
IMPORTANT:
|
|
||||||
- Return ONLY valid JSON
|
|
||||||
- Set confidence as "high", "medium", or "low"
|
|
||||||
- Use null for missing data
|
|
||||||
- Include brief, helpful notes for each platform
|
|
||||||
- Focus on official business accounts, not personal profiles
|
|
||||||
- If unsure, mark confidence as "low" and explain in notes
|
|
||||||
- Ensure all 14 platforms are included in the platforms array
|
|
||||||
"""
|
|
||||||
|
|
||||||
def _format_success_response(self, ai_result: Dict, brand_name: str, website_url: str) -> Dict[str, Any]:
|
|
||||||
"""Format the successful analysis response."""
|
|
||||||
return {
|
|
||||||
"status": "success",
|
|
||||||
"brand_analysis": {
|
|
||||||
"brand_name": brand_name,
|
|
||||||
"website": website_url,
|
|
||||||
"analysis_date": datetime.now().isoformat(),
|
|
||||||
"processing_time": "AI-powered analysis"
|
|
||||||
},
|
|
||||||
"data": ai_result,
|
|
||||||
"meta": {
|
|
||||||
"analyzer_version": "1.0",
|
|
||||||
"platforms_supported": 14,
|
|
||||||
"analysis_method": "AI-powered research"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def _create_error_response(self, error_message: str) -> Dict[str, Any]:
|
|
||||||
"""Create standardized error response."""
|
|
||||||
return {
|
|
||||||
"status": "error",
|
|
||||||
"error": {
|
|
||||||
"message": error_message,
|
|
||||||
"timestamp": datetime.now().isoformat(),
|
|
||||||
"code": "ANALYSIS_FAILED"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Global analyzer instance - commented out to avoid import-time initialization
|
|
||||||
# analyzer = BrandPresenceAnalyzer()
|
|
||||||
|
|
||||||
def analyze_brand_presence(brand_name: str, website_url: str) -> Dict[str, Any]:
|
|
||||||
"""
|
|
||||||
Convenience function for analyzing brand presence.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
brand_name: The brand name to analyze
|
|
||||||
website_url: The brand's website URL
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Analysis results dictionary
|
|
||||||
"""
|
|
||||||
# Create analyzer instance when needed to avoid import-time initialization
|
|
||||||
analyzer = BrandPresenceAnalyzer()
|
|
||||||
return analyzer.analyze_brand_presence(brand_name, website_url)
|
|
||||||
File diff suppressed because it is too large
Load Diff
12
build.sh
12
build.sh
@ -1,12 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Build script for Render deployment
|
|
||||||
|
|
||||||
set -o errexit # exit on error
|
|
||||||
|
|
||||||
echo "Installing dependencies..."
|
|
||||||
pip install -r requirements.txt
|
|
||||||
|
|
||||||
echo "Collecting static files..."
|
|
||||||
python manage.py collectstatic --noinput
|
|
||||||
|
|
||||||
echo "Build completed successfully!"
|
|
||||||
@ -1,33 +0,0 @@
|
|||||||
"""
|
|
||||||
Debug middleware for troubleshooting Dokploy 404 issues
|
|
||||||
"""
|
|
||||||
import logging
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
class DebugRequestMiddleware:
|
|
||||||
"""Middleware to log all incoming requests for debugging"""
|
|
||||||
|
|
||||||
def __init__(self, get_response):
|
|
||||||
self.get_response = get_response
|
|
||||||
|
|
||||||
def __call__(self, request):
|
|
||||||
# Log incoming request details
|
|
||||||
logger.info(f"🌐 INCOMING REQUEST:")
|
|
||||||
logger.info(f" - Method: {request.method}")
|
|
||||||
logger.info(f" - Path: {request.path}")
|
|
||||||
logger.info(f" - Full Path: {request.get_full_path()}")
|
|
||||||
logger.info(f" - Host: {request.get_host()}")
|
|
||||||
logger.info(f" - User Agent: {request.META.get('HTTP_USER_AGENT', 'Unknown')[:100]}")
|
|
||||||
logger.info(f" - Remote IP: {request.META.get('REMOTE_ADDR', 'Unknown')}")
|
|
||||||
logger.info(f" - Headers: {dict(request.headers)}")
|
|
||||||
|
|
||||||
# Process request
|
|
||||||
response = self.get_response(request)
|
|
||||||
|
|
||||||
# Log response
|
|
||||||
logger.info(f"📤 RESPONSE:")
|
|
||||||
logger.info(f" - Status Code: {response.status_code}")
|
|
||||||
logger.info(f" - Content Type: {response.get('Content-Type', 'Unknown')}")
|
|
||||||
|
|
||||||
return response
|
|
||||||
@ -1,32 +0,0 @@
|
|||||||
# Debug settings for Dokploy troubleshooting
|
|
||||||
from netcop_hub.settings import *
|
|
||||||
|
|
||||||
# Enable debug mode
|
|
||||||
DEBUG = True
|
|
||||||
|
|
||||||
# Add debug middleware at the top
|
|
||||||
MIDDLEWARE = ['debug_middleware.DebugRequestMiddleware'] + MIDDLEWARE
|
|
||||||
|
|
||||||
# Enhanced logging
|
|
||||||
LOGGING['loggers']['root']['level'] = 'DEBUG'
|
|
||||||
LOGGING['handlers']['console']['level'] = 'DEBUG'
|
|
||||||
|
|
||||||
# Print all URLs at startup
|
|
||||||
print("🔗 Available URL patterns:")
|
|
||||||
try:
|
|
||||||
from django.urls import get_resolver
|
|
||||||
resolver = get_resolver()
|
|
||||||
url_patterns = []
|
|
||||||
|
|
||||||
def extract_patterns(patterns, prefix=''):
|
|
||||||
for pattern in patterns:
|
|
||||||
if hasattr(pattern, 'url_patterns'):
|
|
||||||
extract_patterns(pattern.url_patterns, prefix + str(pattern.pattern))
|
|
||||||
else:
|
|
||||||
url_patterns.append(prefix + str(pattern.pattern))
|
|
||||||
|
|
||||||
extract_patterns(resolver.url_patterns)
|
|
||||||
for pattern in url_patterns[:20]: # Show first 20
|
|
||||||
print(f" - {pattern}")
|
|
||||||
except Exception as e:
|
|
||||||
print(f" - Error loading URL patterns: {e}")
|
|
||||||
@ -1,54 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# Deployment helper script for Dokploy
|
|
||||||
# This script helps configure environment variables before deployment
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "🚀 Dokploy Deployment Configuration Helper"
|
|
||||||
echo "=========================================="
|
|
||||||
|
|
||||||
# Get domain from user
|
|
||||||
read -p "Enter your domain (e.g., quamtumtaskai.netcoptech.com): " DOMAIN
|
|
||||||
if [ -z "$DOMAIN" ]; then
|
|
||||||
echo "❌ Domain is required"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Generate secret key if not provided
|
|
||||||
if [ -z "$SECRET_KEY" ]; then
|
|
||||||
echo "🔑 Generating SECRET_KEY..."
|
|
||||||
SECRET_KEY=$(python -c 'from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())')
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Set default environment variables
|
|
||||||
export DOMAIN="$DOMAIN"
|
|
||||||
export SECRET_KEY="$SECRET_KEY"
|
|
||||||
export DEBUG="false"
|
|
||||||
export ALLOWED_HOSTS="$DOMAIN,*"
|
|
||||||
export CSRF_TRUSTED_ORIGINS="https://$DOMAIN,http://$DOMAIN"
|
|
||||||
export SECURE_SSL_REDIRECT="false"
|
|
||||||
export SECURE_PROXY_SSL_HEADER="HTTP_X_FORWARDED_PROTO,https"
|
|
||||||
export DOKPLOY_PROJECT_NAME="quantum-tasks-ai"
|
|
||||||
export PYTHONUNBUFFERED="1"
|
|
||||||
|
|
||||||
echo "✅ Configuration complete:"
|
|
||||||
echo " - Domain: $DOMAIN"
|
|
||||||
echo " - SECRET_KEY: ${SECRET_KEY:0:20}..."
|
|
||||||
echo " - ALLOWED_HOSTS: $ALLOWED_HOSTS"
|
|
||||||
echo " - SSL Redirect: $SECURE_SSL_REDIRECT"
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "📋 Environment variables to set in Dokploy:"
|
|
||||||
echo "DOMAIN=$DOMAIN"
|
|
||||||
echo "SECRET_KEY=$SECRET_KEY"
|
|
||||||
echo "DEBUG=false"
|
|
||||||
echo "ALLOWED_HOSTS=$ALLOWED_HOSTS"
|
|
||||||
echo "CSRF_TRUSTED_ORIGINS=$CSRF_TRUSTED_ORIGINS"
|
|
||||||
echo "SECURE_SSL_REDIRECT=false"
|
|
||||||
echo "SECURE_PROXY_SSL_HEADER=HTTP_X_FORWARDED_PROTO,https"
|
|
||||||
echo "DOKPLOY_PROJECT_NAME=quantum-tasks-ai"
|
|
||||||
echo "PYTHONUNBUFFERED=1"
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "🔄 After setting these variables in Dokploy, trigger a redeploy."
|
|
||||||
echo "🌐 Your app should be accessible at: https://$DOMAIN"
|
|
||||||
@ -1,46 +0,0 @@
|
|||||||
# Simple Agent Creation Guide
|
|
||||||
|
|
||||||
## Quick Agent Creation
|
|
||||||
|
|
||||||
1. **Create JSON file** in `agents/configs/agents/your-agent-name.json`
|
|
||||||
2. **Add basic config**:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"name": "Your Agent Name",
|
|
||||||
"description": "What your agent does",
|
|
||||||
"category": "productivity",
|
|
||||||
"price": 5,
|
|
||||||
"webhook_url": "https://your-webhook-endpoint.com",
|
|
||||||
"form_schema": {
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"name": "input",
|
|
||||||
"type": "text",
|
|
||||||
"label": "Your Input",
|
|
||||||
"required": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Restart server** - Agent appears automatically
|
|
||||||
|
|
||||||
## Available Categories
|
|
||||||
|
|
||||||
Edit `agents/configs/categories/categories.json`:
|
|
||||||
- `productivity` - Work tools
|
|
||||||
- `content` - Content creation
|
|
||||||
- `analysis` - Data analysis
|
|
||||||
- `communication` - Communication tools
|
|
||||||
|
|
||||||
## Field Types
|
|
||||||
|
|
||||||
- `text` - Single line text
|
|
||||||
- `textarea` - Multi-line text
|
|
||||||
- `number` - Numeric input
|
|
||||||
- `email` - Email input
|
|
||||||
- `file` - File upload
|
|
||||||
|
|
||||||
That's it! Your agent will appear in the marketplace.
|
|
||||||
@ -1,152 +0,0 @@
|
|||||||
# Agent Request Template
|
|
||||||
|
|
||||||
Use this template when requesting new agents for quick, error-free creation using the modern file-based system.
|
|
||||||
|
|
||||||
## How to Use This Template
|
|
||||||
|
|
||||||
1. **Copy the template below**
|
|
||||||
2. **Fill in all required fields**
|
|
||||||
3. **Provide to Claude Code** with the request "Create agent using this template"
|
|
||||||
4. **Claude will handle** JSON config creation and deployment
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Agent Request Template
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
## New Agent Request
|
|
||||||
|
|
||||||
**Agent Name**: [Enter the display name for the agent]
|
|
||||||
**Type**: [Webhook OR Direct Access]
|
|
||||||
**Category**: [Choose from: analysis, career-education, document-processing, human-resources, marketing, consulting]
|
|
||||||
**Price**: [X.XX AED or 0.0 for FREE]
|
|
||||||
**Short Description**: [Brief 1-line description for marketplace]
|
|
||||||
**Full Description**: [Detailed description of what the agent does and its benefits]
|
|
||||||
|
|
||||||
### For Webhook Agents Only:
|
|
||||||
**Form Fields**:
|
|
||||||
- Field 1: [name: field_name, type: text/textarea/select/file/url/checkbox, label: "Display Label", required: true/false]
|
|
||||||
- Field 2: [name: field_name, type: text/textarea/select/file/url/checkbox, label: "Display Label", required: true/false]
|
|
||||||
- [Add more fields as needed]
|
|
||||||
|
|
||||||
**N8N Webhook URL**: [Your N8N webhook endpoint URL]
|
|
||||||
|
|
||||||
### For Direct Access Agents Only:
|
|
||||||
**External Form URL**: [JotForm, Google Forms, or other external form URL]
|
|
||||||
**Custom Template Needed**: [Yes/No - specify if you need custom styling/layout]
|
|
||||||
**Custom Views Needed**: [Yes/No - specify if you need special marketplace behavior]
|
|
||||||
|
|
||||||
### Optional Information:
|
|
||||||
**Special Requirements**: [Any unique features or customizations needed]
|
|
||||||
**Integration Notes**: [Any special setup or configuration details]
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Available Categories
|
|
||||||
|
|
||||||
**Choose from these existing categories** (avoid creating new ones):
|
|
||||||
|
|
||||||
- 🧠 **`analysis`** - Problem-solving, SWOT analysis, strategic analysis tools
|
|
||||||
- 🎓 **`career-education`** - Career guidance, educational resources, professional development
|
|
||||||
- 📄 **`document-processing`** - PDF analysis, file processing, document tools
|
|
||||||
- 💼 **`human-resources`** - Job postings, HR automation, talent management
|
|
||||||
- 📢 **`marketing`** - Social ads, branding, content marketing, advertising
|
|
||||||
- 💼 **`consulting`** - Business consultation, strategy services, expert advice
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Form Field Types (Webhook Agents)
|
|
||||||
|
|
||||||
- **`text`** - Single-line text input
|
|
||||||
- **`textarea`** - Multi-line text input
|
|
||||||
- **`select`** - Dropdown (requires options array)
|
|
||||||
- **`file`** - File upload with drag-and-drop
|
|
||||||
- **`url`** - URL input with validation
|
|
||||||
- **`checkbox`** - Boolean true/false
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Example Requests
|
|
||||||
|
|
||||||
### Example 1: Webhook Agent
|
|
||||||
```markdown
|
|
||||||
## New Agent Request
|
|
||||||
|
|
||||||
**Agent Name**: Email Campaign Optimizer
|
|
||||||
**Type**: Webhook
|
|
||||||
**Category**: marketing
|
|
||||||
**Price**: 4.0 AED
|
|
||||||
**Short Description**: AI-powered email campaign optimization and A/B testing
|
|
||||||
**Full Description**: Optimize your email campaigns with AI analysis of subject lines, content, and send times. Get recommendations for better open rates and conversions.
|
|
||||||
|
|
||||||
### Form Fields:
|
|
||||||
- Field 1: [name: email_subject, type: text, label: "Email Subject Line", required: true]
|
|
||||||
- Field 2: [name: email_content, type: textarea, label: "Email Content", required: true]
|
|
||||||
- Field 3: [name: target_audience, type: select, label: "Target Audience", required: true, options: [{"value": "b2b", "label": "Business"}, {"value": "b2c", "label": "Consumer"}]]
|
|
||||||
|
|
||||||
**N8N Webhook URL**: http://localhost:5678/webhook/email-optimizer
|
|
||||||
```
|
|
||||||
|
|
||||||
### Example 2: Direct Access Agent
|
|
||||||
```markdown
|
|
||||||
## New Agent Request
|
|
||||||
|
|
||||||
**Agent Name**: Financial Planning Consultant
|
|
||||||
**Type**: Direct Access
|
|
||||||
**Category**: consulting
|
|
||||||
**Price**: 0.0 AED
|
|
||||||
**Short Description**: Professional financial planning and investment consultation
|
|
||||||
**Full Description**: Get expert financial advice tailored to your goals. Our certified financial planners provide personalized investment strategies and retirement planning.
|
|
||||||
|
|
||||||
### For Direct Access Agents:
|
|
||||||
**External Form URL**: https://form.jotform.com/financial-planning-form-id
|
|
||||||
**Custom Template Needed**: No
|
|
||||||
**Custom Views Needed**: No
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## What Happens Next
|
|
||||||
|
|
||||||
After you provide the completed template:
|
|
||||||
|
|
||||||
1. ✅ **Claude creates JSON config** in `agents/configs/agents/`
|
|
||||||
2. ✅ **Agent configuration is committed to git**
|
|
||||||
3. ✅ **Agent appears in marketplace** automatically via file-based system
|
|
||||||
4. ✅ **Creates any needed templates/views** (for advanced Direct Access agents)
|
|
||||||
5. ✅ **Updates marketplace integration** if needed
|
|
||||||
6. ✅ **Railway deployment ready** - no manual database commands
|
|
||||||
|
|
||||||
**Simple Process:** JSON file → git commit → agent appears! 🚀
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Current Agents (8 Total)
|
|
||||||
|
|
||||||
### Webhook Agents (4)
|
|
||||||
- **Social Ads Generator** - 6.00 AED - Social media ad creation
|
|
||||||
- **Job Posting Generator** - 10.00 AED - Professional job postings
|
|
||||||
- **PDF Summarizer** - 8.00 AED - Document analysis and summarization
|
|
||||||
- **5 Whys Analyzer** - 15.00 AED - Interactive root cause analysis
|
|
||||||
|
|
||||||
### Direct Access Agents (4)
|
|
||||||
- **CyberSec Career Navigator** - FREE - Career guidance
|
|
||||||
- **AI Brand Strategist** - FREE - Brand strategy consultation
|
|
||||||
- **Lean Six Sigma Expert** - FREE - Process improvement
|
|
||||||
- **SWOT Analysis Expert** - FREE - Strategic analysis
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Tips for Better Requests
|
|
||||||
|
|
||||||
- ✅ **Use existing categories** - Avoid creating new ones unless absolutely necessary
|
|
||||||
- ✅ **Be specific** - Clear descriptions help users understand the agent's value
|
|
||||||
- ✅ **Test external forms** - Ensure JotForm/external URLs are working before requesting
|
|
||||||
- ✅ **Consider pricing** - Free agents get more usage, paid agents need clear value proposition
|
|
||||||
- ✅ **Think about fields** - For webhook agents, plan your form fields carefully
|
|
||||||
- ✅ **Simple is better** - The file-based system makes creation effortless
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
*For comprehensive agent creation details, see `docs/AGENT_CREATION.md`*
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "quantum-tasks-ai-debug",
|
|
||||||
"type": "dockerfile",
|
|
||||||
"dockerfile": "./Dockerfile.dokploy.debug",
|
|
||||||
"port": 3000,
|
|
||||||
"healthCheck": "/health/",
|
|
||||||
"buildArgs": {},
|
|
||||||
"buildOptions": ["--no-cache"],
|
|
||||||
"env": {
|
|
||||||
"PYTHONUNBUFFERED": "1",
|
|
||||||
"DEBUG": "true",
|
|
||||||
"SECRET_KEY": "debug-key-change-in-production",
|
|
||||||
"ALLOWED_HOSTS": "*"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
25
dokploy.json
25
dokploy.json
@ -1,25 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "quantum-tasks-ai",
|
|
||||||
"type": "dockerfile",
|
|
||||||
"dockerfile": "./Dockerfile.dokploy",
|
|
||||||
"port": 3000,
|
|
||||||
"healthCheck": "/health/",
|
|
||||||
"buildArgs": {},
|
|
||||||
"buildOptions": ["--no-cache"],
|
|
||||||
"security": {
|
|
||||||
"redirectHttpsToHttp": true,
|
|
||||||
"forceHttps": false
|
|
||||||
},
|
|
||||||
"env": {
|
|
||||||
"PYTHONUNBUFFERED": "1",
|
|
||||||
"DEBUG": "false",
|
|
||||||
"SECRET_KEY": "${SECRET_KEY:-production-key-change-this-123456789}",
|
|
||||||
"ALLOWED_HOSTS": "${ALLOWED_HOSTS:-*}",
|
|
||||||
"DOKPLOY_PROJECT_NAME": "quantum-tasks-ai",
|
|
||||||
"SECURE_SSL_REDIRECT": "${SECURE_SSL_REDIRECT:-false}",
|
|
||||||
"SECURE_PROXY_SSL_HEADER": "HTTP_X_FORWARDED_PROTO,https",
|
|
||||||
"CSRF_TRUSTED_ORIGINS": "${CSRF_TRUSTED_ORIGINS:-}",
|
|
||||||
"DATABASE_URL": "${DATABASE_URL:-}",
|
|
||||||
"DOMAIN": "${DOMAIN:-quamtumtaskai.netcoptech.com}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,39 +0,0 @@
|
|||||||
# Production HTTPS settings for Dokploy deployment
|
|
||||||
from netcop_hub.settings import *
|
|
||||||
|
|
||||||
# Force HTTPS in production
|
|
||||||
SECURE_SSL_REDIRECT = True
|
|
||||||
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
|
|
||||||
|
|
||||||
# HSTS (HTTP Strict Transport Security)
|
|
||||||
SECURE_HSTS_SECONDS = 31536000 # 1 year
|
|
||||||
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
|
|
||||||
SECURE_HSTS_PRELOAD = True
|
|
||||||
|
|
||||||
# Cookie security
|
|
||||||
SESSION_COOKIE_SECURE = True
|
|
||||||
CSRF_COOKIE_SECURE = True
|
|
||||||
SESSION_COOKIE_HTTPONLY = True
|
|
||||||
CSRF_COOKIE_HTTPONLY = True
|
|
||||||
|
|
||||||
# Additional security headers
|
|
||||||
SECURE_CONTENT_TYPE_NOSNIFF = True
|
|
||||||
SECURE_BROWSER_XSS_FILTER = True
|
|
||||||
X_FRAME_OPTIONS = 'DENY'
|
|
||||||
|
|
||||||
# Trust Dokploy/Traefik proxy headers
|
|
||||||
USE_X_FORWARDED_HOST = True
|
|
||||||
USE_X_FORWARDED_PORT = True
|
|
||||||
|
|
||||||
# CSRF trusted origins for HTTPS
|
|
||||||
CSRF_TRUSTED_ORIGINS = [
|
|
||||||
'https://website-quantumtaskai-wrczik-cc50ac-31-97-62-205.traefik.me',
|
|
||||||
'http://website-quantumtaskai-wrczik-cc50ac-31-97-62-205.traefik.me', # For testing
|
|
||||||
'https://localhost:3000',
|
|
||||||
'http://localhost:3000',
|
|
||||||
]
|
|
||||||
|
|
||||||
print("🔒 HTTPS Production Settings Loaded")
|
|
||||||
print(f" - SSL Redirect: {SECURE_SSL_REDIRECT}")
|
|
||||||
print(f" - HSTS: {SECURE_HSTS_SECONDS} seconds")
|
|
||||||
print(f" - Trusted Origins: {len(CSRF_TRUSTED_ORIGINS)} configured")
|
|
||||||
39
run_dev.sh
39
run_dev.sh
@ -1,39 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# Development server startup script
|
|
||||||
# Ensures clean environment for Django development
|
|
||||||
|
|
||||||
echo "🚀 Starting Django Development Server"
|
|
||||||
echo "======================================"
|
|
||||||
|
|
||||||
# Clear any DATABASE_URL that might interfere with local development
|
|
||||||
unset DATABASE_URL
|
|
||||||
|
|
||||||
# Activate virtual environment
|
|
||||||
echo "📦 Activating virtual environment..."
|
|
||||||
source venv/bin/activate
|
|
||||||
|
|
||||||
# Check database configuration
|
|
||||||
echo "🔍 Checking database configuration..."
|
|
||||||
python manage.py check_db
|
|
||||||
|
|
||||||
# Check for pending migrations
|
|
||||||
echo ""
|
|
||||||
echo "🔄 Checking for pending migrations..."
|
|
||||||
if python manage.py showmigrations --plan | grep -q '\[ \]'; then
|
|
||||||
echo "⚠️ Found pending migrations. Applying them..."
|
|
||||||
python manage.py migrate
|
|
||||||
echo "✅ Migrations applied successfully!"
|
|
||||||
else
|
|
||||||
echo "✅ All migrations up to date!"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "🌐 Starting Django server..."
|
|
||||||
echo "Visit: http://localhost:8000"
|
|
||||||
echo "Admin: http://localhost:8000/admin"
|
|
||||||
echo ""
|
|
||||||
echo "Press Ctrl+C to stop the server"
|
|
||||||
echo "======================================"
|
|
||||||
|
|
||||||
# Start the development server
|
|
||||||
python manage.py runserver
|
|
||||||
@ -1,319 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
"""
|
|
||||||
Auto Documentation Update Script
|
|
||||||
Automatically updates README.md, CLAUDE.md, and docs/ files based on recent changes
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import json
|
|
||||||
import subprocess
|
|
||||||
import re
|
|
||||||
from datetime import datetime
|
|
||||||
from pathlib import Path
|
|
||||||
from typing import List, Dict, Set
|
|
||||||
|
|
||||||
class DocumentationUpdater:
|
|
||||||
def __init__(self, project_root: str = None):
|
|
||||||
self.project_root = Path(project_root) if project_root else Path.cwd()
|
|
||||||
self.changes_summary = {}
|
|
||||||
self.updated_files = []
|
|
||||||
|
|
||||||
def analyze_recent_changes(self, commit_count: int = 5) -> Dict:
|
|
||||||
"""Analyze recent git commits to understand what changed"""
|
|
||||||
try:
|
|
||||||
# Get recent commit messages
|
|
||||||
result = subprocess.run([
|
|
||||||
'git', 'log', f'--oneline', f'-{commit_count}'
|
|
||||||
], capture_output=True, text=True, cwd=self.project_root)
|
|
||||||
|
|
||||||
commits = result.stdout.strip().split('\n') if result.stdout else []
|
|
||||||
|
|
||||||
# Get changed files in recent commits
|
|
||||||
result = subprocess.run([
|
|
||||||
'git', 'diff', 'HEAD~1', '--name-only'
|
|
||||||
], capture_output=True, text=True, cwd=self.project_root)
|
|
||||||
|
|
||||||
changed_files = result.stdout.strip().split('\n') if result.stdout else []
|
|
||||||
|
|
||||||
# Categorize changes
|
|
||||||
categories = {
|
|
||||||
'agents': [],
|
|
||||||
'core': [],
|
|
||||||
'deployment': [],
|
|
||||||
'documentation': [],
|
|
||||||
'frontend': [],
|
|
||||||
'backend': []
|
|
||||||
}
|
|
||||||
|
|
||||||
for file in changed_files:
|
|
||||||
if not file:
|
|
||||||
continue
|
|
||||||
|
|
||||||
file_lower = file.lower()
|
|
||||||
if any(agent in file for agent in ['agent', 'processor', 'models.py']):
|
|
||||||
categories['agents'].append(file)
|
|
||||||
elif any(core in file for core in ['settings', 'urls.py', 'views.py']):
|
|
||||||
categories['core'].append(file)
|
|
||||||
elif any(deploy in file for deploy in ['railway', 'requirements', 'docker']):
|
|
||||||
categories['deployment'].append(file)
|
|
||||||
elif file_lower.endswith('.md') or 'docs/' in file:
|
|
||||||
categories['documentation'].append(file)
|
|
||||||
elif any(frontend in file for frontend in ['.html', '.css', '.js']):
|
|
||||||
categories['frontend'].append(file)
|
|
||||||
else:
|
|
||||||
categories['backend'].append(file)
|
|
||||||
|
|
||||||
return {
|
|
||||||
'commits': commits,
|
|
||||||
'changed_files': changed_files,
|
|
||||||
'categories': categories,
|
|
||||||
'analysis_date': datetime.now().isoformat()
|
|
||||||
}
|
|
||||||
|
|
||||||
except subprocess.CalledProcessError as e:
|
|
||||||
print(f"Error analyzing git changes: {e}")
|
|
||||||
return {}
|
|
||||||
|
|
||||||
def find_documentation_files(self) -> Dict[str, List[Path]]:
|
|
||||||
"""Find all documentation files in the project"""
|
|
||||||
doc_files = {
|
|
||||||
'readme': [],
|
|
||||||
'claude_md': [],
|
|
||||||
'docs_directory': []
|
|
||||||
}
|
|
||||||
|
|
||||||
# Find README files
|
|
||||||
for readme in self.project_root.rglob('README.md'):
|
|
||||||
doc_files['readme'].append(readme)
|
|
||||||
|
|
||||||
# Find CLAUDE.md files
|
|
||||||
for claude in self.project_root.rglob('CLAUDE.md'):
|
|
||||||
doc_files['claude_md'].append(claude)
|
|
||||||
|
|
||||||
# Find docs directory files
|
|
||||||
docs_path = self.project_root / 'docs'
|
|
||||||
if docs_path.exists():
|
|
||||||
for doc_file in docs_path.rglob('*.md'):
|
|
||||||
doc_files['docs_directory'].append(doc_file)
|
|
||||||
|
|
||||||
return doc_files
|
|
||||||
|
|
||||||
def should_update_documentation(self, changes: Dict) -> bool:
|
|
||||||
"""Determine if documentation updates are needed"""
|
|
||||||
# Check if significant changes were made
|
|
||||||
categories = changes.get('categories', {})
|
|
||||||
|
|
||||||
# Always update if agents, core, or deployment changed
|
|
||||||
significant_changes = (
|
|
||||||
categories.get('agents', []) or
|
|
||||||
categories.get('core', []) or
|
|
||||||
categories.get('deployment', [])
|
|
||||||
)
|
|
||||||
|
|
||||||
# Check commit messages for documentation keywords
|
|
||||||
commits = changes.get('commits', [])
|
|
||||||
doc_keywords = ['add', 'update', 'new', 'feature', 'agent', 'deploy']
|
|
||||||
|
|
||||||
has_doc_worthy_commits = any(
|
|
||||||
any(keyword in commit.lower() for keyword in doc_keywords)
|
|
||||||
for commit in commits
|
|
||||||
)
|
|
||||||
|
|
||||||
return bool(significant_changes or has_doc_worthy_commits)
|
|
||||||
|
|
||||||
def update_claude_md(self, changes: Dict) -> bool:
|
|
||||||
"""Update CLAUDE.md with recent changes"""
|
|
||||||
claude_file = self.project_root / 'CLAUDE.md'
|
|
||||||
if not claude_file.exists():
|
|
||||||
return False
|
|
||||||
|
|
||||||
try:
|
|
||||||
content = claude_file.read_text()
|
|
||||||
original_content = content
|
|
||||||
updated = False
|
|
||||||
|
|
||||||
categories = changes.get('categories', {})
|
|
||||||
|
|
||||||
# Update project overview if agents were added/modified
|
|
||||||
if categories.get('agents'):
|
|
||||||
# This is a simplified example - in practice, you'd parse and update specific sections
|
|
||||||
overview_pattern = r'(## Project Overview.*?)(## Development Commands)'
|
|
||||||
if re.search(overview_pattern, content, re.DOTALL):
|
|
||||||
print("Found project overview section in CLAUDE.md")
|
|
||||||
# Add logic to update agent count, new agent descriptions, etc.
|
|
||||||
updated = True
|
|
||||||
|
|
||||||
# Update commands section if new scripts were added
|
|
||||||
if any('manage.py' in f or 'script' in f for f in changes.get('changed_files', [])):
|
|
||||||
print("Detected management command changes")
|
|
||||||
updated = True
|
|
||||||
|
|
||||||
# Update environment variables section if settings changed
|
|
||||||
if any('settings' in f or 'env' in f for f in changes.get('changed_files', [])):
|
|
||||||
print("Detected environment/settings changes")
|
|
||||||
updated = True
|
|
||||||
|
|
||||||
# Add timestamp of last update
|
|
||||||
if updated:
|
|
||||||
timestamp_pattern = r'(Last updated: )[\d\-:T\s]+\n'
|
|
||||||
new_timestamp = f"Last updated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n"
|
|
||||||
|
|
||||||
if re.search(timestamp_pattern, content):
|
|
||||||
content = re.sub(timestamp_pattern, f"\\1{new_timestamp}", content)
|
|
||||||
else:
|
|
||||||
# Add timestamp at the end
|
|
||||||
content += f"\n\n---\nLast updated: {new_timestamp}"
|
|
||||||
|
|
||||||
claude_file.write_text(content)
|
|
||||||
self.updated_files.append(str(claude_file))
|
|
||||||
return True
|
|
||||||
|
|
||||||
return updated
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error updating CLAUDE.md: {e}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
def update_readme(self, changes: Dict) -> bool:
|
|
||||||
"""Update README.md with recent changes"""
|
|
||||||
readme_file = self.project_root / 'README.md'
|
|
||||||
if not readme_file.exists():
|
|
||||||
return False
|
|
||||||
|
|
||||||
try:
|
|
||||||
content = readme_file.read_text()
|
|
||||||
updated = False
|
|
||||||
|
|
||||||
categories = changes.get('categories', {})
|
|
||||||
|
|
||||||
# Update features section if new agents were added
|
|
||||||
if categories.get('agents'):
|
|
||||||
print("Updating README features section for new agents")
|
|
||||||
updated = True
|
|
||||||
|
|
||||||
# Update installation section if requirements changed
|
|
||||||
if any('requirements' in f or 'setup' in f for f in changes.get('changed_files', [])):
|
|
||||||
print("Updating README installation section")
|
|
||||||
updated = True
|
|
||||||
|
|
||||||
if updated:
|
|
||||||
readme_file.write_text(content)
|
|
||||||
self.updated_files.append(str(readme_file))
|
|
||||||
return True
|
|
||||||
|
|
||||||
return False
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error updating README.md: {e}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
def update_docs_directory(self, changes: Dict) -> bool:
|
|
||||||
"""Update files in docs/ directory"""
|
|
||||||
docs_path = self.project_root / 'docs'
|
|
||||||
if not docs_path.exists():
|
|
||||||
return False
|
|
||||||
|
|
||||||
updated_any = False
|
|
||||||
categories = changes.get('categories', {})
|
|
||||||
|
|
||||||
# Update agent creation guide if agent changes were made
|
|
||||||
if categories.get('agents'):
|
|
||||||
agent_guide = docs_path / 'development' / 'agent-creation.md'
|
|
||||||
if agent_guide.exists():
|
|
||||||
print("Updating agent creation guide")
|
|
||||||
# Add new patterns, update examples, etc.
|
|
||||||
updated_any = True
|
|
||||||
self.updated_files.append(str(agent_guide))
|
|
||||||
|
|
||||||
# Update deployment guide if deployment files changed
|
|
||||||
if categories.get('deployment'):
|
|
||||||
deploy_guide = docs_path / 'deployment' / 'railway-deployment.md'
|
|
||||||
if deploy_guide.exists():
|
|
||||||
print("Updating deployment guide")
|
|
||||||
updated_any = True
|
|
||||||
self.updated_files.append(str(deploy_guide))
|
|
||||||
|
|
||||||
return updated_any
|
|
||||||
|
|
||||||
def generate_update_summary(self, changes: Dict) -> str:
|
|
||||||
"""Generate a summary of what was updated"""
|
|
||||||
summary = []
|
|
||||||
summary.append("=== Documentation Auto-Update Summary ===")
|
|
||||||
summary.append(f"Update Date: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
|
||||||
summary.append("")
|
|
||||||
|
|
||||||
# Recent commits
|
|
||||||
commits = changes.get('commits', [])
|
|
||||||
if commits:
|
|
||||||
summary.append("Recent Commits:")
|
|
||||||
for commit in commits[:3]: # Show last 3 commits
|
|
||||||
summary.append(f" - {commit}")
|
|
||||||
summary.append("")
|
|
||||||
|
|
||||||
# Changed files by category
|
|
||||||
categories = changes.get('categories', {})
|
|
||||||
for category, files in categories.items():
|
|
||||||
if files:
|
|
||||||
summary.append(f"{category.title()} Changes:")
|
|
||||||
for file in files[:5]: # Show up to 5 files per category
|
|
||||||
summary.append(f" - {file}")
|
|
||||||
summary.append("")
|
|
||||||
|
|
||||||
# Updated documentation files
|
|
||||||
if self.updated_files:
|
|
||||||
summary.append("Updated Documentation Files:")
|
|
||||||
for file in self.updated_files:
|
|
||||||
summary.append(f" - {file}")
|
|
||||||
else:
|
|
||||||
summary.append("No documentation files required updates.")
|
|
||||||
|
|
||||||
summary.append("")
|
|
||||||
summary.append("=== End Summary ===")
|
|
||||||
|
|
||||||
return "\n".join(summary)
|
|
||||||
|
|
||||||
def run_update(self) -> str:
|
|
||||||
"""Main method to run the documentation update process"""
|
|
||||||
print("Starting documentation auto-update...")
|
|
||||||
|
|
||||||
# Analyze recent changes
|
|
||||||
changes = self.analyze_recent_changes()
|
|
||||||
|
|
||||||
if not changes:
|
|
||||||
return "Error: Could not analyze recent changes"
|
|
||||||
|
|
||||||
# Check if updates are needed
|
|
||||||
if not self.should_update_documentation(changes):
|
|
||||||
return "No significant changes detected - documentation update skipped"
|
|
||||||
|
|
||||||
# Find documentation files
|
|
||||||
doc_files = self.find_documentation_files()
|
|
||||||
print(f"Found documentation files: {sum(len(files) for files in doc_files.values())}")
|
|
||||||
|
|
||||||
# Update each type of documentation
|
|
||||||
updated_claude = self.update_claude_md(changes)
|
|
||||||
updated_readme = self.update_readme(changes)
|
|
||||||
updated_docs = self.update_docs_directory(changes)
|
|
||||||
|
|
||||||
# Generate and save summary
|
|
||||||
summary = self.generate_update_summary(changes)
|
|
||||||
|
|
||||||
# Save summary to file
|
|
||||||
summary_file = self.project_root / 'docs_update_summary.txt'
|
|
||||||
summary_file.write_text(summary)
|
|
||||||
|
|
||||||
print(summary)
|
|
||||||
return summary
|
|
||||||
|
|
||||||
def main():
|
|
||||||
"""Main entry point"""
|
|
||||||
project_root = sys.argv[1] if len(sys.argv) > 1 else None
|
|
||||||
|
|
||||||
updater = DocumentationUpdater(project_root)
|
|
||||||
result = updater.run_update()
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
@ -1,143 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# GitHub Branch Protection Setup Script
|
|
||||||
# Run this script to configure branch protection rules
|
|
||||||
|
|
||||||
# Colors for output
|
|
||||||
RED='\033[0;31m'
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
YELLOW='\033[1;33m'
|
|
||||||
NC='\033[0m' # No Color
|
|
||||||
|
|
||||||
echo -e "${GREEN}🔐 Setting up GitHub Branch Protection Rules${NC}"
|
|
||||||
echo "This script will guide you through configuring branch protection for Railway deployment control."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check if GitHub CLI is installed
|
|
||||||
if ! command -v gh &> /dev/null; then
|
|
||||||
echo -e "${RED}❌ GitHub CLI (gh) is not installed.${NC}"
|
|
||||||
echo "Please install GitHub CLI first:"
|
|
||||||
echo " - macOS: brew install gh"
|
|
||||||
echo " - Ubuntu: sudo apt install gh"
|
|
||||||
echo " - Or visit: https://cli.github.com/"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check if user is authenticated
|
|
||||||
if ! gh auth status &> /dev/null; then
|
|
||||||
echo -e "${YELLOW}🔑 You need to authenticate with GitHub first.${NC}"
|
|
||||||
echo "Run: gh auth login"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Get repository information
|
|
||||||
REPO_OWNER=$(gh repo view --json owner --jq '.owner.login')
|
|
||||||
REPO_NAME=$(gh repo view --json name --jq '.name')
|
|
||||||
|
|
||||||
echo -e "${GREEN}📋 Repository: ${REPO_OWNER}/${REPO_NAME}${NC}"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Function to create branch protection rule
|
|
||||||
create_branch_protection() {
|
|
||||||
local branch=$1
|
|
||||||
local description=$2
|
|
||||||
|
|
||||||
echo -e "${YELLOW}🛡️ Setting up protection for ${branch} branch (${description})${NC}"
|
|
||||||
|
|
||||||
# Create branch protection rule
|
|
||||||
gh api repos/${REPO_OWNER}/${REPO_NAME}/branches/${branch}/protection \
|
|
||||||
--method PUT \
|
|
||||||
--field required_status_checks='{"strict":true,"contexts":[]}' \
|
|
||||||
--field enforce_admins=true \
|
|
||||||
--field required_pull_request_reviews='{"required_approving_review_count":1,"dismiss_stale_reviews":true,"require_code_owner_reviews":false}' \
|
|
||||||
--field restrictions=null \
|
|
||||||
--field allow_force_pushes=false \
|
|
||||||
--field allow_deletions=false \
|
|
||||||
> /dev/null 2>&1
|
|
||||||
|
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
echo -e "${GREEN}✅ Branch protection enabled for ${branch}${NC}"
|
|
||||||
else
|
|
||||||
echo -e "${RED}❌ Failed to set protection for ${branch}${NC}"
|
|
||||||
echo "This might be because:"
|
|
||||||
echo " - You don't have admin permissions on the repository"
|
|
||||||
echo " - The branch doesn't exist yet"
|
|
||||||
echo " - GitHub API rate limits"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Create main branch protection (Production)
|
|
||||||
echo -e "${GREEN}Setting up main branch protection (Production deployment control)${NC}"
|
|
||||||
create_branch_protection "main" "Production deployment"
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Create staging branch protection (Optional)
|
|
||||||
echo -e "${YELLOW}Do you want to protect the staging branch too? (y/n)${NC}"
|
|
||||||
read -r setup_staging
|
|
||||||
|
|
||||||
if [[ $setup_staging =~ ^[Yy]$ ]]; then
|
|
||||||
create_branch_protection "staging" "Staging deployment"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Create development branch if it doesn't exist
|
|
||||||
echo -e "${GREEN}Ensuring development branch exists...${NC}"
|
|
||||||
git show-ref --verify --quiet refs/heads/development
|
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
echo -e "${GREEN}✅ Development branch already exists${NC}"
|
|
||||||
else
|
|
||||||
echo -e "${YELLOW}📝 Creating development branch...${NC}"
|
|
||||||
git checkout -b development 2>/dev/null || git checkout development
|
|
||||||
git push -u origin development
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Push staging branch if it doesn't exist on remote
|
|
||||||
echo -e "${GREEN}Ensuring staging branch exists on remote...${NC}"
|
|
||||||
if git ls-remote --heads origin staging | grep -q staging; then
|
|
||||||
echo -e "${GREEN}✅ Staging branch already exists on remote${NC}"
|
|
||||||
else
|
|
||||||
echo -e "${YELLOW}📝 Pushing staging branch to remote...${NC}"
|
|
||||||
git push -u origin staging
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Set default branch to development
|
|
||||||
echo -e "${YELLOW}Do you want to set 'development' as the default branch for new PRs? (y/n)${NC}"
|
|
||||||
read -r set_default
|
|
||||||
|
|
||||||
if [[ $set_default =~ ^[Yy]$ ]]; then
|
|
||||||
gh api repos/${REPO_OWNER}/${REPO_NAME} \
|
|
||||||
--method PATCH \
|
|
||||||
--field default_branch='development' \
|
|
||||||
> /dev/null 2>&1
|
|
||||||
|
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
echo -e "${GREEN}✅ Default branch set to development${NC}"
|
|
||||||
else
|
|
||||||
echo -e "${RED}❌ Failed to set default branch${NC}"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo -e "${GREEN}🎉 Branch protection setup complete!${NC}"
|
|
||||||
echo ""
|
|
||||||
echo -e "${YELLOW}Summary of your deployment control setup:${NC}"
|
|
||||||
echo "📦 main branch → Protected, auto-deploys to Railway production"
|
|
||||||
echo "🧪 staging branch → ${setup_staging:+Protected, }deploys to Railway staging"
|
|
||||||
echo "🛠️ development → Unprotected, no automatic deployment"
|
|
||||||
echo ""
|
|
||||||
echo -e "${GREEN}Next steps:${NC}"
|
|
||||||
echo "1. Configure Railway to deploy only from 'main' branch"
|
|
||||||
echo "2. Optionally create staging Railway service for 'staging' branch"
|
|
||||||
echo "3. Always work on 'development' branch for new features"
|
|
||||||
echo "4. Use Pull Requests to merge: development → staging → main"
|
|
||||||
echo ""
|
|
||||||
echo -e "${YELLOW}To complete Railway configuration:${NC}"
|
|
||||||
echo "1. Go to your Railway dashboard"
|
|
||||||
echo "2. In your service settings, set 'Source Repo' branch to 'main'"
|
|
||||||
echo "3. Enable 'Auto Deploy' only for the main branch"
|
|
||||||
echo "4. For staging, create a separate service connected to 'staging' branch"
|
|
||||||
@ -1,120 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# Setup Git Hooks for Auto-Documentation Updates
|
|
||||||
|
|
||||||
PROJECT_ROOT=$(pwd)
|
|
||||||
GIT_HOOKS_DIR="$PROJECT_ROOT/.git/hooks"
|
|
||||||
SCRIPTS_DIR="$PROJECT_ROOT/scripts"
|
|
||||||
|
|
||||||
echo "Setting up git hooks for auto-documentation updates..."
|
|
||||||
|
|
||||||
# Create post-commit hook
|
|
||||||
cat > "$GIT_HOOKS_DIR/post-commit" << 'EOF'
|
|
||||||
#!/bin/bash
|
|
||||||
# Auto-update documentation after successful commits
|
|
||||||
|
|
||||||
PROJECT_ROOT=$(git rev-parse --show-toplevel)
|
|
||||||
SCRIPTS_DIR="$PROJECT_ROOT/scripts"
|
|
||||||
AUTO_UPDATE_SCRIPT="$SCRIPTS_DIR/auto_update_docs.py"
|
|
||||||
|
|
||||||
# Check if the auto-update script exists
|
|
||||||
if [ -f "$AUTO_UPDATE_SCRIPT" ]; then
|
|
||||||
echo "Auto-updating documentation after commit..."
|
|
||||||
python3 "$AUTO_UPDATE_SCRIPT" "$PROJECT_ROOT"
|
|
||||||
|
|
||||||
# Check if any documentation was updated
|
|
||||||
if [ -f "$PROJECT_ROOT/docs_update_summary.txt" ]; then
|
|
||||||
echo "Documentation auto-update completed. Check docs_update_summary.txt for details."
|
|
||||||
|
|
||||||
# Optionally auto-commit documentation updates
|
|
||||||
# Uncomment the lines below if you want documentation updates to be auto-committed
|
|
||||||
# git add *.md docs/ CLAUDE.md README.md docs_update_summary.txt
|
|
||||||
# git commit -m "📚 Auto-update documentation after recent changes"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "Auto-update script not found at $AUTO_UPDATE_SCRIPT"
|
|
||||||
fi
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# Make post-commit hook executable
|
|
||||||
chmod +x "$GIT_HOOKS_DIR/post-commit"
|
|
||||||
|
|
||||||
# Create pre-push hook to ensure documentation is up to date
|
|
||||||
cat > "$GIT_HOOKS_DIR/pre-push" << 'EOF'
|
|
||||||
#!/bin/bash
|
|
||||||
# Ensure documentation is up to date before pushing
|
|
||||||
|
|
||||||
PROJECT_ROOT=$(git rev-parse --show-toplevel)
|
|
||||||
SCRIPTS_DIR="$PROJECT_ROOT/scripts"
|
|
||||||
AUTO_UPDATE_SCRIPT="$SCRIPTS_DIR/auto_update_docs.py"
|
|
||||||
|
|
||||||
echo "Checking documentation status before push..."
|
|
||||||
|
|
||||||
# Run documentation update check
|
|
||||||
if [ -f "$AUTO_UPDATE_SCRIPT" ]; then
|
|
||||||
python3 "$AUTO_UPDATE_SCRIPT" "$PROJECT_ROOT"
|
|
||||||
|
|
||||||
# Check if any updates were made
|
|
||||||
if git diff --quiet; then
|
|
||||||
echo "Documentation is up to date."
|
|
||||||
else
|
|
||||||
echo "Documentation updates were generated. Please review and commit them before pushing."
|
|
||||||
echo "Modified files:"
|
|
||||||
git diff --name-only
|
|
||||||
echo ""
|
|
||||||
echo "To commit documentation updates:"
|
|
||||||
echo " git add ."
|
|
||||||
echo " git commit -m '📚 Update documentation'"
|
|
||||||
echo " git push"
|
|
||||||
|
|
||||||
# Uncomment to block push until docs are committed
|
|
||||||
# exit 1
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "Auto-update script not found. Proceeding with push..."
|
|
||||||
fi
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# Make pre-push hook executable
|
|
||||||
chmod +x "$GIT_HOOKS_DIR/pre-push"
|
|
||||||
|
|
||||||
# Create a manual trigger script
|
|
||||||
cat > "$SCRIPTS_DIR/update_docs_manual.sh" << 'EOF'
|
|
||||||
#!/bin/bash
|
|
||||||
# Manual trigger for documentation updates
|
|
||||||
|
|
||||||
PROJECT_ROOT=$(git rev-parse --show-toplevel)
|
|
||||||
SCRIPTS_DIR="$PROJECT_ROOT/scripts"
|
|
||||||
AUTO_UPDATE_SCRIPT="$SCRIPTS_DIR/auto_update_docs.py"
|
|
||||||
|
|
||||||
echo "Manually triggering documentation update..."
|
|
||||||
|
|
||||||
if [ -f "$AUTO_UPDATE_SCRIPT" ]; then
|
|
||||||
python3 "$AUTO_UPDATE_SCRIPT" "$PROJECT_ROOT"
|
|
||||||
|
|
||||||
if [ -f "$PROJECT_ROOT/docs_update_summary.txt" ]; then
|
|
||||||
echo ""
|
|
||||||
echo "Documentation update completed!"
|
|
||||||
echo "Summary saved to: docs_update_summary.txt"
|
|
||||||
echo ""
|
|
||||||
echo "To commit the updates:"
|
|
||||||
echo " git add ."
|
|
||||||
echo " git commit -m '📚 Manual documentation update'"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "Error: Auto-update script not found at $AUTO_UPDATE_SCRIPT"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
EOF
|
|
||||||
|
|
||||||
chmod +x "$SCRIPTS_DIR/update_docs_manual.sh"
|
|
||||||
|
|
||||||
echo "Git hooks setup completed!"
|
|
||||||
echo ""
|
|
||||||
echo "Created hooks:"
|
|
||||||
echo " - post-commit: Auto-updates docs after each commit"
|
|
||||||
echo " - pre-push: Checks docs before pushing"
|
|
||||||
echo ""
|
|
||||||
echo "Created scripts:"
|
|
||||||
echo " - $SCRIPTS_DIR/update_docs_manual.sh: Manual documentation update trigger"
|
|
||||||
echo ""
|
|
||||||
echo "To disable auto-updates, remove or rename the hooks in .git/hooks/"
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# Manual trigger for documentation updates
|
|
||||||
|
|
||||||
PROJECT_ROOT=$(git rev-parse --show-toplevel)
|
|
||||||
SCRIPTS_DIR="$PROJECT_ROOT/scripts"
|
|
||||||
AUTO_UPDATE_SCRIPT="$SCRIPTS_DIR/auto_update_docs.py"
|
|
||||||
|
|
||||||
echo "Manually triggering documentation update..."
|
|
||||||
|
|
||||||
if [ -f "$AUTO_UPDATE_SCRIPT" ]; then
|
|
||||||
python3 "$AUTO_UPDATE_SCRIPT" "$PROJECT_ROOT"
|
|
||||||
|
|
||||||
if [ -f "$PROJECT_ROOT/docs_update_summary.txt" ]; then
|
|
||||||
echo ""
|
|
||||||
echo "Documentation update completed!"
|
|
||||||
echo "Summary saved to: docs_update_summary.txt"
|
|
||||||
echo ""
|
|
||||||
echo "To commit the updates:"
|
|
||||||
echo " git add ."
|
|
||||||
echo " git commit -m '📚 Manual documentation update'"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "Error: Auto-update script not found at $AUTO_UPDATE_SCRIPT"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# Dokploy startup script
|
|
||||||
|
|
||||||
set -e # Exit on any error
|
|
||||||
|
|
||||||
echo "🚀 Starting Quantum Tasks AI on Dokploy"
|
|
||||||
echo "======================================="
|
|
||||||
|
|
||||||
# Run database migrations
|
|
||||||
echo "📄 Running database migrations..."
|
|
||||||
DJANGO_SETTINGS_MODULE=netcop_hub.production_settings python manage.py migrate --noinput
|
|
||||||
|
|
||||||
# Create cache table if needed
|
|
||||||
echo "🗄️ Ensuring cache table exists..."
|
|
||||||
DJANGO_SETTINGS_MODULE=netcop_hub.production_settings python manage.py createcachetable || true
|
|
||||||
|
|
||||||
# Check if we can access the database
|
|
||||||
echo "🔍 Testing database connection..."
|
|
||||||
DJANGO_SETTINGS_MODULE=netcop_hub.production_settings python manage.py check --database default
|
|
||||||
|
|
||||||
# Start the application
|
|
||||||
echo "🌐 Starting gunicorn server on port 3000..."
|
|
||||||
echo "Health check endpoint: /health/"
|
|
||||||
echo "🔒 SSL redirect: $SECURE_SSL_REDIRECT"
|
|
||||||
echo "🌐 Allowed hosts: $ALLOWED_HOSTS"
|
|
||||||
echo "======================================="
|
|
||||||
|
|
||||||
DJANGO_SETTINGS_MODULE=netcop_hub.production_settings exec gunicorn netcop_hub.wsgi:application
|
|
||||||
--bind 0.0.0.0:3000 \
|
|
||||||
--workers 2 \
|
|
||||||
--timeout 120 \
|
|
||||||
--max-requests 1000 \
|
|
||||||
--preload \
|
|
||||||
--log-level info \
|
|
||||||
--access-logfile - \
|
|
||||||
--error-logfile -
|
|
||||||
13
start.sh
13
start.sh
@ -1,13 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Start script for Render deployment
|
|
||||||
|
|
||||||
set -o errexit # exit on error
|
|
||||||
|
|
||||||
echo "Running database migrations..."
|
|
||||||
python manage.py migrate
|
|
||||||
|
|
||||||
echo "Creating admin user if needed..."
|
|
||||||
python manage.py reset_admin --password=RenderTemp123! || true
|
|
||||||
|
|
||||||
echo "Starting gunicorn server..."
|
|
||||||
exec gunicorn netcop_hub.wsgi:application --bind 0.0.0.0:$PORT --workers 1 --timeout 60
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import django
|
|
||||||
|
|
||||||
# Add the project root to Python path
|
|
||||||
sys.path.insert(0, '/home/amit/projects/quantumtaskai_django')
|
|
||||||
|
|
||||||
# Set Django settings
|
|
||||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'quantumtaskai_hub.settings')
|
|
||||||
django.setup()
|
|
||||||
|
|
||||||
from agent_base.models import BaseAgent
|
|
||||||
|
|
||||||
print("🔍 Checking agents in database:")
|
|
||||||
print("=" * 40)
|
|
||||||
|
|
||||||
agents = BaseAgent.objects.all()
|
|
||||||
if agents:
|
|
||||||
for agent in agents:
|
|
||||||
print(f"✅ {agent.name} ({agent.slug})")
|
|
||||||
print(f" Category: {agent.category}")
|
|
||||||
print(f" Price: {agent.price} AED")
|
|
||||||
print(f" Type: {agent.agent_type}")
|
|
||||||
print(f" Active: {agent.is_active}")
|
|
||||||
print()
|
|
||||||
else:
|
|
||||||
print("❌ No agents found in database")
|
|
||||||
|
|
||||||
print(f"Total agents: {agents.count()}")
|
|
||||||
@ -1,85 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import django
|
|
||||||
|
|
||||||
# Add the project root to Python path
|
|
||||||
sys.path.insert(0, '/home/amit/Desktop/quantum_ai')
|
|
||||||
|
|
||||||
# Set Django settings
|
|
||||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'quantumtaskai_hub.settings')
|
|
||||||
django.setup()
|
|
||||||
|
|
||||||
from agent_base.models import BaseAgent
|
|
||||||
from core.views import homepage_view
|
|
||||||
from django.http import HttpRequest
|
|
||||||
from django.contrib.auth.models import AnonymousUser
|
|
||||||
|
|
||||||
def test_agent_visibility():
|
|
||||||
print("🧪 Testing Agent System Integration")
|
|
||||||
print("=" * 40)
|
|
||||||
|
|
||||||
# Check agents in database
|
|
||||||
agents = BaseAgent.objects.filter(is_active=True)
|
|
||||||
print(f"✅ Active agents in database: {agents.count()}")
|
|
||||||
|
|
||||||
for agent in agents:
|
|
||||||
print(f" 📋 {agent.name} ({agent.slug})")
|
|
||||||
print(f" Category: {agent.category}")
|
|
||||||
print(f" Price: {agent.price} AED")
|
|
||||||
print(f" Type: {agent.agent_type}")
|
|
||||||
print()
|
|
||||||
|
|
||||||
# Test the homepage view directly
|
|
||||||
print("🧪 Testing Homepage View")
|
|
||||||
print("-" * 20)
|
|
||||||
|
|
||||||
request = HttpRequest()
|
|
||||||
request.method = 'GET'
|
|
||||||
request.user = AnonymousUser()
|
|
||||||
request.META = {'HTTP_HOST': 'testserver'}
|
|
||||||
|
|
||||||
try:
|
|
||||||
response = homepage_view(request)
|
|
||||||
print(f"✅ Homepage view response status: {response.status_code}")
|
|
||||||
|
|
||||||
# Check if the response contains weather agent
|
|
||||||
if hasattr(response, 'content'):
|
|
||||||
content = response.content.decode('utf-8')
|
|
||||||
if 'Weather Reporter' in content:
|
|
||||||
print("✅ Weather Reporter found in homepage HTML")
|
|
||||||
else:
|
|
||||||
print("❌ Weather Reporter not found in homepage HTML")
|
|
||||||
|
|
||||||
if 'Use Now' in content:
|
|
||||||
print("✅ 'Use Now' buttons found")
|
|
||||||
else:
|
|
||||||
print("❌ 'Use Now' buttons not found")
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"❌ Error in homepage view: {e}")
|
|
||||||
|
|
||||||
def check_url_structure():
|
|
||||||
print("\n🧪 Checking URL Structure")
|
|
||||||
print("=" * 40)
|
|
||||||
|
|
||||||
from django.urls import reverse
|
|
||||||
|
|
||||||
try:
|
|
||||||
# Test core URLs
|
|
||||||
homepage_url = reverse('core:homepage')
|
|
||||||
print(f"✅ Homepage URL: {homepage_url}")
|
|
||||||
|
|
||||||
marketplace_url = reverse('agent_base:marketplace')
|
|
||||||
print(f"✅ Marketplace URL: {marketplace_url}")
|
|
||||||
|
|
||||||
# Test weather reporter URL
|
|
||||||
weather_url = reverse('weather_reporter:detail')
|
|
||||||
print(f"✅ Weather Reporter URL: {weather_url}")
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"❌ URL resolution error: {e}")
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
test_agent_visibility()
|
|
||||||
check_url_structure()
|
|
||||||
@ -1,74 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import django
|
|
||||||
|
|
||||||
# Add the project root to Python path
|
|
||||||
sys.path.insert(0, '/home/amit/projects/quantumtaskai_django')
|
|
||||||
|
|
||||||
# Set Django settings
|
|
||||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'quantumtaskai_hub.settings')
|
|
||||||
django.setup()
|
|
||||||
|
|
||||||
from django.test import Client
|
|
||||||
from django.contrib.auth import get_user_model
|
|
||||||
|
|
||||||
User = get_user_model()
|
|
||||||
|
|
||||||
def test_homepage():
|
|
||||||
print("🧪 Testing Homepage Agent Display")
|
|
||||||
print("=" * 40)
|
|
||||||
|
|
||||||
# Create a test client
|
|
||||||
client = Client()
|
|
||||||
|
|
||||||
# Get homepage
|
|
||||||
response = client.get('/')
|
|
||||||
print(f"✅ Homepage response status: {response.status_code}")
|
|
||||||
|
|
||||||
# Check if agents are in context
|
|
||||||
if 'featured_agents' in response.context:
|
|
||||||
agents = response.context['featured_agents']
|
|
||||||
print(f"✅ Featured agents found: {agents.count()}")
|
|
||||||
|
|
||||||
for agent in agents:
|
|
||||||
print(f" 📋 {agent.name} ({agent.slug}) - {agent.price} AED")
|
|
||||||
else:
|
|
||||||
print("❌ No featured_agents in context")
|
|
||||||
|
|
||||||
# Check if Weather Reporter is in the HTML
|
|
||||||
html_content = response.content.decode('utf-8')
|
|
||||||
if 'Weather Reporter' in html_content:
|
|
||||||
print("✅ Weather Reporter found in HTML")
|
|
||||||
else:
|
|
||||||
print("❌ Weather Reporter not found in HTML")
|
|
||||||
|
|
||||||
if 'Use Now' in html_content:
|
|
||||||
print("✅ 'Use Now' buttons found in HTML")
|
|
||||||
else:
|
|
||||||
print("❌ 'Use Now' buttons not found in HTML")
|
|
||||||
|
|
||||||
def test_agent_direct_access():
|
|
||||||
print("\n🧪 Testing Direct Agent Access")
|
|
||||||
print("=" * 40)
|
|
||||||
|
|
||||||
client = Client()
|
|
||||||
|
|
||||||
# Test direct access to weather reporter
|
|
||||||
response = client.get('/agents/weather-reporter/')
|
|
||||||
print(f"✅ Weather Reporter direct access: {response.status_code}")
|
|
||||||
|
|
||||||
if response.status_code == 200:
|
|
||||||
html_content = response.content.decode('utf-8')
|
|
||||||
if 'Weather Reporter Agent' in html_content:
|
|
||||||
print("✅ Weather Reporter page loads correctly")
|
|
||||||
else:
|
|
||||||
print("❌ Weather Reporter page content issue")
|
|
||||||
elif response.status_code == 302:
|
|
||||||
print(f"✅ Redirected to: {response.url}")
|
|
||||||
else:
|
|
||||||
print(f"❌ Unexpected status code: {response.status_code}")
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
test_homepage()
|
|
||||||
test_agent_direct_access()
|
|
||||||
Loading…
Reference in New Issue
Block a user