Add comprehensive deployment automation and prevention system

🎯 Future-proof deployment system:

1. DEPLOYMENT_CHECKLIST.md - Zero-fail step-by-step guide
2. scripts/pre-deploy-check.sh - Validates everything before deployment
3. scripts/post-deploy-verify.sh - Tests deployment after completion
4. .github/workflows/deploy.yml - Automated GitHub Actions validation

 Key features:
- Catches static files, migrations, Docker issues before deployment
- Provides clear error messages and next steps
- Tests all endpoints after deployment
- 5-minute deployment target with this system
- Copy-paste templates for new projects

Run: ./scripts/pre-deploy-check.sh before every deployment
Run: ./scripts/post-deploy-verify.sh after deployment

Never face deployment issues again! 🚀
This commit is contained in:
amitrana01 2025-09-11 18:52:42 +05:30
parent 3827944aa5
commit 85ebac761d
4 changed files with 513 additions and 0 deletions

89
.github/workflows/deploy.yml vendored Normal file
View File

@ -0,0 +1,89 @@
name: 🚀 Deploy to Dokploy
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
workflow_dispatch:
jobs:
pre-deploy-checks:
runs-on: ubuntu-latest
name: 🔍 Pre-deployment validation
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
- name: Cache Python dependencies
uses: actions/cache@v3
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('requirements/production.txt') }}
- name: Install Python dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements/production.txt
- name: Install and build Tailwind CSS
run: |
cd theme/static_src
npm install
npm run build
- name: Run Django system checks
run: |
export DJANGO_SETTINGS_MODULE=django_project.settings.production
export SECRET_KEY=github-actions-secret-key
export ALLOWED_HOSTS=localhost
export DEBUG=False
python manage.py check --deploy
- name: Test static file collection
run: |
export DJANGO_SETTINGS_MODULE=django_project.settings.build
python manage.py collectstatic --noinput --dry-run
- name: Check for pending migrations
run: |
export DJANGO_SETTINGS_MODULE=django_project.settings.production
export SECRET_KEY=github-actions-secret-key
export DATABASE_URL=sqlite:///temp.db
python manage.py makemigrations --check --dry-run
- name: Test Docker build
run: |
docker build --target production -t django-template-test .
docker rmi django-template-test
deploy:
runs-on: ubuntu-latest
name: 📤 Deploy notification
needs: pre-deploy-checks
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
steps:
- name: ✅ Pre-deployment checks passed
run: |
echo "🎉 All pre-deployment checks passed!"
echo "🚀 Ready for deployment to Dokploy"
echo "📋 Manual steps required:"
echo " 1. Trigger deployment in Dokploy dashboard"
echo " 2. Wait for build completion"
echo " 3. Run post-deployment verification"
- name: 📝 Deployment reminder
if: success()
run: |
echo "::notice::Deployment ready! Trigger deployment in Dokploy manually"

162
DEPLOYMENT_CHECKLIST.md Normal file
View File

@ -0,0 +1,162 @@
# 🚀 Django Deployment Checklist - Zero-Fail Guide
Use this checklist to deploy Django projects smoothly every time.
## ✅ **Pre-Deployment Checklist**
### **1. Static Files & Assets**
- [ ] **Build Tailwind CSS locally**: `npm run build` in theme/static_src/
- [ ] **Verify CSS files exist**: Check `theme/static/css/dist/styles.css` exists
- [ ] **Test collectstatic locally**: `python manage.py collectstatic --noinput`
- [ ] **Commit static files**: Ensure built assets are in Git
### **2. Database & Migrations**
- [ ] **Create migrations**: `python manage.py makemigrations`
- [ ] **Test migrations locally**: `python manage.py migrate`
- [ ] **Verify Sites framework**: Check `django.contrib.sites` in INSTALLED_APPS
- [ ] **Test site creation**: Run `python manage.py configure_site` locally
### **3. Environment Configuration**
- [ ] **Update .env.example**: Include all required variables
- [ ] **Document required vars**: List in README what's needed for production
- [ ] **Test with production settings**: `DJANGO_SETTINGS_MODULE=project.settings.production`
### **4. Docker Configuration**
- [ ] **Test Docker build**: `docker build --target production .`
- [ ] **Verify startup script**: Ensure `startup.sh` is executable
- [ ] **Test compose file**: `docker-compose -f docker-compose.dokploy-simple.yml up`
## 🔧 **Deployment Steps (Dokploy)**
### **Step 1: Repository Setup**
- [ ] Push all changes to main branch
- [ ] Verify compose file path is correct in Dokploy
- [ ] Check Dockerfile builds successfully
### **Step 2: Environment Variables**
Set these in Dokploy environment tab:
```env
SECRET_KEY=your-long-secret-key-here
DEBUG=False
ALLOWED_HOSTS=yourdomain.com,www.yourdomain.com
CSRF_TRUSTED_ORIGINS=https://yourdomain.com
SECURE_SSL_REDIRECT=True
DATABASE_URL=postgresql://... (if using external DB)
```
### **Step 3: Domain Configuration**
- [ ] DNS: Point domain to Dokploy server IP
- [ ] Dokploy Domain: Set service=web, port=8000
- [ ] HTTPS: Enable SSL/Auto SSL
- [ ] Wait 2-3 minutes for SSL certificate
### **Step 4: Deploy & Verify**
- [ ] Deploy application
- [ ] Check deployment logs for errors
- [ ] Test endpoints:
- [ ] Homepage: `https://yourdomain.com/`
- [ ] Health: `https://yourdomain.com/health/`
- [ ] Login: `https://yourdomain.com/accounts/login/`
- [ ] Admin: `https://yourdomain.com/admin/`
## 🛡️ **Common Issues Prevention**
### **Static Files**
**DO**: Build static files during Docker build
**DON'T**: Rely on runtime collectstatic with volume mounts
### **Database Migrations**
**DO**: Run explicit site migration: `migrate sites`
**DON'T**: Assume all migrations run automatically
### **Environment Variables**
**DO**: Use environment variables for all settings
**DON'T**: Hardcode production values in settings files
### **Docker Configuration**
**DO**: Use simple port mapping (ports: "8000:8000")
**DON'T**: Use complex Traefik labels unless necessary
## 🚀 **Quick Deploy Templates**
### **For New Projects** (Copy-Paste Ready)
**docker-compose.dokploy.yml:**
```yaml
services:
web:
build: .
ports:
- "8000:8000"
environment:
- DEBUG=${DEBUG:-False}
- ALLOWED_HOSTS=${ALLOWED_HOSTS}
- SECRET_KEY=${SECRET_KEY}
- DATABASE_URL=${DATABASE_URL:-postgresql://django_user:django_password@db:5432/django_db}
command: sh -c "chmod +x /app/startup.sh && /app/startup.sh"
depends_on:
- db
db:
image: postgres:15-alpine
environment:
- POSTGRES_DB=django_db
- POSTGRES_USER=django_user
- POSTGRES_PASSWORD=django_password
volumes:
- postgres_data:/var/lib/postgresql/data/
volumes:
postgres_data:
```
**startup.sh:**
```bash
#!/bin/bash
set -e
python manage.py migrate --noinput
python manage.py migrate sites --noinput
python manage.py collectstatic --noinput
exec gunicorn --bind 0.0.0.0:8000 django_project.wsgi:application
```
## 📋 **Environment Variables Template**
```env
SECRET_KEY=generate-long-random-key-here
DEBUG=False
ALLOWED_HOSTS=yourdomain.com
CSRF_TRUSTED_ORIGINS=https://yourdomain.com
SECURE_SSL_REDIRECT=True
DATABASE_URL=postgresql://user:pass@host:5432/db
```
## 🎯 **Time to Deploy: 5 Minutes**
With this checklist, deployment should take:
- ⏱️ **2 min**: Environment setup
- ⏱️ **2 min**: Docker build & deploy
- ⏱️ **1 min**: SSL certificate generation
**Total: 5 minutes from code to live site!** 🚀
## 🆘 **Emergency Debugging**
If deployment fails:
1. **Check logs**: Look for specific error messages
2. **Test health endpoint**: `/health/` shows Django status
3. **Verify environment**: Check env vars are set correctly
4. **Database connection**: Ensure DATABASE_URL is correct
5. **Static files**: Verify CSS files exist in image
## 🔄 **Automation Ideas**
Future improvements:
- [ ] GitHub Actions for automated deployments
- [ ] Pre-commit hooks for static file builds
- [ ] Docker health checks
- [ ] Automated backup scripts
- [ ] Monitoring and alerting setup
---
**Follow this checklist and you'll never have deployment issues again!** ✅

158
scripts/post-deploy-verify.sh Executable file
View File

