Services: Admin-Lehrer, Backend-Lehrer, Studio v2, Website, Klausur-Service, School-Service, Voice-Service, Geo-Service, BreakPilot Drive, Agent-Core Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
666 lines
29 KiB
TypeScript
666 lines
29 KiB
TypeScript
'use client'
|
|
|
|
import { useState, useEffect } from 'react'
|
|
import {
|
|
GitBranch,
|
|
Terminal,
|
|
Server,
|
|
Database,
|
|
CheckCircle2,
|
|
ArrowRight,
|
|
Laptop,
|
|
HardDrive,
|
|
RefreshCw,
|
|
Clock,
|
|
Shield,
|
|
Users,
|
|
FileCode,
|
|
Play,
|
|
Eye,
|
|
Download,
|
|
AlertTriangle,
|
|
Info,
|
|
Container
|
|
} from 'lucide-react'
|
|
|
|
interface WorkflowStep {
|
|
id: number
|
|
title: string
|
|
description: string
|
|
command?: string
|
|
icon: React.ReactNode
|
|
location: 'macbook' | 'macmini'
|
|
}
|
|
|
|
interface BackupInfo {
|
|
lastRun: string | null
|
|
nextRun: string
|
|
status: 'ok' | 'warning' | 'error'
|
|
}
|
|
|
|
export default function WorkflowPage() {
|
|
const [activeStep, setActiveStep] = useState<number>(1)
|
|
const [backupInfo, setBackupInfo] = useState<BackupInfo>({
|
|
lastRun: null,
|
|
nextRun: '02:00 Uhr',
|
|
status: 'ok'
|
|
})
|
|
|
|
const workflowSteps: WorkflowStep[] = [
|
|
{
|
|
id: 1,
|
|
title: 'Code bearbeiten',
|
|
description: 'Arbeite mit Claude Code im Terminal. Beschreibe was du brauchst und Claude schreibt den Code.',
|
|
command: 'claude',
|
|
icon: <Terminal className="h-6 w-6" />,
|
|
location: 'macbook'
|
|
},
|
|
{
|
|
id: 2,
|
|
title: 'Änderungen stagen',
|
|
description: 'Füge die geänderten Dateien zum nächsten Commit hinzu.',
|
|
command: 'git add <dateien>',
|
|
icon: <FileCode className="h-6 w-6" />,
|
|
location: 'macbook'
|
|
},
|
|
{
|
|
id: 3,
|
|
title: 'Commit erstellen',
|
|
description: 'Erstelle einen Commit mit einer aussagekräftigen Nachricht.',
|
|
command: 'git commit -m "feat: neue Funktion"',
|
|
icon: <GitBranch className="h-6 w-6" />,
|
|
location: 'macbook'
|
|
},
|
|
{
|
|
id: 4,
|
|
title: 'Push zum Server',
|
|
description: 'Sende die Änderungen an den Mac Mini. Dies startet automatisch die CI/CD Pipeline.',
|
|
command: 'git push origin main',
|
|
icon: <ArrowRight className="h-6 w-6" />,
|
|
location: 'macbook'
|
|
},
|
|
{
|
|
id: 5,
|
|
title: 'CI/CD Pipeline',
|
|
description: 'Woodpecker führt automatisch Tests aus und baut die Container.',
|
|
command: '(automatisch)',
|
|
icon: <RefreshCw className="h-6 w-6" />,
|
|
location: 'macmini'
|
|
},
|
|
{
|
|
id: 6,
|
|
title: 'Integration Tests',
|
|
description: 'Docker Compose Test-Umgebung mit Backend, DB und Consent-Service fuer vollstaendige E2E-Tests.',
|
|
command: 'docker compose -f docker-compose.test.yml up -d',
|
|
icon: <Container className="h-6 w-6" />,
|
|
location: 'macmini'
|
|
},
|
|
{
|
|
id: 7,
|
|
title: 'Frontend testen',
|
|
description: 'Teste die Änderungen im Browser auf dem Mac Mini.',
|
|
command: 'http://macmini:3000',
|
|
icon: <Eye className="h-6 w-6" />,
|
|
location: 'macbook'
|
|
}
|
|
]
|
|
|
|
const services = [
|
|
{ name: 'Website', url: 'http://macmini:3000', port: 3000, status: 'running' },
|
|
{ name: 'Admin v2', url: 'http://macmini:3002', port: 3002, status: 'running' },
|
|
{ name: 'Studio v2', url: 'http://macmini:3001', port: 3001, status: 'running' },
|
|
{ name: 'Backend', url: 'http://macmini:8000', port: 8000, status: 'running' },
|
|
{ name: 'Gitea', url: 'http://macmini:3003', port: 3003, status: 'running' },
|
|
{ name: 'Klausur-Service', url: 'http://macmini:8086', port: 8086, status: 'running' },
|
|
]
|
|
|
|
const commitTypes = [
|
|
{ type: 'feat:', description: 'Neue Funktion', example: 'feat: add user login' },
|
|
{ type: 'fix:', description: 'Bugfix', example: 'fix: resolve login timeout' },
|
|
{ type: 'docs:', description: 'Dokumentation', example: 'docs: update API docs' },
|
|
{ type: 'style:', description: 'Formatierung', example: 'style: fix indentation' },
|
|
{ type: 'refactor:', description: 'Code-Umbau', example: 'refactor: extract helper' },
|
|
{ type: 'test:', description: 'Tests', example: 'test: add unit tests' },
|
|
{ type: 'chore:', description: 'Wartung', example: 'chore: update deps' },
|
|
]
|
|
|
|
return (
|
|
<div className="space-y-8">
|
|
{/* Header */}
|
|
<div className="bg-gradient-to-r from-indigo-600 to-purple-600 rounded-2xl p-8 text-white">
|
|
<h1 className="text-3xl font-bold mb-2">Entwicklungs-Workflow</h1>
|
|
<p className="text-indigo-100">
|
|
Wie wir bei BreakPilot entwickeln - von der Idee bis zum Deployment
|
|
</p>
|
|
</div>
|
|
|
|
{/* Architecture Overview */}
|
|
<div className="bg-white rounded-xl border border-slate-200 p-6">
|
|
<h2 className="text-xl font-semibold text-slate-900 mb-4 flex items-center gap-2">
|
|
<Server className="h-5 w-5 text-indigo-600" />
|
|
Systemarchitektur
|
|
</h2>
|
|
|
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
{/* MacBook */}
|
|
<div className="bg-slate-50 rounded-xl p-5 border-2 border-slate-200">
|
|
<div className="flex items-center gap-3 mb-4">
|
|
<div className="p-2 bg-blue-100 rounded-lg">
|
|
<Laptop className="h-6 w-6 text-blue-600" />
|
|
</div>
|
|
<div>
|
|
<h3 className="font-semibold text-slate-900">MacBook (Entwicklung)</h3>
|
|
<p className="text-sm text-slate-500">Dein Arbeitsplatz</p>
|
|
</div>
|
|
</div>
|
|
<ul className="space-y-2 text-sm">
|
|
<li className="flex items-center gap-2">
|
|
<CheckCircle2 className="h-4 w-4 text-green-500" />
|
|
<span>Terminal + Claude Code</span>
|
|
</li>
|
|
<li className="flex items-center gap-2">
|
|
<CheckCircle2 className="h-4 w-4 text-green-500" />
|
|
<span>Lokales Git Repository</span>
|
|
</li>
|
|
<li className="flex items-center gap-2">
|
|
<CheckCircle2 className="h-4 w-4 text-green-500" />
|
|
<span>Browser für Frontend-Tests</span>
|
|
</li>
|
|
<li className="flex items-center gap-2">
|
|
<AlertTriangle className="h-4 w-4 text-amber-500" />
|
|
<span>Backup manuell (MacBook nachts aus)</span>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
{/* Mac Mini */}
|
|
<div className="bg-slate-50 rounded-xl p-5 border-2 border-indigo-200">
|
|
<div className="flex items-center gap-3 mb-4">
|
|
<div className="p-2 bg-indigo-100 rounded-lg">
|
|
<HardDrive className="h-6 w-6 text-indigo-600" />
|
|
</div>
|
|
<div>
|
|
<h3 className="font-semibold text-slate-900">Mac Mini (Server)</h3>
|
|
<p className="text-sm text-slate-500">192.168.178.100</p>
|
|
</div>
|
|
</div>
|
|
<ul className="space-y-2 text-sm">
|
|
<li className="flex items-center gap-2">
|
|
<CheckCircle2 className="h-4 w-4 text-green-500" />
|
|
<span>Gitea (Git Server)</span>
|
|
</li>
|
|
<li className="flex items-center gap-2">
|
|
<CheckCircle2 className="h-4 w-4 text-green-500" />
|
|
<span>Woodpecker (CI/CD)</span>
|
|
</li>
|
|
<li className="flex items-center gap-2">
|
|
<CheckCircle2 className="h-4 w-4 text-green-500" />
|
|
<span>Docker Container (alle Services)</span>
|
|
</li>
|
|
<li className="flex items-center gap-2">
|
|
<CheckCircle2 className="h-4 w-4 text-green-500" />
|
|
<span>PostgreSQL Datenbank</span>
|
|
</li>
|
|
<li className="flex items-center gap-2">
|
|
<CheckCircle2 className="h-4 w-4 text-green-500" />
|
|
<span>Automatisches Backup (02:00 Uhr lokal)</span>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Workflow Steps */}
|
|
<div className="bg-white rounded-xl border border-slate-200 p-6">
|
|
<h2 className="text-xl font-semibold text-slate-900 mb-6 flex items-center gap-2">
|
|
<Play className="h-5 w-5 text-indigo-600" />
|
|
Entwicklungs-Schritte
|
|
</h2>
|
|
|
|
<div className="space-y-4">
|
|
{workflowSteps.map((step, index) => (
|
|
<div
|
|
key={step.id}
|
|
className={`relative flex items-start gap-4 p-4 rounded-xl transition-all cursor-pointer ${
|
|
activeStep === step.id
|
|
? 'bg-indigo-50 border-2 border-indigo-300'
|
|
: 'bg-slate-50 border-2 border-transparent hover:border-slate-200'
|
|
}`}
|
|
onClick={() => setActiveStep(step.id)}
|
|
>
|
|
{/* Step Number */}
|
|
<div className={`flex-shrink-0 w-10 h-10 rounded-full flex items-center justify-center font-bold ${
|
|
activeStep === step.id
|
|
? 'bg-indigo-600 text-white'
|
|
: 'bg-slate-200 text-slate-600'
|
|
}`}>
|
|
{step.id}
|
|
</div>
|
|
|
|
{/* Content */}
|
|
<div className="flex-grow">
|
|
<div className="flex items-center gap-2 mb-1">
|
|
<h3 className="font-semibold text-slate-900">{step.title}</h3>
|
|
<span className={`text-xs px-2 py-0.5 rounded-full ${
|
|
step.location === 'macbook'
|
|
? 'bg-blue-100 text-blue-700'
|
|
: 'bg-purple-100 text-purple-700'
|
|
}`}>
|
|
{step.location === 'macbook' ? 'MacBook' : 'Mac Mini'}
|
|
</span>
|
|
</div>
|
|
<p className="text-sm text-slate-600 mb-2">{step.description}</p>
|
|
{step.command && (
|
|
<code className="text-xs bg-slate-800 text-green-400 px-3 py-1.5 rounded-lg font-mono">
|
|
{step.command}
|
|
</code>
|
|
)}
|
|
</div>
|
|
|
|
{/* Icon */}
|
|
<div className={`flex-shrink-0 p-2 rounded-lg ${
|
|
activeStep === step.id ? 'bg-indigo-100 text-indigo-600' : 'bg-slate-100 text-slate-400'
|
|
}`}>
|
|
{step.icon}
|
|
</div>
|
|
|
|
{/* Connector Line */}
|
|
{index < workflowSteps.length - 1 && (
|
|
<div className="absolute left-9 top-14 w-0.5 h-8 bg-slate-200" />
|
|
)}
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Services & URLs */}
|
|
<div className="bg-white rounded-xl border border-slate-200 p-6">
|
|
<h2 className="text-xl font-semibold text-slate-900 mb-4 flex items-center gap-2">
|
|
<Eye className="h-5 w-5 text-indigo-600" />
|
|
Services & URLs zum Testen
|
|
</h2>
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-3">
|
|
{services.map((service) => (
|
|
<a
|
|
key={service.name}
|
|
href={service.url}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="flex items-center justify-between p-4 bg-slate-50 rounded-lg hover:bg-slate-100 transition-colors border border-slate-200"
|
|
>
|
|
<div>
|
|
<h3 className="font-medium text-slate-900">{service.name}</h3>
|
|
<p className="text-sm text-slate-500">Port {service.port}</p>
|
|
</div>
|
|
<div className="flex items-center gap-2">
|
|
<span className="w-2 h-2 bg-green-500 rounded-full animate-pulse" />
|
|
<ArrowRight className="h-4 w-4 text-slate-400" />
|
|
</div>
|
|
</a>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Commit Convention */}
|
|
<div className="bg-white rounded-xl border border-slate-200 p-6">
|
|
<h2 className="text-xl font-semibold text-slate-900 mb-4 flex items-center gap-2">
|
|
<GitBranch className="h-5 w-5 text-indigo-600" />
|
|
Commit-Konventionen
|
|
</h2>
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-3">
|
|
{commitTypes.map((item) => (
|
|
<div key={item.type} className="bg-slate-50 rounded-lg p-3 border border-slate-200">
|
|
<code className="text-sm font-bold text-indigo-600">{item.type}</code>
|
|
<p className="text-sm text-slate-600 mt-1">{item.description}</p>
|
|
<p className="text-xs text-slate-400 mt-1 font-mono">{item.example}</p>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Backup Info */}
|
|
<div className="bg-white rounded-xl border border-slate-200 p-6">
|
|
<h2 className="text-xl font-semibold text-slate-900 mb-4 flex items-center gap-2">
|
|
<Shield className="h-5 w-5 text-indigo-600" />
|
|
Backup & Sicherheit
|
|
</h2>
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
|
{/* Mac Mini - Automatisches lokales Backup */}
|
|
<div className="bg-green-50 rounded-xl p-5 border border-green-200">
|
|
<div className="flex items-center gap-3 mb-3">
|
|
<Clock className="h-5 w-5 text-green-600" />
|
|
<h3 className="font-semibold text-green-900">Mac Mini (Auto)</h3>
|
|
</div>
|
|
<ul className="space-y-2 text-sm text-green-800">
|
|
<li>• Automatisch um 02:00 Uhr</li>
|
|
<li>• PostgreSQL-Dump lokal</li>
|
|
<li>• Git Repository gesichert</li>
|
|
<li>• 7 Tage Aufbewahrung</li>
|
|
</ul>
|
|
<div className="mt-4 p-3 bg-green-100 rounded-lg">
|
|
<code className="text-xs text-green-700 font-mono">
|
|
~/Projekte/backup-logs/
|
|
</code>
|
|
</div>
|
|
</div>
|
|
|
|
{/* MacBook - Manuelles Backup */}
|
|
<div className="bg-amber-50 rounded-xl p-5 border border-amber-200">
|
|
<div className="flex items-center gap-3 mb-3">
|
|
<AlertTriangle className="h-5 w-5 text-amber-600" />
|
|
<h3 className="font-semibold text-amber-900">MacBook (Manuell)</h3>
|
|
</div>
|
|
<ul className="space-y-2 text-sm text-amber-800">
|
|
<li>• MacBook nachts aus (02:00)</li>
|
|
<li>• Keine Auto-Synchronisation</li>
|
|
<li>• Backup manuell anstoßen</li>
|
|
</ul>
|
|
<div className="mt-4 p-3 bg-amber-100 rounded-lg">
|
|
<code className="text-xs text-amber-700 font-mono">
|
|
rsync -avz macmini:~/Projekte/ ~/Projekte/
|
|
</code>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Manuelles Backup starten */}
|
|
<div className="bg-blue-50 rounded-xl p-5 border border-blue-200">
|
|
<div className="flex items-center gap-3 mb-3">
|
|
<Download className="h-5 w-5 text-blue-600" />
|
|
<h3 className="font-semibold text-blue-900">Backup Script</h3>
|
|
</div>
|
|
<p className="text-sm text-blue-800 mb-3">
|
|
Backup jederzeit manuell starten:
|
|
</p>
|
|
<code className="block text-xs bg-slate-800 text-green-400 p-3 rounded-lg font-mono">
|
|
~/Projekte/breakpilot-pwa/scripts/daily-backup.sh
|
|
</code>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Quick Commands */}
|
|
<div className="bg-slate-800 rounded-xl p-6 text-white">
|
|
<h2 className="text-xl font-semibold mb-4 flex items-center gap-2">
|
|
<Terminal className="h-5 w-5 text-green-400" />
|
|
Wichtige Befehle
|
|
</h2>
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 font-mono text-sm">
|
|
<div className="bg-slate-900 rounded-lg p-4">
|
|
<p className="text-slate-400 mb-2"># CI/CD Logs ansehen</p>
|
|
<code className="text-green-400">ssh macmini "docker logs breakpilot-pwa-backend --tail 50"</code>
|
|
</div>
|
|
<div className="bg-slate-900 rounded-lg p-4">
|
|
<p className="text-slate-400 mb-2"># Container neu starten</p>
|
|
<code className="text-green-400">ssh macmini "docker compose restart backend"</code>
|
|
</div>
|
|
<div className="bg-slate-900 rounded-lg p-4">
|
|
<p className="text-slate-400 mb-2"># Alle Container Status</p>
|
|
<code className="text-green-400">ssh macmini "docker ps"</code>
|
|
</div>
|
|
<div className="bg-slate-900 rounded-lg p-4">
|
|
<p className="text-slate-400 mb-2"># Pipeline Status (Gitea)</p>
|
|
<code className="text-green-400">open http://macmini:3003</code>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Team Workflow with Feature Branches */}
|
|
<div className="bg-indigo-50 rounded-xl border border-indigo-200 p-6">
|
|
<h2 className="text-xl font-semibold text-indigo-900 mb-4 flex items-center gap-2">
|
|
<GitBranch className="h-5 w-5 text-indigo-600" />
|
|
Team-Workflow (3+ Entwickler)
|
|
</h2>
|
|
|
|
<div className="bg-white rounded-xl p-5 mb-4">
|
|
<h3 className="font-semibold text-slate-900 mb-3">Feature Branch Workflow</h3>
|
|
<div className="flex flex-wrap items-center gap-2 text-sm">
|
|
<code className="bg-slate-100 px-2 py-1 rounded">main</code>
|
|
<ArrowRight className="h-4 w-4 text-slate-400" />
|
|
<code className="bg-blue-100 text-blue-700 px-2 py-1 rounded">feature/neue-funktion</code>
|
|
<ArrowRight className="h-4 w-4 text-slate-400" />
|
|
<span className="text-slate-600">Entwicklung</span>
|
|
<ArrowRight className="h-4 w-4 text-slate-400" />
|
|
<span className="bg-purple-100 text-purple-700 px-2 py-1 rounded">Pull Request</span>
|
|
<ArrowRight className="h-4 w-4 text-slate-400" />
|
|
<span className="bg-green-100 text-green-700 px-2 py-1 rounded">Code Review</span>
|
|
<ArrowRight className="h-4 w-4 text-slate-400" />
|
|
<code className="bg-slate-100 px-2 py-1 rounded">main</code>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
<div className="bg-white rounded-lg p-4 border border-indigo-100">
|
|
<h4 className="font-medium text-slate-900 mb-2">1. Feature Branch erstellen</h4>
|
|
<code className="block text-xs bg-slate-800 text-green-400 p-2 rounded font-mono">
|
|
git checkout -b feature/mein-feature
|
|
</code>
|
|
</div>
|
|
<div className="bg-white rounded-lg p-4 border border-indigo-100">
|
|
<h4 className="font-medium text-slate-900 mb-2">2. Änderungen committen</h4>
|
|
<code className="block text-xs bg-slate-800 text-green-400 p-2 rounded font-mono">
|
|
git commit -m "feat: beschreibung"
|
|
</code>
|
|
</div>
|
|
<div className="bg-white rounded-lg p-4 border border-indigo-100">
|
|
<h4 className="font-medium text-slate-900 mb-2">3. Branch pushen</h4>
|
|
<code className="block text-xs bg-slate-800 text-green-400 p-2 rounded font-mono">
|
|
git push -u origin feature/mein-feature
|
|
</code>
|
|
</div>
|
|
<div className="bg-white rounded-lg p-4 border border-indigo-100">
|
|
<h4 className="font-medium text-slate-900 mb-2">4. Pull Request in Gitea</h4>
|
|
<code className="block text-xs bg-slate-800 text-green-400 p-2 rounded font-mono">
|
|
http://macmini:3003 → Pull Request
|
|
</code>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="mt-4 p-4 bg-indigo-100 rounded-lg">
|
|
<h4 className="font-medium text-indigo-900 mb-2">Branch-Namenskonvention</h4>
|
|
<div className="grid grid-cols-2 md:grid-cols-4 gap-2 text-sm">
|
|
<div><code className="text-indigo-700">feature/</code> Neue Funktion</div>
|
|
<div><code className="text-indigo-700">fix/</code> Bugfix</div>
|
|
<div><code className="text-indigo-700">hotfix/</code> Dringender Fix</div>
|
|
<div><code className="text-indigo-700">refactor/</code> Code-Umbau</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Team Rules */}
|
|
<div className="bg-amber-50 rounded-xl border border-amber-200 p-6">
|
|
<h2 className="text-xl font-semibold text-amber-900 mb-4 flex items-center gap-2">
|
|
<Users className="h-5 w-5 text-amber-600" />
|
|
Team-Regeln
|
|
</h2>
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
<div className="flex items-start gap-3">
|
|
<CheckCircle2 className="h-5 w-5 text-green-600 flex-shrink-0 mt-0.5" />
|
|
<div>
|
|
<h3 className="font-medium text-slate-900">Feature Branches nutzen</h3>
|
|
<p className="text-sm text-slate-600">Nie direkt auf main pushen - immer über Pull Request</p>
|
|
</div>
|
|
</div>
|
|
<div className="flex items-start gap-3">
|
|
<CheckCircle2 className="h-5 w-5 text-green-600 flex-shrink-0 mt-0.5" />
|
|
<div>
|
|
<h3 className="font-medium text-slate-900">Code Review erforderlich</h3>
|
|
<p className="text-sm text-slate-600">Mindestens 1 Approval vor dem Merge</p>
|
|
</div>
|
|
</div>
|
|
<div className="flex items-start gap-3">
|
|
<CheckCircle2 className="h-5 w-5 text-green-600 flex-shrink-0 mt-0.5" />
|
|
<div>
|
|
<h3 className="font-medium text-slate-900">Tests müssen grün sein</h3>
|
|
<p className="text-sm text-slate-600">CI/CD Pipeline muss erfolgreich durchlaufen</p>
|
|
</div>
|
|
</div>
|
|
<div className="flex items-start gap-3">
|
|
<CheckCircle2 className="h-5 w-5 text-green-600 flex-shrink-0 mt-0.5" />
|
|
<div>
|
|
<h3 className="font-medium text-slate-900">Aussagekräftige Commits</h3>
|
|
<p className="text-sm text-slate-600">Nutze Conventional Commits (feat:, fix:, etc.)</p>
|
|
</div>
|
|
</div>
|
|
<div className="flex items-start gap-3">
|
|
<CheckCircle2 className="h-5 w-5 text-green-600 flex-shrink-0 mt-0.5" />
|
|
<div>
|
|
<h3 className="font-medium text-slate-900">Branch aktuell halten</h3>
|
|
<p className="text-sm text-slate-600">Regelmäßig main in deinen Branch mergen</p>
|
|
</div>
|
|
</div>
|
|
<div className="flex items-start gap-3">
|
|
<AlertTriangle className="h-5 w-5 text-amber-600 flex-shrink-0 mt-0.5" />
|
|
<div>
|
|
<h3 className="font-medium text-slate-900">Nie Force-Push auf main</h3>
|
|
<p className="text-sm text-slate-600">Geschichte von main nie überschreiben</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* CI/CD Infrastruktur - Automatisierte OAuth Integration */}
|
|
<div className="bg-white rounded-xl border border-slate-200 p-6">
|
|
<h2 className="text-xl font-semibold text-slate-900 mb-4 flex items-center gap-2">
|
|
<Shield className="h-5 w-5 text-indigo-600" />
|
|
CI/CD Infrastruktur (Automatisiert)
|
|
</h2>
|
|
|
|
<div className="bg-blue-50 rounded-xl p-4 mb-6 border border-blue-200">
|
|
<div className="flex items-start gap-3">
|
|
<Info className="h-5 w-5 text-blue-600 flex-shrink-0 mt-0.5" />
|
|
<div>
|
|
<h4 className="font-medium text-blue-900">Warum automatisiert?</h4>
|
|
<p className="text-sm text-blue-800 mt-1">
|
|
Die OAuth-Integration zwischen Woodpecker und Gitea ist vollautomatisiert.
|
|
Dies ist eine DevSecOps Best Practice: Credentials werden in HashiCorp Vault gespeichert
|
|
und können bei Bedarf automatisch regeneriert werden.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
{/* Architektur */}
|
|
<div className="bg-slate-50 rounded-xl p-5 border border-slate-200">
|
|
<h3 className="font-semibold text-slate-900 mb-3">Architektur</h3>
|
|
<div className="space-y-3 text-sm">
|
|
<div className="flex items-center gap-3 p-2 bg-white rounded-lg border">
|
|
<div className="w-3 h-3 bg-green-500 rounded-full" />
|
|
<span className="font-medium">Gitea</span>
|
|
<span className="text-slate-500">Port 3003</span>
|
|
<span className="text-xs text-slate-400 ml-auto">Git Server</span>
|
|
</div>
|
|
<div className="flex items-center justify-center">
|
|
<ArrowRight className="h-4 w-4 text-slate-400 rotate-90" />
|
|
<span className="text-xs text-slate-500 ml-2">OAuth 2.0</span>
|
|
</div>
|
|
<div className="flex items-center gap-3 p-2 bg-white rounded-lg border">
|
|
<div className="w-3 h-3 bg-blue-500 rounded-full" />
|
|
<span className="font-medium">Woodpecker</span>
|
|
<span className="text-slate-500">Port 8090</span>
|
|
<span className="text-xs text-slate-400 ml-auto">CI/CD Server</span>
|
|
</div>
|
|
<div className="flex items-center justify-center">
|
|
<ArrowRight className="h-4 w-4 text-slate-400 rotate-90" />
|
|
<span className="text-xs text-slate-500 ml-2">Credentials</span>
|
|
</div>
|
|
<div className="flex items-center gap-3 p-2 bg-white rounded-lg border">
|
|
<div className="w-3 h-3 bg-purple-500 rounded-full" />
|
|
<span className="font-medium">Vault</span>
|
|
<span className="text-slate-500">Port 8200</span>
|
|
<span className="text-xs text-slate-400 ml-auto">Secrets Manager</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Credentials Speicherort */}
|
|
<div className="bg-slate-50 rounded-xl p-5 border border-slate-200">
|
|
<h3 className="font-semibold text-slate-900 mb-3">Credentials Speicherorte</h3>
|
|
<div className="space-y-3 text-sm">
|
|
<div className="p-3 bg-white rounded-lg border">
|
|
<div className="flex items-center gap-2 mb-1">
|
|
<Database className="h-4 w-4 text-purple-500" />
|
|
<span className="font-medium">HashiCorp Vault</span>
|
|
</div>
|
|
<code className="text-xs bg-slate-100 px-2 py-1 rounded">
|
|
secret/cicd/woodpecker
|
|
</code>
|
|
<p className="text-xs text-slate-500 mt-1">Client ID + Secret (Quelle der Wahrheit)</p>
|
|
</div>
|
|
<div className="p-3 bg-white rounded-lg border">
|
|
<div className="flex items-center gap-2 mb-1">
|
|
<FileCode className="h-4 w-4 text-blue-500" />
|
|
<span className="font-medium">.env Datei</span>
|
|
</div>
|
|
<code className="text-xs bg-slate-100 px-2 py-1 rounded">
|
|
WOODPECKER_GITEA_CLIENT/SECRET
|
|
</code>
|
|
<p className="text-xs text-slate-500 mt-1">Für Docker Compose (aus Vault geladen)</p>
|
|
</div>
|
|
<div className="p-3 bg-white rounded-lg border">
|
|
<div className="flex items-center gap-2 mb-1">
|
|
<Database className="h-4 w-4 text-green-500" />
|
|
<span className="font-medium">Gitea PostgreSQL</span>
|
|
</div>
|
|
<code className="text-xs bg-slate-100 px-2 py-1 rounded">
|
|
oauth2_application
|
|
</code>
|
|
<p className="text-xs text-slate-500 mt-1">OAuth App Registration (gehashtes Secret)</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Troubleshooting */}
|
|
<div className="mt-6 bg-amber-50 rounded-xl p-5 border border-amber-200">
|
|
<h3 className="font-semibold text-amber-900 mb-3 flex items-center gap-2">
|
|
<AlertTriangle className="h-5 w-5 text-amber-600" />
|
|
Troubleshooting: OAuth Fehler beheben
|
|
</h3>
|
|
<p className="text-sm text-amber-800 mb-3">
|
|
Falls der Fehler "Client ID not registered" oder "user does not exist" auftritt:
|
|
</p>
|
|
<div className="bg-slate-800 rounded-lg p-4 font-mono text-sm">
|
|
<p className="text-slate-400"># Credentials automatisch regenerieren</p>
|
|
<p className="text-green-400">./scripts/sync-woodpecker-credentials.sh --regenerate</p>
|
|
<p className="text-slate-400 mt-2"># Oder manuell: Vault → Gitea → .env → Restart</p>
|
|
<p className="text-green-400">rsync .env macmini:~/Projekte/breakpilot-pwa/</p>
|
|
<p className="text-green-400">ssh macmini "cd ~/Projekte/breakpilot-pwa && docker compose up -d --force-recreate woodpecker-server"</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Team Members Info */}
|
|
<div className="bg-white rounded-xl border border-slate-200 p-6">
|
|
<h2 className="text-xl font-semibold text-slate-900 mb-4 flex items-center gap-2">
|
|
<Users className="h-5 w-5 text-indigo-600" />
|
|
Team-Kommunikation
|
|
</h2>
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
|
<div className="bg-slate-50 rounded-lg p-4 text-center">
|
|
<div className="text-3xl mb-2">💬</div>
|
|
<h3 className="font-medium text-slate-900">Pull Request Kommentare</h3>
|
|
<p className="text-sm text-slate-600 mt-1">Code-Diskussionen im PR</p>
|
|
</div>
|
|
<div className="bg-slate-50 rounded-lg p-4 text-center">
|
|
<div className="text-3xl mb-2">📋</div>
|
|
<h3 className="font-medium text-slate-900">Issues in Gitea</h3>
|
|
<p className="text-sm text-slate-600 mt-1">Bugs & Features tracken</p>
|
|
</div>
|
|
<div className="bg-slate-50 rounded-lg p-4 text-center">
|
|
<div className="text-3xl mb-2">🔔</div>
|
|
<h3 className="font-medium text-slate-900">CI/CD Notifications</h3>
|
|
<p className="text-sm text-slate-600 mt-1">Pipeline-Status per Mail</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|