diff --git a/.gitea/workflows/ci-cd-dev-staging.yml b/.gitea/workflows/ci-cd-dev-staging.yml new file mode 100644 index 0000000..1a0004e --- /dev/null +++ b/.gitea/workflows/ci-cd-dev-staging.yml @@ -0,0 +1,209 @@ +name: CI/CD Pipeline (Dev/Staging) + +on: + push: + branches: [dev, main] + +env: + NODE_VERSION: '20' + DOCKER_IMAGE: portfolio-app + CONTAINER_NAME: portfolio-app-staging + +jobs: + staging: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Run linting + run: npm run lint + + - name: Run tests + run: npm run test:production + + - name: Build application + run: npm run build + + - name: Run security scan + run: | + echo "πŸ” Running npm audit..." + npm audit --audit-level=high || echo "⚠️ Some vulnerabilities found, but continuing..." + + - name: Verify Gitea Variables and Secrets + run: | + echo "πŸ” Verifying Gitea Variables and Secrets..." + + # Check Variables + if [ -z "${{ vars.NEXT_PUBLIC_BASE_URL }}" ]; then + echo "❌ NEXT_PUBLIC_BASE_URL variable is missing!" + echo "Please set this variable in Gitea repository settings" + exit 1 + fi + if [ -z "${{ vars.MY_EMAIL }}" ]; then + echo "❌ MY_EMAIL variable is missing!" + echo "Please set this variable in Gitea repository settings" + exit 1 + fi + if [ -z "${{ vars.MY_INFO_EMAIL }}" ]; then + echo "❌ MY_INFO_EMAIL variable is missing!" + echo "Please set this variable in Gitea repository settings" + exit 1 + fi + + # Check Secrets + if [ -z "${{ secrets.MY_PASSWORD }}" ]; then + echo "❌ MY_PASSWORD secret is missing!" + echo "Please set this secret in Gitea repository settings" + exit 1 + fi + if [ -z "${{ secrets.MY_INFO_PASSWORD }}" ]; then + echo "❌ MY_INFO_PASSWORD secret is missing!" + echo "Please set this secret in Gitea repository settings" + exit 1 + fi + if [ -z "${{ secrets.ADMIN_BASIC_AUTH }}" ]; then + echo "❌ ADMIN_BASIC_AUTH secret is missing!" + echo "Please set this secret in Gitea repository settings" + exit 1 + fi + + echo "βœ… All required Gitea variables and secrets are present" + echo "πŸ“ Variables found:" + echo " - NEXT_PUBLIC_BASE_URL: ${{ vars.NEXT_PUBLIC_BASE_URL }}" + echo " - MY_EMAIL: ${{ vars.MY_EMAIL }}" + echo " - MY_INFO_EMAIL: ${{ vars.MY_INFO_EMAIL }}" + echo " - NODE_ENV: staging" + echo " - LOG_LEVEL: ${{ vars.LOG_LEVEL }}" + + - name: Build Docker image + run: | + echo "πŸ—οΈ Building Docker image..." + docker build -t ${{ env.DOCKER_IMAGE }}:staging . + docker tag ${{ env.DOCKER_IMAGE }}:staging ${{ env.DOCKER_IMAGE }}:staging-$(date +%Y%m%d-%H%M%S) + echo "βœ… Docker image built successfully" + + - name: Deploy Staging using Gitea Variables and Secrets + run: | + echo "πŸš€ Deploying Staging using Gitea Variables and Secrets..." + + echo "πŸ“ Using Gitea Variables and Secrets:" + echo " - NODE_ENV: staging" + echo " - LOG_LEVEL: ${LOG_LEVEL}" + echo " - NEXT_PUBLIC_BASE_URL: ${NEXT_PUBLIC_BASE_URL}" + echo " - MY_EMAIL: ${MY_EMAIL}" + echo " - MY_INFO_EMAIL: ${MY_INFO_EMAIL}" + echo " - MY_PASSWORD: [SET FROM GITEA SECRET]" + echo " - MY_INFO_PASSWORD: [SET FROM GITEA SECRET]" + echo " - ADMIN_BASIC_AUTH: [SET FROM GITEA SECRET]" + echo " - N8N_WEBHOOK_URL: ${N8N_WEBHOOK_URL}" + + # Stop old staging containers + echo "πŸ›‘ Stopping old staging containers..." + docker compose -f docker-compose.staging.yml down || true + + # Clean up orphaned containers + echo "🧹 Cleaning up orphaned containers..." + docker compose -f docker-compose.staging.yml down --remove-orphans || true + + # Start new staging containers + echo "πŸš€ Starting new staging containers..." + docker compose -f docker-compose.staging.yml up -d + + # Wait a moment for containers to start + echo "⏳ Waiting for containers to start..." + sleep 10 + + # Check container logs for debugging + echo "πŸ“‹ Container logs (first 20 lines):" + docker compose -f docker-compose.staging.yml logs --tail=20 + + echo "βœ… Staging deployment completed!" + env: + NODE_ENV: staging + LOG_LEVEL: ${{ vars.LOG_LEVEL }} + NEXT_PUBLIC_BASE_URL: ${{ vars.NEXT_PUBLIC_BASE_URL }} + NEXT_PUBLIC_UMAMI_URL: ${{ vars.NEXT_PUBLIC_UMAMI_URL }} + NEXT_PUBLIC_UMAMI_WEBSITE_ID: ${{ vars.NEXT_PUBLIC_UMAMI_WEBSITE_ID }} + MY_EMAIL: ${{ vars.MY_EMAIL }} + MY_INFO_EMAIL: ${{ vars.MY_INFO_EMAIL }} + MY_PASSWORD: ${{ secrets.MY_PASSWORD }} + MY_INFO_PASSWORD: ${{ secrets.MY_INFO_PASSWORD }} + ADMIN_BASIC_AUTH: ${{ secrets.ADMIN_BASIC_AUTH }} + N8N_WEBHOOK_URL: ${{ vars.N8N_WEBHOOK_URL }} + N8N_API_KEY: ${{ secrets.N8N_API_KEY }} + + - name: Wait for containers to be ready + run: | + echo "⏳ Waiting for containers to be ready..." + sleep 45 + + # Check if all containers are running + echo "πŸ“Š Checking container status..." + docker compose -f docker-compose.staging.yml ps + + # Wait for application container to be healthy + echo "πŸ₯ Waiting for application container to be healthy..." + for i in {1..60}; do + if docker exec portfolio-app-staging curl -f http://localhost:3000/api/health > /dev/null 2>&1; then + echo "βœ… Application container is healthy!" + break + fi + echo "⏳ Waiting for application container... ($i/60)" + sleep 5 + done + + # Additional wait for main page to be accessible + echo "🌐 Waiting for main page to be accessible..." + for i in {1..30}; do + if curl -f http://localhost:3001/ > /dev/null 2>&1; then + echo "βœ… Main page is accessible!" + break + fi + echo "⏳ Waiting for main page... ($i/30)" + sleep 3 + done + + - name: Health check + run: | + echo "πŸ” Running comprehensive health checks..." + + # Check container status + echo "πŸ“Š Container status:" + docker compose -f docker-compose.staging.yml ps + + # Check application container + echo "πŸ₯ Checking application container..." + if docker exec portfolio-app-staging curl -f http://localhost:3000/api/health; then + echo "βœ… Application health check passed!" + else + echo "❌ Application health check failed!" + docker logs portfolio-app-staging --tail=50 + exit 1 + fi + + # Check main page + if curl -f http://localhost:3001/ > /dev/null; then + echo "βœ… Main page is accessible!" + else + echo "❌ Main page is not accessible!" + exit 1 + fi + + echo "βœ… All health checks passed! Staging deployment successful!" + + - name: Cleanup old images + run: | + echo "🧹 Cleaning up old images..." + docker image prune -f + docker system prune -f + echo "βœ… Cleanup completed" diff --git a/DEV_TESTING.md b/DEV_TESTING.md new file mode 100644 index 0000000..03d3bf6 --- /dev/null +++ b/DEV_TESTING.md @@ -0,0 +1,236 @@ +# πŸ§ͺ Dev Branch Testing Guide + +## Übersicht + +Dieses Dokument erklΓ€rt, wie du dein Portfolio-Projekt auf dem `dev` Branch testen kannst, bevor du es in Production deployst. + +## Voraussetzungen + +1. βœ… n8n lΓ€uft bereits auf `n8n.dk0.dev` +2. βœ… Gitea Repository ist eingerichtet +3. βœ… Docker und Docker Compose sind installiert + +## Setup fΓΌr lokales Testen mit n8n + +### 1. Environment Variables konfigurieren + +Erstelle eine `.env.local` Datei (oder aktualisiere deine bestehende `.env`): + +```bash +# n8n Integration +N8N_WEBHOOK_URL=https://n8n.dk0.dev +N8N_API_KEY=dein-n8n-api-key +N8N_SECRET_TOKEN=dein-n8n-secret-token + +# Application +NODE_ENV=development +NEXT_PUBLIC_BASE_URL=http://localhost:3000 + +# Database (wird automatisch von docker-compose.dev.minimal.yml gesetzt) +# DATABASE_URL=postgresql://portfolio_user:portfolio_dev_pass@localhost:5432/portfolio_dev?schema=public + +# Redis (wird automatisch von docker-compose.dev.minimal.yml gesetzt) +# REDIS_URL=redis://localhost:6379 + +# Email Configuration +MY_EMAIL=contact@dk0.dev +MY_INFO_EMAIL=info@dk0.dev +MY_PASSWORD=dein-email-passwort +MY_INFO_PASSWORD=dein-info-email-passwort + +# Analytics +NEXT_PUBLIC_UMAMI_URL=https://analytics.dk0.dev +NEXT_PUBLIC_UMAMI_WEBSITE_ID=b3665829-927a-4ada-b9bb-fcf24171061e + +# Security +ADMIN_BASIC_AUTH=admin:dein-sicheres-passwort +LOG_LEVEL=debug +``` + +### 2. Lokal testen + +```bash +# 1. Starte Datenbank und Redis +npm run dev:minimal + +# 2. In einem neuen Terminal: Starte die Next.js App +npm run dev + +# 3. Γ–ffne http://localhost:3000 +``` + +### 3. n8n Webhook testen + +Teste die Verbindung zu deinem n8n Server: + +```bash +# Teste den Status Endpoint +curl https://n8n.dk0.dev/webhook/denshooter-71242/status + +# Teste den Chat Endpoint (wenn konfiguriert) +curl -X POST https://n8n.dk0.dev/webhook/chat \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer DEIN_N8N_SECRET_TOKEN" \ + -d '{"message": "Hallo", "history": []}' +``` + +## Staging Deployment auf dem Server + +### 1. Gitea Variables und Secrets konfigurieren + +Gehe zu deinem Gitea Repository β†’ Settings β†’ Secrets/Variables und fΓΌge hinzu: + +**Variables:** +- `NEXT_PUBLIC_BASE_URL` = `https://staging.dk0.dev` (oder deine Staging URL) +- `MY_EMAIL` = `contact@dk0.dev` +- `MY_INFO_EMAIL` = `info@dk0.dev` +- `NEXT_PUBLIC_UMAMI_URL` = `https://analytics.dk0.dev` +- `NEXT_PUBLIC_UMAMI_WEBSITE_ID` = `b3665829-927a-4ada-b9bb-fcf24171061e` +- `N8N_WEBHOOK_URL` = `https://n8n.dk0.dev` +- `LOG_LEVEL` = `debug` + +**Secrets:** +- `MY_PASSWORD` = Dein Email Passwort +- `MY_INFO_PASSWORD` = Dein Info Email Passwort +- `ADMIN_BASIC_AUTH` = `admin:dein-sicheres-passwort` +- `N8N_API_KEY` = Dein n8n API Key (optional) +- `N8N_SECRET_TOKEN` = Dein n8n Secret Token (optional) + +### 2. Push zum dev Branch + +```bash +# Stelle sicher, dass du auf dem dev Branch bist +git checkout dev + +# Committe deine Γ„nderungen +git add . +git commit -m "Test: Dev deployment" + +# Push zum dev Branch (triggert automatisch Staging Deployment) +git push origin dev +``` + +### 3. Deployment ΓΌberwachen + +Nach dem Push: +1. Gehe zu deinem Gitea Repository β†’ Actions +2. Überwache den Workflow `CI/CD Pipeline (Dev/Staging)` +3. Der Workflow wird: + - Tests ausfΓΌhren + - Docker Image bauen + - Staging Container auf Port 3001 deployen + +### 4. Staging testen + +```bash +# Auf deinem Server: PrΓΌfe Container Status +docker ps | grep staging + +# PrΓΌfe Health Endpoint +curl http://localhost:3001/api/health + +# PrΓΌfe n8n Status Endpoint +curl http://localhost:3001/api/n8n/status + +# Logs ansehen +docker logs portfolio-app-staging -f +``` + +### 5. Staging URL konfigurieren + +Falls du eine Subdomain fΓΌr Staging hast (z.B. `staging.dk0.dev`): +- Konfiguriere deinen Reverse Proxy (Nginx/Traefik) um auf Port 3001 zu zeigen +- Oder verwende direkt `http://dein-server-ip:3001` + +## Troubleshooting + +### Dev Container wird nicht erstellt + +1. **PrΓΌfe Gitea Workflow:** + - Gehe zu Repository β†’ Actions + - PrΓΌfe ob der Workflow `ci-cd-dev-staging.yml` existiert + - PrΓΌfe ob der Workflow auf `dev` Branch Push reagiert + +2. **PrΓΌfe Gitea Variables:** + - Stelle sicher, dass alle erforderlichen Variables und Secrets gesetzt sind + - PrΓΌfe die Workflow Logs fΓΌr fehlende Variablen + +3. **PrΓΌfe Docker:** + ```bash + # Auf deinem Server + docker ps -a + docker images | grep portfolio-app + ``` + +### n8n Verbindungsfehler + +1. **PrΓΌfe n8n URL:** + ```bash + # Teste ob n8n erreichbar ist + curl https://n8n.dk0.dev/webhook/denshooter-71242/status + ``` + +2. **PrΓΌfe Environment Variables:** + ```bash + # Im Container + docker exec portfolio-app-staging env | grep N8N + ``` + +3. **PrΓΌfe n8n Webhook Konfiguration:** + - Stelle sicher, dass der Webhook in n8n aktiviert ist + - PrΓΌfe ob der Webhook-Pfad korrekt ist (`/webhook/denshooter-71242/status`) + +### Datenbank Fehler + +```bash +# PrΓΌfe ob die Datenbank lΓ€uft +docker ps | grep postgres-staging + +# PrΓΌfe Datenbank Logs +docker logs portfolio-postgres-staging + +# PrΓΌfe Verbindung +docker exec portfolio-postgres-staging pg_isready -U portfolio_user -d portfolio_staging_db +``` + +## Workflow Übersicht + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Push to dev β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β–Ό +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Run Tests β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β–Ό +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Build Docker β”‚ +β”‚ Image (staging) β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β–Ό +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Deploy Staging β”‚ +β”‚ (Port 3001) β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β–Ό +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Health Check β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +## NΓ€chste Schritte + +1. βœ… Teste lokal mit `npm run dev` +2. βœ… Konfiguriere Gitea Variables und Secrets +3. βœ… Push zum `dev` Branch +4. βœ… Teste Staging auf Port 3001 +5. βœ… Wenn alles funktioniert: Merge zu `production` Branch + +--- + +**Tipp:** Verwende `LOG_LEVEL=debug` in Staging um mehr Informationen zu sehen! diff --git a/docker-compose.staging.yml b/docker-compose.staging.yml index c3a51ad..a5fbee7 100644 --- a/docker-compose.staging.yml +++ b/docker-compose.staging.yml @@ -22,6 +22,9 @@ services: - MY_INFO_PASSWORD=${MY_INFO_PASSWORD} - ADMIN_BASIC_AUTH=${ADMIN_BASIC_AUTH:-admin:staging_password} - LOG_LEVEL=debug + - N8N_WEBHOOK_URL=${N8N_WEBHOOK_URL:-https://n8n.dk0.dev} + - N8N_API_KEY=${N8N_API_KEY} + - N8N_SECRET_TOKEN=${N8N_SECRET_TOKEN} volumes: - portfolio_staging_data:/app/.next/cache networks: