#!/bin/bash # Gitea-specific deployment script # Optimiert fΓΌr lokalen Gitea Runner set -e # Configuration PROJECT_NAME="portfolio" CONTAINER_NAME="portfolio-app" IMAGE_NAME="portfolio-app" PORT=3000 BACKUP_PORT=3001 LOG_FILE="./logs/gitea-deploy.log" # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Logging function log() { echo -e "${BLUE}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $1" | tee -a "$LOG_FILE" } error() { echo -e "${RED}[ERROR]${NC} $1" | tee -a "$LOG_FILE" } success() { echo -e "${GREEN}[SUCCESS]${NC} $1" | tee -a "$LOG_FILE" } warning() { echo -e "${YELLOW}[WARNING]${NC} $1" | tee -a "$LOG_FILE" } # Check if running as root (skip in CI environments) if [[ $EUID -eq 0 ]] && [[ -z "$CI" ]]; then error "This script should not be run as root (use CI=true to override)" exit 1 fi # Check if Docker is running if ! docker info > /dev/null 2>&1; then error "Docker is not running. Please start Docker and try again." exit 1 fi # Check if we're in the right directory if [ ! -f "package.json" ] || [ ! -f "Dockerfile" ]; then error "Please run this script from the project root directory" exit 1 fi log "πŸš€ Starting Gitea deployment for $PROJECT_NAME" # Step 1: Code Quality Checks log "πŸ“‹ Step 1: Running code quality checks..." # Run linting log "πŸ” Running ESLint..." npm run lint || { error "ESLint failed. Please fix the issues before deploying." exit 1 } # Run tests log "πŸ§ͺ Running tests..." npm run test || { error "Tests failed. Please fix the issues before deploying." exit 1 } success "βœ… Code quality checks passed" # Step 2: Build Application log "πŸ”¨ Step 2: Building application..." # Build Next.js application log "πŸ“¦ Building Next.js application..." npm run build || { error "Build failed" exit 1 } success "βœ… Application built successfully" # Step 3: Docker Operations log "🐳 Step 3: Docker operations..." # Build Docker image log "πŸ—οΈ Building Docker image..." docker build -t "$IMAGE_NAME:latest" . || { error "Docker build failed" exit 1 } # Tag with timestamp TIMESTAMP=$(date +%Y%m%d-%H%M%S) docker tag "$IMAGE_NAME:latest" "$IMAGE_NAME:$TIMESTAMP" success "βœ… Docker image built successfully" # Step 4: Deployment log "πŸš€ Step 4: Deploying application..." # Check if container is running if [ "$(docker inspect -f '{{.State.Running}}' "$CONTAINER_NAME" 2>/dev/null)" = "true" ]; then log "πŸ“¦ Stopping existing container..." docker stop "$CONTAINER_NAME" || true docker rm "$CONTAINER_NAME" || true fi # Check if port is available if lsof -Pi :$PORT -sTCP:LISTEN -t >/dev/null ; then warning "Port $PORT is in use. Trying backup port $BACKUP_PORT" DEPLOY_PORT=$BACKUP_PORT else DEPLOY_PORT=$PORT fi # Start new container with environment variables log "πŸš€ Starting new container on port $DEPLOY_PORT..." docker run -d \ --name "$CONTAINER_NAME" \ --restart unless-stopped \ -p "$DEPLOY_PORT:3000" \ -e NODE_ENV=production \ -e NEXT_PUBLIC_BASE_URL=https://dk0.dev \ -e MY_EMAIL=contact@dk0.dev \ -e MY_INFO_EMAIL=info@dk0.dev \ -e MY_PASSWORD="${MY_PASSWORD:-your-email-password}" \ -e MY_INFO_PASSWORD="${MY_INFO_PASSWORD:-your-info-email-password}" \ -e ADMIN_BASIC_AUTH="${ADMIN_BASIC_AUTH:-admin:your_secure_password_here}" \ -e LOG_LEVEL=info \ "$IMAGE_NAME:latest" || { error "Failed to start container" exit 1 } # Wait for container to be ready log "⏳ Waiting for container to be ready..." sleep 15 # Check if container is actually running if [ "$(docker inspect -f '{{.State.Running}}' "$CONTAINER_NAME" 2>/dev/null)" != "true" ]; then error "Container failed to start or crashed" log "Container logs:" docker logs "$CONTAINER_NAME" --tail=50 exit 1 fi # Health check log "πŸ₯ Performing health check..." HEALTH_CHECK_TIMEOUT=120 HEALTH_CHECK_INTERVAL=3 ELAPSED=0 while [ $ELAPSED -lt $HEALTH_CHECK_TIMEOUT ]; do # Check if container is still running if [ "$(docker inspect -f '{{.State.Running}}' "$CONTAINER_NAME" 2>/dev/null)" != "true" ]; then error "Container stopped during health check" log "Container logs:" docker logs "$CONTAINER_NAME" --tail=50 exit 1 fi # Try health check endpoint if curl -f "http://localhost:$DEPLOY_PORT/api/health" > /dev/null 2>&1; then success "βœ… Application is healthy!" break fi sleep $HEALTH_CHECK_INTERVAL ELAPSED=$((ELAPSED + HEALTH_CHECK_INTERVAL)) echo -n "." done if [ $ELAPSED -ge $HEALTH_CHECK_TIMEOUT ]; then error "Health check timeout. Application may not be running properly." log "Container status:" docker inspect "$CONTAINER_NAME" --format='{{.State.Status}} - {{.State.Health.Status}}' log "Container logs:" docker logs "$CONTAINER_NAME" --tail=100 exit 1 fi # Step 5: Verification log "βœ… Step 5: Verifying deployment..." # Test main page if curl -f "http://localhost:$DEPLOY_PORT/" > /dev/null 2>&1; then success "βœ… Main page is accessible" else error "❌ Main page is not accessible" exit 1 fi # Show container status log "πŸ“Š Container status:" docker ps --filter "name=$CONTAINER_NAME" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" # Show resource usage log "πŸ“ˆ Resource usage:" docker stats --no-stream --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}" "$CONTAINER_NAME" # Step 6: Cleanup log "🧹 Step 6: Cleaning up old images..." # Remove old images (keep last 3 versions) docker images "$IMAGE_NAME" --format "table {{.Tag}}\t{{.ID}}" | tail -n +2 | head -n -3 | awk '{print $2}' | xargs -r docker rmi || { warning "No old images to remove" } # Clean up unused Docker resources docker system prune -f --volumes || { warning "Failed to clean up Docker resources" } # Final success message success "πŸŽ‰ Gitea deployment completed successfully!" log "🌐 Application is available at: http://localhost:$DEPLOY_PORT" log "πŸ₯ Health check endpoint: http://localhost:$DEPLOY_PORT/api/health" log "πŸ“Š Container name: $CONTAINER_NAME" log "πŸ“ Logs: docker logs $CONTAINER_NAME" # Update deployment log echo "$(date): Gitea deployment successful - Port: $DEPLOY_PORT - Image: $IMAGE_NAME:$TIMESTAMP" >> "$LOG_FILE" exit 0