@ -0,0 +1,158 @@
#!/bin/bash
# Post-deployment verification script
# Run this after deployment to verify everything is working
set -e
# Default domain (can be overridden)
DOMAIN=${1:-"dt.netcoptech.com"}
PROTOCOL=${2:-"https"}
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
echo "🔍 Verifying deployment for $PROTOCOL://$DOMAIN"
# Function to test URL
test_url() {
local url=$1
local expected_status=${2:-200}
local description=$3
echo "Testing: $description"
# Use curl to test the URL
if command -v curl > /dev/null 2>&1; then
response=$(curl -s -o /dev/null -w "%{http_code}" -L "$url" 2>/dev/null || echo "000")
else
echo -e "${YELLOW}⚠️ curl not found, skipping URL test${NC}"
return 0
fi
if [ "$response" -eq "$expected_status" ]; then
echo -e "${GREEN}$description - HTTP $response${NC}"
elif [ "$response" -eq "000" ]; then
echo -e "${RED}$description - Connection failed${NC}"
return 1
else
echo -e "${RED}$description - HTTP $response (expected $expected_status)${NC}"
return 1
fi
}
# Function to test JSON endpoint
test_json_endpoint() {
local url=$1
local description=$2
echo "Testing: $description"
if command -v curl > /dev/null 2>&1; then
response=$(curl -s -L "$url" 2>/dev/null || echo "")
if echo "$response" | python3 -m json.tool > /dev/null 2>&1; then
echo -e "${GREEN}$description - Valid JSON response${NC}"
# Pretty print the response
echo "$response" | python3 -m json.tool | head -10
else
echo -e "${RED}$description - Invalid JSON response${NC}"
return 1
fi
else
echo -e "${YELLOW}⚠️ curl not found, skipping JSON test${NC}"
return 0
fi
}
echo ""
echo "🌐 Testing core endpoints..."
# Test main endpoints
test_url "$PROTOCOL://$DOMAIN/" 200 "Homepage"
test_json_endpoint "$PROTOCOL://$DOMAIN/health/" "Health check endpoint"
test_url "$PROTOCOL://$DOMAIN/accounts/login/" 200 "Login page"
test_url "$PROTOCOL://$DOMAIN/admin/" 302 "Admin panel (should redirect to login)"
echo ""
echo "🔒 Testing SSL/HTTPS..."
if [ "$PROTOCOL" = "https" ]; then
# Test SSL certificate
if command -v openssl > /dev/null 2>&1; then
echo "Checking SSL certificate..."
cert_info=$(echo | openssl s_client -servername "$DOMAIN" -connect "$DOMAIN:443" 2>/dev/null | openssl x509 -noout -dates 2>/dev/null || echo "")
if [ -n "$cert_info" ]; then
echo -e "${GREEN}✅ SSL certificate is valid${NC}"
echo "$cert_info"
else
echo -e "${RED}❌ SSL certificate check failed${NC}"
fi
else
echo -e "${YELLOW}⚠️ openssl not found, skipping SSL check${NC}"
fi
# Test HTTP to HTTPS redirect
if command -v curl > /dev/null 2>&1; then
redirect_response=$(curl -s -o /dev/null -w "%{redirect_url}" "http://$DOMAIN/" || echo "")
if [[ "$redirect_response" == "https://"* ]]; then
echo -e "${GREEN}✅ HTTP to HTTPS redirect working${NC}"
else
echo -e "${YELLOW}⚠️ HTTP to HTTPS redirect not detected${NC}"
fi
fi
else
echo "Testing HTTP deployment..."
fi
echo ""
echo "🗄️ Testing database connectivity..."
# Test if site is configured properly by checking login page
login_response=$(curl -s -L "$PROTOCOL://$DOMAIN/accounts/login/" 2>/dev/null || echo "")
if echo "$login_response" | grep -q "django_site" 2>/dev/null; then
echo -e "${RED}❌ Database error: django_site relation not found${NC}"
elif echo "$login_response" | grep -q "Login" 2>/dev/null; then
echo -e "${GREEN}✅ Database connectivity working${NC}"
else
echo -e "${YELLOW}⚠️ Unable to verify database connectivity${NC}"
fi
echo ""
echo "📱 Testing responsive design..."
# Test if CSS is loading
css_test=$(curl -s -L "$PROTOCOL://$DOMAIN/" 2>/dev/null | grep -o "styles\.css" || echo "")
if [ -n "$css_test" ]; then
echo -e "${GREEN}✅ CSS files are being loaded${NC}"
else
echo -e "${YELLOW}⚠️ CSS files may not be loading properly${NC}"
fi
echo ""
echo "🎯 Deployment verification summary:"
# Final health check
health_url="$PROTOCOL://$DOMAIN/health/"
if curl -s "$health_url" > /dev/null 2>&1; then
echo -e "${GREEN}🎉 Deployment successful!${NC}"
echo -e "${GREEN}✅ Your Django app is live and healthy${NC}"
echo ""
echo "🔗 Important URLs:"
echo " Homepage: $PROTOCOL://$DOMAIN/"
echo " Login: $PROTOCOL://$DOMAIN/accounts/login/"
echo " Admin: $PROTOCOL://$DOMAIN/admin/"
echo " Health: $PROTOCOL://$DOMAIN/health/"
echo ""
echo "Next steps:"
echo "1. Create your admin user: python manage.py createsuperuser"
echo "2. Configure social authentication in admin panel"
echo "3. Test all functionality thoroughly"
else
echo -e "${RED}❌ Deployment verification failed${NC}"
echo "Check deployment logs and retry"
exit 1
fi

