docs: remove duplicated setup guides
Co-authored-by: dennis <dennis@konkol.net>
This commit is contained in:
@@ -1,200 +0,0 @@
|
||||
# 🚀 Deployment Setup Guide
|
||||
|
||||
## Overview
|
||||
|
||||
This project uses a **dual-branch deployment strategy** with zero-downtime deployments:
|
||||
|
||||
- **Production Branch** (`production`) → Serves `https://dk0.dev` on port 3000
|
||||
- **Dev Branch** (`dev`) → Serves `https://dev.dk0.dev` on port 3002
|
||||
|
||||
Both environments are completely isolated with separate:
|
||||
- Docker containers
|
||||
- Databases (PostgreSQL)
|
||||
- Redis instances
|
||||
- Networks
|
||||
- Volumes
|
||||
|
||||
## Branch Strategy
|
||||
|
||||
### Production Branch
|
||||
- **Branch**: `production`
|
||||
- **Domain**: `https://dk0.dev`
|
||||
- **Port**: `3000`
|
||||
- **Container**: `portfolio-app`
|
||||
- **Database**: `portfolio_db` (port 5432)
|
||||
- **Redis**: `portfolio-redis` (port 6379)
|
||||
- **Image Tag**: `portfolio-app:production` / `portfolio-app:latest`
|
||||
|
||||
### Dev Branch
|
||||
- **Branch**: `dev`
|
||||
- **Domain**: `https://dev.dk0.dev`
|
||||
- **Port**: `3002`
|
||||
- **Container**: `portfolio-app-staging`
|
||||
- **Database**: `portfolio_staging_db` (port 5434)
|
||||
- **Redis**: `portfolio-redis-staging` (port 6381)
|
||||
- **Image Tag**: `portfolio-app:staging`
|
||||
|
||||
## Automatic Deployment
|
||||
|
||||
### How It Works
|
||||
|
||||
1. **Push to `production` branch**:
|
||||
- Triggers `.gitea/workflows/production-deploy.yml`
|
||||
- Runs tests, builds, and deploys to production
|
||||
- Zero-downtime deployment (starts new container, waits for health, removes old)
|
||||
|
||||
2. **Push to `dev` branch**:
|
||||
- Triggers `.gitea/workflows/dev-deploy.yml`
|
||||
- Runs tests, builds, and deploys to dev/staging
|
||||
- Zero-downtime deployment
|
||||
|
||||
### Zero-Downtime Process
|
||||
|
||||
1. Build new Docker image
|
||||
2. Start new container with updated image
|
||||
3. Wait for new container to be healthy (health checks)
|
||||
4. Verify HTTP endpoints respond correctly
|
||||
5. Remove old container (if different)
|
||||
6. Cleanup old images
|
||||
|
||||
## Manual Deployment
|
||||
|
||||
### Production
|
||||
```bash
|
||||
# Build and deploy production
|
||||
docker build -t portfolio-app:latest .
|
||||
docker compose -f docker-compose.production.yml up -d --build
|
||||
```
|
||||
|
||||
### Dev/Staging
|
||||
```bash
|
||||
# Build and deploy dev
|
||||
docker build -t portfolio-app:staging .
|
||||
docker compose -f docker-compose.staging.yml up -d --build
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
### Required Gitea Variables
|
||||
- `NEXT_PUBLIC_BASE_URL` - Base URL for the application
|
||||
- `MY_EMAIL` - Email address for contact
|
||||
- `MY_INFO_EMAIL` - Info email address
|
||||
- `LOG_LEVEL` - Logging level (info/debug)
|
||||
|
||||
### Required Gitea Secrets
|
||||
- `MY_PASSWORD` - Email password
|
||||
- `MY_INFO_PASSWORD` - Info email password
|
||||
- `ADMIN_BASIC_AUTH` - Admin basic auth credentials
|
||||
- `N8N_SECRET_TOKEN` - Optional: n8n webhook secret
|
||||
|
||||
### Optional Variables
|
||||
- `N8N_WEBHOOK_URL` - n8n webhook URL for automation
|
||||
|
||||
## Health Checks
|
||||
|
||||
Both environments have health check endpoints:
|
||||
- Production: `http://localhost:3000/api/health`
|
||||
- Dev: `http://localhost:3002/api/health`
|
||||
|
||||
## Monitoring
|
||||
|
||||
### Check Container Status
|
||||
```bash
|
||||
# Production
|
||||
docker compose -f docker-compose.production.yml ps
|
||||
|
||||
# Dev
|
||||
docker compose -f docker-compose.staging.yml ps
|
||||
```
|
||||
|
||||
### View Logs
|
||||
```bash
|
||||
# Production
|
||||
docker logs portfolio-app --tail=100 -f
|
||||
|
||||
# Dev
|
||||
docker logs portfolio-app-staging --tail=100 -f
|
||||
```
|
||||
|
||||
### Health Check
|
||||
```bash
|
||||
# Production
|
||||
curl http://localhost:3000/api/health
|
||||
|
||||
# Dev
|
||||
curl http://localhost:3002/api/health
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Container Won't Start
|
||||
1. Check logs: `docker logs <container-name>`
|
||||
2. Verify environment variables are set
|
||||
3. Check database/redis connectivity
|
||||
4. Verify ports aren't already in use
|
||||
|
||||
### Deployment Fails
|
||||
1. Check Gitea Actions logs
|
||||
2. Verify all required secrets/variables are set
|
||||
3. Check if old containers are blocking ports
|
||||
4. Verify Docker image builds successfully
|
||||
|
||||
### Zero-Downtime Issues
|
||||
- Old container might still be running - check with `docker ps`
|
||||
- Health checks might be failing - check container logs
|
||||
- Port conflicts - verify ports 3000 and 3002 are available
|
||||
|
||||
## Rollback
|
||||
|
||||
If a deployment fails or causes issues:
|
||||
|
||||
```bash
|
||||
# Production rollback
|
||||
docker compose -f docker-compose.production.yml down
|
||||
docker tag portfolio-app:previous portfolio-app:latest
|
||||
docker compose -f docker-compose.production.yml up -d
|
||||
|
||||
# Dev rollback
|
||||
docker compose -f docker-compose.staging.yml down
|
||||
docker tag portfolio-app:staging-previous portfolio-app:staging
|
||||
docker compose -f docker-compose.staging.yml up -d
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Always test on dev branch first** before pushing to production
|
||||
2. **Monitor health checks** after deployment
|
||||
3. **Keep old images** for quick rollback (last 3 versions)
|
||||
4. **Use feature flags** for new features
|
||||
5. **Document breaking changes** before deploying
|
||||
6. **Run tests locally** before pushing
|
||||
|
||||
## Network Configuration
|
||||
|
||||
- **Production Network**: `portfolio_net` + `proxy` (external)
|
||||
- **Dev Network**: `portfolio_staging_net`
|
||||
- **Isolation**: Complete separation ensures no interference
|
||||
|
||||
## Database Management
|
||||
|
||||
### Production Database
|
||||
- **Container**: `portfolio-postgres`
|
||||
- **Port**: `5432` (internal only)
|
||||
- **Database**: `portfolio_db`
|
||||
- **User**: `portfolio_user`
|
||||
|
||||
### Dev Database
|
||||
- **Container**: `portfolio-postgres-staging`
|
||||
- **Port**: `5434` (external), `5432` (internal)
|
||||
- **Database**: `portfolio_staging_db`
|
||||
- **User**: `portfolio_user`
|
||||
|
||||
## Redis Configuration
|
||||
|
||||
### Production Redis
|
||||
- **Container**: `portfolio-redis`
|
||||
- **Port**: `6379` (internal only)
|
||||
|
||||
### Dev Redis
|
||||
- **Container**: `portfolio-redis-staging`
|
||||
- **Port**: `6381` (external), `6379` (internal)
|
||||
239
DEV-SETUP.md
239
DEV-SETUP.md
@@ -1,239 +0,0 @@
|
||||
# 🚀 Development Environment Setup
|
||||
|
||||
This document explains how to set up and use the development environment for the portfolio project.
|
||||
|
||||
## ✨ Features
|
||||
|
||||
- **Automatic Database Setup**: PostgreSQL and Redis start automatically
|
||||
- **Hot Reload**: Next.js development server with hot reload
|
||||
- **Database Integration**: Real database integration for email management
|
||||
- **Modern Admin Dashboard**: Completely redesigned admin interface
|
||||
- **Minimal Setup**: Only essential services for fast development
|
||||
|
||||
## 🛠️ Quick Start
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Node.js 18+
|
||||
- Docker & Docker Compose
|
||||
- npm or yarn
|
||||
|
||||
### 1. Install Dependencies
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
### 2. Start Development Environment
|
||||
|
||||
#### Option A: Full Development Environment (with Docker)
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
This single command will:
|
||||
- Start PostgreSQL database
|
||||
- Start Redis cache
|
||||
- Start Next.js development server
|
||||
- Set up all environment variables
|
||||
|
||||
#### Option B: Simple Development Mode (without Docker)
|
||||
```bash
|
||||
npm run dev:simple
|
||||
```
|
||||
|
||||
This starts only the Next.js development server without Docker services. Use this if you don't have Docker installed or want a faster startup.
|
||||
|
||||
### 3. Access Services
|
||||
|
||||
- **Portfolio**: http://localhost:3000
|
||||
- **Admin Dashboard**: http://localhost:3000/manage
|
||||
- **PostgreSQL**: localhost:5432
|
||||
- **Redis**: localhost:6379
|
||||
|
||||
## 📧 Email Testing
|
||||
|
||||
The development environment supports email functionality:
|
||||
|
||||
1. Send emails through the contact form or admin panel
|
||||
2. Emails are sent directly (configure SMTP in production)
|
||||
3. Check console logs for email debugging
|
||||
|
||||
## 🗄️ Database
|
||||
|
||||
### Development Database
|
||||
|
||||
- **Host**: localhost:5432
|
||||
- **Database**: portfolio_dev
|
||||
- **User**: portfolio_user
|
||||
- **Password**: portfolio_dev_pass
|
||||
|
||||
### Database Commands
|
||||
|
||||
```bash
|
||||
# Generate Prisma client
|
||||
npm run db:generate
|
||||
|
||||
# Push schema changes
|
||||
npm run db:push
|
||||
|
||||
# Seed database with sample data
|
||||
npm run db:seed
|
||||
|
||||
# Open Prisma Studio
|
||||
npm run db:studio
|
||||
|
||||
# Reset database
|
||||
npm run db:reset
|
||||
```
|
||||
|
||||
## 🎨 Admin Dashboard
|
||||
|
||||
The new admin dashboard includes:
|
||||
|
||||
- **Overview**: Statistics and recent activity
|
||||
- **Projects**: Manage portfolio projects
|
||||
- **Emails**: Handle contact form submissions with beautiful templates
|
||||
- **Analytics**: View performance metrics
|
||||
- **Settings**: Import/export functionality
|
||||
|
||||
### Email Templates
|
||||
|
||||
Three beautiful email templates are available:
|
||||
|
||||
1. **Welcome Template** (Green): Friendly greeting with portfolio links
|
||||
2. **Project Template** (Purple): Professional project discussion response
|
||||
3. **Quick Template** (Orange): Fast acknowledgment response
|
||||
|
||||
## 🔧 Environment Variables
|
||||
|
||||
Create a `.env.local` file:
|
||||
|
||||
```env
|
||||
# Development Database
|
||||
DATABASE_URL="postgresql://portfolio_user:portfolio_dev_pass@localhost:5432/portfolio_dev?schema=public"
|
||||
|
||||
# Redis
|
||||
REDIS_URL="redis://localhost:6379"
|
||||
|
||||
# Email (for production)
|
||||
MY_EMAIL=contact@dk0.dev
|
||||
MY_PASSWORD=your-email-password
|
||||
|
||||
# Application
|
||||
NEXT_PUBLIC_BASE_URL=http://localhost:3000
|
||||
NODE_ENV=development
|
||||
```
|
||||
|
||||
## 🛑 Stopping the Environment
|
||||
|
||||
Use Ctrl+C to stop all services, or:
|
||||
|
||||
```bash
|
||||
# Stop Docker services only
|
||||
npm run docker:dev:down
|
||||
```
|
||||
|
||||
## 🐳 Docker Commands
|
||||
|
||||
```bash
|
||||
# Start only database services
|
||||
npm run docker:dev
|
||||
|
||||
# Stop database services
|
||||
npm run docker:dev:down
|
||||
|
||||
# View logs
|
||||
docker compose -f docker-compose.dev.minimal.yml logs -f
|
||||
```
|
||||
|
||||
## 📁 Project Structure
|
||||
|
||||
```
|
||||
├── docker-compose.dev.minimal.yml # Minimal development services
|
||||
├── scripts/
|
||||
│ ├── dev-minimal.js # Main development script
|
||||
│ ├── dev-simple.js # Simple development script
|
||||
│ ├── setup-database.js # Database setup script
|
||||
│ └── init-db.sql # Database initialization
|
||||
├── app/
|
||||
│ ├── admin/ # Admin dashboard
|
||||
│ ├── api/
|
||||
│ │ ├── contacts/ # Contact management API
|
||||
│ │ └── email/ # Email sending API
|
||||
│ └── components/
|
||||
│ ├── ModernAdminDashboard.tsx
|
||||
│ ├── EmailManager.tsx
|
||||
│ └── EmailResponder.tsx
|
||||
└── prisma/
|
||||
└── schema.prisma # Database schema
|
||||
```
|
||||
|
||||
## 🚨 Troubleshooting
|
||||
|
||||
### Docker Compose Not Found
|
||||
|
||||
If you get the error `spawn docker compose ENOENT`:
|
||||
|
||||
```bash
|
||||
# Try the simple dev mode instead
|
||||
npm run dev:simple
|
||||
|
||||
# Or install Docker Desktop
|
||||
# Download from: https://www.docker.com/products/docker-desktop
|
||||
```
|
||||
|
||||
### Port Conflicts
|
||||
|
||||
If ports are already in use:
|
||||
|
||||
```bash
|
||||
# Check what's using the ports
|
||||
lsof -i :3000
|
||||
lsof -i :5432
|
||||
lsof -i :6379
|
||||
|
||||
# Kill processes if needed
|
||||
kill -9 <PID>
|
||||
```
|
||||
|
||||
### Database Connection Issues
|
||||
|
||||
```bash
|
||||
# Restart database services
|
||||
npm run docker:dev:down
|
||||
npm run docker:dev
|
||||
|
||||
# Check database status
|
||||
docker compose -f docker-compose.dev.minimal.yml ps
|
||||
```
|
||||
|
||||
### Email Not Working
|
||||
|
||||
1. Verify environment variables
|
||||
2. Check browser console for errors
|
||||
3. Ensure SMTP is configured for production
|
||||
|
||||
## 🎯 Production Deployment
|
||||
|
||||
For production deployment, use:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
npm run start
|
||||
```
|
||||
|
||||
The production environment uses the production Docker Compose configuration.
|
||||
|
||||
## 📝 Notes
|
||||
|
||||
- The development environment automatically creates sample data
|
||||
- Database changes are persisted in Docker volumes
|
||||
- Hot reload works for all components and API routes
|
||||
- Minimal setup for fast development startup
|
||||
|
||||
## 🔗 Links
|
||||
|
||||
- **Portfolio**: https://dk0.dev
|
||||
- **Admin**: https://dk0.dev/manage
|
||||
- **GitHub**: https://github.com/denniskonkol/portfolio
|
||||
@@ -1,153 +0,0 @@
|
||||
# 🔧 Gitea Variables & Secrets Setup Guide
|
||||
|
||||
## Übersicht
|
||||
|
||||
In Gitea kannst du **Variables** (öffentlich) und **Secrets** (verschlüsselt) für dein Repository setzen. Diese werden in den CI/CD Workflows verwendet.
|
||||
|
||||
## 📍 Wo findest du die Einstellungen?
|
||||
|
||||
1. Gehe zu deinem Repository auf Gitea
|
||||
2. Klicke auf **Settings** (Einstellungen)
|
||||
3. Klicke auf **Variables** oder **Secrets** im linken Menü
|
||||
|
||||
## 🔑 Variablen für Production Branch (`production` → `dk0.dev`)
|
||||
|
||||
Für den `production` Branch brauchst du:
|
||||
|
||||
### Variables (öffentlich sichtbar):
|
||||
- `NEXT_PUBLIC_BASE_URL_PRODUCTION` = `https://dk0.dev`
|
||||
- `MY_EMAIL` = `contact@dk0.dev` (oder deine Email)
|
||||
- `MY_INFO_EMAIL` = `info@dk0.dev` (oder deine Info-Email)
|
||||
- `LOG_LEVEL` = `info`
|
||||
- `N8N_WEBHOOK_URL` = `https://n8n.dk0.dev` (optional)
|
||||
|
||||
### Secrets (verschlüsselt):
|
||||
- `MY_PASSWORD` = Dein Email-Passwort
|
||||
- `MY_INFO_PASSWORD` = Dein Info-Email-Passwort
|
||||
- `ADMIN_BASIC_AUTH` = `admin:dein_sicheres_passwort`
|
||||
- `ADMIN_SESSION_SECRET` = zufälliger Secret (mind. 32 Zeichen)
|
||||
- `N8N_SECRET_TOKEN` = Dein n8n Secret Token (optional)
|
||||
|
||||
## 🧪 Variablen für Dev Branch
|
||||
|
||||
Für den `testing` Branch brauchst du die **gleichen** Variablen, aber mit anderen Werten:
|
||||
|
||||
### Variables:
|
||||
- `NEXT_PUBLIC_BASE_URL_TESTING` = `https://testing.dk0.dev` ⚠️ **WICHTIG: Andere URL!**
|
||||
- `MY_EMAIL` = `contact@dk0.dev` (kann gleich sein)
|
||||
- `MY_INFO_EMAIL` = `info@dk0.dev` (kann gleich sein)
|
||||
- `LOG_LEVEL` = `debug` (für Dev mehr Logging)
|
||||
- `N8N_WEBHOOK_URL` = `https://n8n.dk0.dev` (optional)
|
||||
|
||||
### Secrets:
|
||||
- `MY_PASSWORD` = Dein Email-Passwort (kann gleich sein)
|
||||
- `MY_INFO_PASSWORD` = Dein Info-Email-Passwort (kann gleich sein)
|
||||
- `ADMIN_BASIC_AUTH` = `admin:testing_password` (kann anders sein)
|
||||
- `ADMIN_SESSION_SECRET` = zufälliger Secret (mind. 32 Zeichen; kann gleich sein)
|
||||
- `N8N_SECRET_TOKEN` = Dein n8n Secret Token (optional)
|
||||
|
||||
## ✅ Lösung: Automatische Branch-Erkennung
|
||||
|
||||
**Gitea unterstützt keine branch-spezifischen Variablen, aber die Workflows erkennen automatisch den Branch!**
|
||||
|
||||
### Wie es funktioniert:
|
||||
|
||||
Die Workflows triggern auf unterschiedlichen Branches und verwenden automatisch die richtigen Defaults:
|
||||
|
||||
**Production Workflow** (`.gitea/workflows/production-deploy.yml`):
|
||||
- Triggert nur auf `production` Branch
|
||||
- Verwendet: `NEXT_PUBLIC_BASE_URL_PRODUCTION` (wenn gesetzt) oder Default: `https://dk0.dev`
|
||||
|
||||
**Testing Workflow** (`.gitea/workflows/dev-deploy.yml`):
|
||||
- Triggert nur auf `testing` Branch
|
||||
- Verwendet: `NEXT_PUBLIC_BASE_URL_TESTING` (wenn gesetzt) oder Default: `https://testing.dk0.dev`
|
||||
|
||||
**Das bedeutet:**
|
||||
- Du setzt **zwei** Variablen in Gitea (empfohlen, weil Gitea nicht branch-spezifisch scoped):
|
||||
- `NEXT_PUBLIC_BASE_URL_PRODUCTION`
|
||||
- `NEXT_PUBLIC_BASE_URL_TESTING`
|
||||
|
||||
### ⚠️ WICHTIG:
|
||||
Gitea kann Variablen/Secrets nicht pro Branch trennen. Darum nutzen wir **separate Variablennamen** für Production und Testing.
|
||||
|
||||
## ✅ Empfohlene Konfiguration
|
||||
|
||||
### ⭐ Einfachste Lösung: nur URLs setzen (optional)
|
||||
|
||||
Die Workflows haben bereits die richtigen Defaults:
|
||||
- **Production Branch** → automatisch `https://dk0.dev`
|
||||
- **Testing Branch** → automatisch `https://testing.dk0.dev`
|
||||
|
||||
Du musst **NICHTS** in Gitea setzen, es funktioniert automatisch!
|
||||
|
||||
### Wenn du Variablen setzen willst:
|
||||
|
||||
**Nur diese Variablen setzen (für beide Branches):**
|
||||
- `MY_EMAIL` = `contact@dk0.dev`
|
||||
- `MY_INFO_EMAIL` = `info@dk0.dev`
|
||||
- `LOG_LEVEL` = `info` (wird für Production verwendet, Dev überschreibt mit `debug`)
|
||||
|
||||
**Secrets (für beide Branches):**
|
||||
- `MY_PASSWORD` = Dein Email-Passwort
|
||||
- `MY_INFO_PASSWORD` = Dein Info-Email-Passwort
|
||||
- `ADMIN_BASIC_AUTH` = `admin:dein_passwort`
|
||||
- `ADMIN_SESSION_SECRET` = zufälliger Secret (mind. 32 Zeichen)
|
||||
- `N8N_SECRET_TOKEN` = Dein n8n Token (optional)
|
||||
|
||||
**Optional setzen:**
|
||||
- `NEXT_PUBLIC_BASE_URL_PRODUCTION` = `https://dk0.dev`
|
||||
- `NEXT_PUBLIC_BASE_URL_TESTING` = `https://testing.dk0.dev`
|
||||
|
||||
## 📝 Schritt-für-Schritt Anleitung
|
||||
|
||||
### 1. Gehe zu Repository Settings
|
||||
```
|
||||
https://git.dk0.dev/denshooter/portfolio/settings
|
||||
```
|
||||
|
||||
### 2. Klicke auf "Variables" oder "Secrets"
|
||||
|
||||
### 3. Für Variables (öffentlich):
|
||||
- Klicke auf **"New Variable"**
|
||||
- **Name:** `NEXT_PUBLIC_BASE_URL_PRODUCTION`
|
||||
- **Value:** `https://dk0.dev`
|
||||
- **Protect:** ✅ (optional, schützt vor Änderungen)
|
||||
- Klicke **"Add Variable"**
|
||||
|
||||
- Klicke auf **"New Variable"**
|
||||
- **Name:** `NEXT_PUBLIC_BASE_URL_TESTING`
|
||||
- **Value:** `https://testing.dk0.dev`
|
||||
- **Protect:** ✅ (optional)
|
||||
- Klicke **"Add Variable"**
|
||||
|
||||
### 4. Für Secrets (verschlüsselt):
|
||||
- Klicke auf **"New Secret"**
|
||||
- **Name:** `MY_PASSWORD`
|
||||
- **Value:** Dein Passwort
|
||||
- Klicke **"Add Secret"**
|
||||
|
||||
## 🔄 Aktuelle Workflow-Logik
|
||||
|
||||
Die Workflows verwenden diese einfache Logik:
|
||||
|
||||
```yaml
|
||||
# Production Workflow (triggert nur auf production branch)
|
||||
NEXT_PUBLIC_BASE_URL: ${{ vars.NEXT_PUBLIC_BASE_URL_PRODUCTION || 'https://dk0.dev' }}
|
||||
|
||||
# Testing Workflow (triggert nur auf testing branch)
|
||||
NEXT_PUBLIC_BASE_URL: ${{ vars.NEXT_PUBLIC_BASE_URL_TESTING || 'https://testing.dk0.dev' }}
|
||||
```
|
||||
|
||||
**Das bedeutet:**
|
||||
- Jeder Workflow hat seinen **eigenen Default**
|
||||
- Wenn die jeweilige Variable (`NEXT_PUBLIC_BASE_URL_PRODUCTION` / `NEXT_PUBLIC_BASE_URL_TESTING`) in Gitea gesetzt ist, wird diese verwendet
|
||||
- Wenn **nicht** gesetzt, verwendet jeder Branch seinen eigenen Default
|
||||
|
||||
**⭐ Beste Lösung:**
|
||||
- Setze `NEXT_PUBLIC_BASE_URL_PRODUCTION` und `NEXT_PUBLIC_BASE_URL_TESTING` (oder lass beide weg und nutze Defaults).
|
||||
|
||||
## 🎯 Best Practice
|
||||
|
||||
1. **Production (`production`)**: `docker-compose.production.yml` → Port 3000 → NPM Host `dk0.dev`
|
||||
2. **Testing (`testing`)**: `docker-compose.testing.yml` → Port 3002 → NPM Host `testing.dk0.dev`
|
||||
3. **Secrets**: immer als Gitea Secrets, nie im Code
|
||||
@@ -1,198 +0,0 @@
|
||||
# 🔧 Nginx Proxy Manager Setup Guide
|
||||
|
||||
## Übersicht
|
||||
|
||||
Dieses Projekt nutzt **Nginx Proxy Manager** als Reverse Proxy. Die Container sind im `proxy` Netzwerk, damit Nginx Proxy Manager auf sie zugreifen kann.
|
||||
|
||||
## 🐳 Docker Netzwerk-Konfiguration
|
||||
|
||||
Die Container sind bereits im `proxy` Netzwerk konfiguriert:
|
||||
|
||||
**Production:**
|
||||
```yaml
|
||||
networks:
|
||||
- portfolio_net
|
||||
- proxy # ✅ Bereits konfiguriert
|
||||
```
|
||||
|
||||
**Staging:**
|
||||
```yaml
|
||||
networks:
|
||||
- portfolio_staging_net
|
||||
- proxy # ✅ Bereits konfiguriert
|
||||
```
|
||||
|
||||
## 📋 Nginx Proxy Manager Konfiguration
|
||||
|
||||
### Production (dk0.dev)
|
||||
|
||||
1. **Gehe zu Nginx Proxy Manager** → Hosts → Proxy Hosts → Add Proxy Host
|
||||
|
||||
2. **Details Tab:**
|
||||
- **Domain Names:** `dk0.dev`, `www.dk0.dev`
|
||||
- **Scheme:** `http`
|
||||
- **Forward Hostname/IP:** `portfolio-app` (Container-Name)
|
||||
- **Forward Port:** `3000`
|
||||
- **Cache Assets:** ✅ (optional)
|
||||
- **Block Common Exploits:** ✅
|
||||
- **Websockets Support:** ✅ (für Chat/Activity)
|
||||
|
||||
3. **SSL Tab:**
|
||||
- **SSL Certificate:** Request a new SSL Certificate
|
||||
- **Force SSL:** ✅
|
||||
- **HTTP/2 Support:** ✅
|
||||
- **HSTS Enabled:** ✅
|
||||
|
||||
4. **Advanced Tab:**
|
||||
```
|
||||
# Custom Nginx Configuration
|
||||
# Fix for 421 Misdirected Request
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header X-Forwarded-Port $server_port;
|
||||
|
||||
# Fix HTTP/2 connection reuse issues
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Connection "";
|
||||
|
||||
# Timeouts
|
||||
proxy_connect_timeout 60s;
|
||||
proxy_send_timeout 60s;
|
||||
proxy_read_timeout 60s;
|
||||
```
|
||||
|
||||
### Staging (dev.dk0.dev)
|
||||
|
||||
1. **Gehe zu Nginx Proxy Manager** → Hosts → Proxy Hosts → Add Proxy Host
|
||||
|
||||
2. **Details Tab:**
|
||||
- **Domain Names:** `dev.dk0.dev`
|
||||
- **Scheme:** `http`
|
||||
- **Forward Hostname/IP:** `portfolio-app-staging` (Container-Name)
|
||||
- **Forward Port:** `3000` (interner Port im Container)
|
||||
- **Cache Assets:** ❌ (für Dev besser deaktiviert)
|
||||
- **Block Common Exploits:** ✅
|
||||
- **Websockets Support:** ✅
|
||||
|
||||
3. **SSL Tab:**
|
||||
- **SSL Certificate:** Request a new SSL Certificate
|
||||
- **Force SSL:** ✅
|
||||
- **HTTP/2 Support:** ✅
|
||||
- **HSTS Enabled:** ✅
|
||||
|
||||
4. **Advanced Tab:**
|
||||
```
|
||||
# Custom Nginx Configuration
|
||||
# Fix for 421 Misdirected Request
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header X-Forwarded-Port $server_port;
|
||||
|
||||
# Fix HTTP/2 connection reuse issues
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Connection "";
|
||||
|
||||
# Timeouts
|
||||
proxy_connect_timeout 60s;
|
||||
proxy_send_timeout 60s;
|
||||
proxy_read_timeout 60s;
|
||||
```
|
||||
|
||||
## 🔍 421 Misdirected Request - Lösung
|
||||
|
||||
Der **421 Misdirected Request** Fehler tritt auf, wenn:
|
||||
|
||||
1. **HTTP/2 Connection Reuse:** Nginx Proxy Manager versucht, eine HTTP/2-Verbindung wiederzuverwenden, aber der Host-Header stimmt nicht überein
|
||||
2. **Host-Header nicht richtig weitergegeben:** Der Container erhält den falschen Host-Header
|
||||
|
||||
### Lösung 1: Advanced Tab Konfiguration (Wichtig!)
|
||||
|
||||
Füge diese Zeilen im **Advanced Tab** von Nginx Proxy Manager hinzu:
|
||||
|
||||
```nginx
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Connection "";
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
```
|
||||
|
||||
### Lösung 2: Container-Namen verwenden
|
||||
|
||||
Stelle sicher, dass du den **Container-Namen** (nicht IP) verwendest:
|
||||
- Production: `portfolio-app`
|
||||
- Staging: `portfolio-app-staging`
|
||||
|
||||
### Lösung 3: Netzwerk prüfen
|
||||
|
||||
Stelle sicher, dass beide Container im `proxy` Netzwerk sind:
|
||||
|
||||
```bash
|
||||
# Prüfen
|
||||
docker network inspect proxy
|
||||
|
||||
# Sollte enthalten:
|
||||
# - portfolio-app
|
||||
# - portfolio-app-staging
|
||||
```
|
||||
|
||||
## ✅ Checkliste
|
||||
|
||||
- [ ] Container sind im `proxy` Netzwerk
|
||||
- [ ] Nginx Proxy Manager nutzt Container-Namen (nicht IP)
|
||||
- [ ] Advanced Tab Konfiguration ist gesetzt
|
||||
- [ ] `proxy_http_version 1.1` ist gesetzt
|
||||
- [ ] `proxy_set_header Host $host` ist gesetzt
|
||||
- [ ] SSL-Zertifikat ist konfiguriert
|
||||
- [ ] Websockets Support ist aktiviert
|
||||
|
||||
## 🐛 Troubleshooting
|
||||
|
||||
### 421 Fehler weiterhin vorhanden?
|
||||
|
||||
1. **Prüfe Container-Namen:**
|
||||
```bash
|
||||
docker ps --format "table {{.Names}}\t{{.Status}}"
|
||||
```
|
||||
|
||||
2. **Prüfe Netzwerk:**
|
||||
```bash
|
||||
docker network inspect proxy | grep -A 5 portfolio
|
||||
```
|
||||
|
||||
3. **Prüfe Nginx Proxy Manager Logs:**
|
||||
- Gehe zu Nginx Proxy Manager → System Logs
|
||||
- Suche nach "421" oder "misdirected"
|
||||
|
||||
4. **Teste direkt:**
|
||||
```bash
|
||||
# Vom Host aus
|
||||
curl -H "Host: dk0.dev" http://portfolio-app:3000
|
||||
|
||||
# Sollte funktionieren
|
||||
```
|
||||
|
||||
5. **Deaktiviere HTTP/2 temporär:**
|
||||
- In Nginx Proxy Manager → SSL Tab
|
||||
- **HTTP/2 Support:** ❌
|
||||
- Teste ob es funktioniert
|
||||
|
||||
## 📝 Wichtige Hinweise
|
||||
|
||||
- **Container-Namen sind wichtig:** Nutze `portfolio-app` nicht `localhost` oder IP
|
||||
- **Port:** Immer Port `3000` (interner Container-Port), nicht `3000:3000`
|
||||
- **Netzwerk:** Beide Container müssen im `proxy` Netzwerk sein
|
||||
- **HTTP/2:** Kann Probleme verursachen, wenn Advanced Config fehlt
|
||||
|
||||
## 🔄 Nach Deployment
|
||||
|
||||
Nach jedem Deployment:
|
||||
1. Prüfe ob Container läuft: `docker ps | grep portfolio`
|
||||
2. Prüfe ob Container im proxy-Netzwerk ist
|
||||
3. Teste die URL im Browser
|
||||
4. Prüfe Nginx Proxy Manager Logs bei Problemen
|
||||
284
TESTING_GUIDE.md
284
TESTING_GUIDE.md
@@ -1,284 +0,0 @@
|
||||
# 🧪 Automated Testing Guide
|
||||
|
||||
This guide explains how to run automated tests for critical paths, hydration, emails, and more.
|
||||
|
||||
## 📋 Test Types
|
||||
|
||||
### 1. Unit Tests (Jest)
|
||||
Tests individual components and functions in isolation.
|
||||
|
||||
```bash
|
||||
npm run test # Run all unit tests
|
||||
npm run test:watch # Watch mode
|
||||
npm run test:coverage # With coverage report
|
||||
```
|
||||
|
||||
### 2. E2E Tests (Playwright)
|
||||
Tests complete user flows in a real browser.
|
||||
|
||||
```bash
|
||||
npm run test:e2e # Run all E2E tests
|
||||
npm run test:e2e:ui # Run with UI mode (visual)
|
||||
npm run test:e2e:headed # Run with visible browser
|
||||
npm run test:e2e:debug # Debug mode
|
||||
```
|
||||
|
||||
### 3. Critical Path Tests
|
||||
Tests the most important user flows.
|
||||
|
||||
```bash
|
||||
npm run test:critical # Run critical path tests only
|
||||
```
|
||||
|
||||
### 4. Hydration Tests
|
||||
Ensures React hydration works without errors.
|
||||
|
||||
```bash
|
||||
npm run test:hydration # Run hydration tests only
|
||||
```
|
||||
|
||||
### 5. Email Tests
|
||||
Tests email API endpoints.
|
||||
|
||||
```bash
|
||||
npm run test:email # Run email tests only
|
||||
```
|
||||
|
||||
### 6. Performance Tests
|
||||
Checks page load times and performance.
|
||||
|
||||
```bash
|
||||
npm run test:performance # Run performance tests
|
||||
```
|
||||
|
||||
### 7. Accessibility Tests
|
||||
Basic accessibility checks.
|
||||
|
||||
```bash
|
||||
npm run test:accessibility # Run accessibility tests
|
||||
```
|
||||
|
||||
## 🚀 Running All Tests
|
||||
|
||||
### Quick Test (Recommended)
|
||||
```bash
|
||||
npm run test:all
|
||||
```
|
||||
|
||||
This runs:
|
||||
- ✅ TypeScript check
|
||||
- ✅ ESLint
|
||||
- ✅ Build
|
||||
- ✅ Unit tests
|
||||
- ✅ Critical paths
|
||||
- ✅ Hydration tests
|
||||
- ✅ Email tests
|
||||
- ✅ Performance tests
|
||||
- ✅ Accessibility tests
|
||||
|
||||
### Individual Test Suites
|
||||
```bash
|
||||
# Unit tests only
|
||||
npm run test
|
||||
|
||||
# E2E tests only
|
||||
npm run test:e2e
|
||||
|
||||
# Both
|
||||
npm run test && npm run test:e2e
|
||||
```
|
||||
|
||||
## 📝 What Gets Tested
|
||||
|
||||
### Critical Paths
|
||||
- ✅ Home page loads correctly
|
||||
- ✅ Projects page displays projects
|
||||
- ✅ Individual project pages work
|
||||
- ✅ Admin dashboard is accessible
|
||||
- ✅ API health endpoint
|
||||
- ✅ API projects endpoint
|
||||
|
||||
### Hydration
|
||||
- ✅ No hydration errors in console
|
||||
- ✅ No duplicate React key warnings
|
||||
- ✅ Client-side navigation works
|
||||
- ✅ Server and client HTML match
|
||||
- ✅ Interactive elements work after hydration
|
||||
|
||||
### Email
|
||||
- ✅ Email API accepts requests
|
||||
- ✅ Required field validation
|
||||
- ✅ Email format validation
|
||||
- ✅ Rate limiting (if implemented)
|
||||
- ✅ Email respond endpoint
|
||||
|
||||
### Performance
|
||||
- ✅ Page load times (< 5s)
|
||||
- ✅ No large layout shifts
|
||||
- ✅ Images are optimized
|
||||
- ✅ API response times (< 1s)
|
||||
|
||||
### Accessibility
|
||||
- ✅ Proper heading structure
|
||||
- ✅ Images have alt text
|
||||
- ✅ Links have descriptive text
|
||||
- ✅ Forms have labels
|
||||
|
||||
## 🎯 Pre-Push Testing
|
||||
|
||||
Before pushing to main, run:
|
||||
|
||||
```bash
|
||||
# Full test suite
|
||||
npm run test:all
|
||||
|
||||
# Or manually:
|
||||
npm run build
|
||||
npm run lint
|
||||
npx tsc --noEmit
|
||||
npm run test
|
||||
npm run test:critical
|
||||
npm run test:hydration
|
||||
```
|
||||
|
||||
## 🔧 Configuration
|
||||
|
||||
### Playwright Config
|
||||
Located in `playwright.config.ts`
|
||||
|
||||
- **Base URL**: `http://localhost:3000` (or set `PLAYWRIGHT_TEST_BASE_URL`)
|
||||
- **Browsers**: Chromium, Firefox, WebKit, Mobile Chrome, Mobile Safari
|
||||
- **Retries**: 2 retries in CI, 0 locally
|
||||
- **Screenshots**: On failure
|
||||
- **Videos**: On failure
|
||||
|
||||
### Jest Config
|
||||
Located in `jest.config.ts`
|
||||
|
||||
- **Environment**: jsdom
|
||||
- **Coverage**: v8 provider
|
||||
- **Setup**: `jest.setup.ts`
|
||||
|
||||
## 🐛 Debugging Tests
|
||||
|
||||
### Playwright Debug Mode
|
||||
```bash
|
||||
npm run test:e2e:debug
|
||||
```
|
||||
|
||||
This opens Playwright Inspector where you can:
|
||||
- Step through tests
|
||||
- Inspect elements
|
||||
- View console logs
|
||||
- See network requests
|
||||
|
||||
### UI Mode (Visual)
|
||||
```bash
|
||||
npm run test:e2e:ui
|
||||
```
|
||||
|
||||
Shows a visual interface to:
|
||||
- See all tests
|
||||
- Run specific tests
|
||||
- Watch tests execute
|
||||
- View results
|
||||
|
||||
### Headed Mode
|
||||
```bash
|
||||
npm run test:e2e:headed
|
||||
```
|
||||
|
||||
Runs tests with visible browser (useful for debugging).
|
||||
|
||||
## 📊 Test Reports
|
||||
|
||||
### Playwright HTML Report
|
||||
After running E2E tests:
|
||||
```bash
|
||||
npx playwright show-report
|
||||
```
|
||||
|
||||
Shows:
|
||||
- Test results
|
||||
- Screenshots on failure
|
||||
- Videos on failure
|
||||
- Timeline of test execution
|
||||
|
||||
### Jest Coverage Report
|
||||
```bash
|
||||
npm run test:coverage
|
||||
```
|
||||
|
||||
Generates coverage report in `coverage/` directory.
|
||||
|
||||
## 🚨 Common Issues
|
||||
|
||||
### Tests Fail Locally But Pass in CI
|
||||
- Check environment variables
|
||||
- Ensure database is set up
|
||||
- Check for port conflicts
|
||||
|
||||
### Hydration Errors
|
||||
- Check for server/client mismatches
|
||||
- Ensure no conditional rendering based on `window`
|
||||
- Check for date/time differences
|
||||
|
||||
### Email Tests Fail
|
||||
- Email service might not be configured
|
||||
- Check environment variables
|
||||
- Tests are designed to handle missing email service
|
||||
|
||||
### Performance Tests Fail
|
||||
- Network might be slow
|
||||
- Adjust thresholds in test file
|
||||
- Check for heavy resources loading
|
||||
|
||||
## 📝 Writing New Tests
|
||||
|
||||
### E2E Test Example
|
||||
```typescript
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test('My new feature works', async ({ page }) => {
|
||||
await page.goto('/my-page');
|
||||
await expect(page.locator('h1')).toContainText('Expected Text');
|
||||
});
|
||||
```
|
||||
|
||||
### Unit Test Example
|
||||
```typescript
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import MyComponent from './MyComponent';
|
||||
|
||||
test('renders correctly', () => {
|
||||
render(<MyComponent />);
|
||||
expect(screen.getByText('Hello')).toBeInTheDocument();
|
||||
});
|
||||
```
|
||||
|
||||
## 🎯 CI/CD Integration
|
||||
|
||||
### GitHub Actions Example
|
||||
```yaml
|
||||
- name: Run tests
|
||||
run: |
|
||||
npm install
|
||||
npm run test:all
|
||||
```
|
||||
|
||||
### Pre-Push Hook
|
||||
Add to `.git/hooks/pre-push`:
|
||||
```bash
|
||||
#!/bin/bash
|
||||
npm run test:all
|
||||
```
|
||||
|
||||
## 📚 Resources
|
||||
|
||||
- [Playwright Docs](https://playwright.dev)
|
||||
- [Jest Docs](https://jestjs.io)
|
||||
- [Testing Library](https://testing-library.com)
|
||||
|
||||
---
|
||||
|
||||
**Remember**: Tests should be fast, reliable, and easy to understand! 🚀
|
||||
@@ -1,69 +0,0 @@
|
||||
# Testing & Deployment (Gitea → Docker → Nginx Proxy Manager)
|
||||
|
||||
## Ziel
|
||||
|
||||
- **Production**: Branch `production` → Container `portfolio-app` → `dk0.dev` (Port `3000`)
|
||||
- **Testing**: Branch `testing` → Container `portfolio-app-testing` → `testing.dk0.dev` (Port `3002`)
|
||||
|
||||
Beide Stacks laufen parallel und sind komplett getrennt (eigene Postgres/Redis/Volumes).
|
||||
|
||||
## DNS / Nginx Proxy Manager
|
||||
|
||||
### DNS
|
||||
- Setze `A` (oder `CNAME`) Records:
|
||||
- `dk0.dev` → dein Server
|
||||
- `testing.dk0.dev` → dein Server
|
||||
|
||||
### Nginx Proxy Manager
|
||||
Lege zwei Proxy Hosts an:
|
||||
|
||||
- **`dk0.dev`**
|
||||
- Forward Hostname/IP: `127.0.0.1` (oder Server-IP)
|
||||
- Forward Port: `3000`
|
||||
|
||||
- **`testing.dk0.dev`**
|
||||
- Forward Hostname/IP: `127.0.0.1` (oder Server-IP)
|
||||
- Forward Port: `3002`
|
||||
|
||||
Dann SSL Zertifikate (Let’s Encrypt) aktivieren.
|
||||
|
||||
## Gitea Workflows
|
||||
|
||||
- `production` push → `.gitea/workflows/production-deploy.yml`
|
||||
- `testing` push → `.gitea/workflows/dev-deploy.yml` (umbenannt im Namen, Inhalt ist Testing)
|
||||
|
||||
### Benötigte Variables (Gitea)
|
||||
- `NEXT_PUBLIC_BASE_URL_PRODUCTION` = `https://dk0.dev`
|
||||
- `NEXT_PUBLIC_BASE_URL_TESTING` = `https://testing.dk0.dev`
|
||||
- optional: `MY_EMAIL`, `MY_INFO_EMAIL`, `LOG_LEVEL`, `N8N_WEBHOOK_URL`, `N8N_API_KEY`
|
||||
|
||||
### Benötigte Secrets (Gitea)
|
||||
- `MY_PASSWORD`
|
||||
- `MY_INFO_PASSWORD`
|
||||
- `ADMIN_BASIC_AUTH` (z.B. `admin:<starkes_passwort>`)
|
||||
- `ADMIN_SESSION_SECRET` (mind. 32 Zeichen, zufällig; für Session-Login im Admin)
|
||||
- optional: `N8N_SECRET_TOKEN`
|
||||
|
||||
## Docker Compose Files
|
||||
|
||||
- Production: `docker-compose.production.yml` (Port 3000)
|
||||
- Testing: `docker-compose.testing.yml` (Port 3002)
|
||||
|
||||
Wenn du “dev” nicht mehr brauchst, kannst du den Branch einfach nicht mehr benutzen.
|
||||
|
||||
## Prisma Migrations (Auto-Deploy)
|
||||
|
||||
Der App-Container führt beim Start automatisch aus:
|
||||
- `prisma migrate deploy`
|
||||
|
||||
### Wichtig: bestehende Datenbank (Baseline)
|
||||
Wenn deine DB bereits existiert (vor Einführung von Prisma Migrations), dann würde die initiale Migration sonst mit “table already exists” scheitern.
|
||||
|
||||
**Einmalig beim ersten Deploy**:
|
||||
- Setze `PRISMA_AUTO_BASELINE=true` (z.B. als Compose env oder Gitea Variable/Secret)
|
||||
- Deploy ausführen
|
||||
- Danach wieder auf `false` setzen
|
||||
|
||||
Alternative (manuell/sauber):
|
||||
- Baseline per `prisma migrate resolve --applied <init_migration_name>` ausführen (z.B. lokal gegen die Prod-DB)
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user