104
scripts/pre-deploy-check.sh Executable file
View File

@ -0,0 +1,104 @@
#!/bin/bash
# Pre-deployment validation script
# Run this before every deployment to catch issues early
set -e
echo "🔍 Running pre-deployment checks..."
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Function to print status
print_status() {
if [ $1 -eq 0 ]; then
echo -e "${GREEN}$2${NC}"
else
echo -e "${RED}$2${NC}"
exit 1
fi
}
print_warning() {
echo -e "${YELLOW}⚠️ $1${NC}"
}
# Check 1: Verify Tailwind CSS is built
echo "📦 Checking Tailwind CSS files..."
if [ -f "theme/static/css/dist/styles.css" ]; then
print_status 0 "Tailwind CSS files exist"
else
print_status 1 "Tailwind CSS not built. Run: cd theme/static_src && npm run build"
fi
# Check 2: Test collectstatic
echo "📁 Testing static file collection..."
if python manage.py collectstatic --noinput --dry-run > /dev/null 2>&1; then
print_status 0 "Static files collection test passed"
else
print_status 1 "Static files collection failed. Check STATIC_ROOT and STATICFILES_DIRS"
fi
# Check 3: Check for pending migrations
echo "🗄️ Checking for pending migrations..."
if python manage.py showmigrations --plan | grep -q "\[ \]"; then
print_status 1 "Pending migrations found. Run: python manage.py makemigrations"
else
print_status 0 "No pending migrations"
fi
# Check 4: Validate Django configuration
echo "⚙️ Validating Django settings..."
if python manage.py check > /dev/null 2>&1; then
print_status 0 "Django configuration valid"
else
print_status 1 "Django configuration issues found. Run: python manage.py check"
fi
# Check 5: Test Docker build
echo "🐳 Testing Docker build..."
if docker build --target production -t django-deploy-test . > /dev/null 2>&1; then
print_status 0 "Docker build successful"
docker rmi django-deploy-test > /dev/null 2>&1 || true
else
print_status 1 "Docker build failed. Check Dockerfile"
fi
# Check 6: Verify startup script
echo "🚀 Checking startup script..."
if [ -x "startup.sh" ]; then
print_status 0 "Startup script is executable"
else
print_status 1 "Startup script not executable. Run: chmod +x startup.sh"
fi
# Check 7: Validate environment variables
echo "🔐 Checking environment configuration..."
if [ -f ".env.example" ]; then
print_status 0 "Environment example file exists"
else
print_warning "No .env.example file found. Consider creating one"
fi
# Check 8: Verify required files
required_files=("manage.py" "requirements/production.txt" "docker-compose.dokploy-simple.yml")
for file in "${required_files[@]}"; do
if [ -f "$file" ]; then
print_status 0 "Required file exists: $file"
else
print_status 1 "Missing required file: $file"
fi
done
echo ""
echo -e "${GREEN}🎉 All pre-deployment checks passed!${NC}"
echo -e "${GREEN}✅ Ready for deployment!${NC}"
echo ""
echo "Next steps:"
echo "1. git add . && git commit -m 'Ready for deployment' && git push"
echo "2. Deploy in Dokploy"
echo "3. Test endpoints after deployment"