- Modify root checks to allow running as root in CI environments - Add conditional check: only prevent root when not in CI (CI env var not set) - Updated scripts: - scripts/gitea-deploy.sh - scripts/gitea-deploy-simple.sh - scripts/deploy.sh - scripts/auto-deploy.sh - scripts/setup-gitea-runner.sh This fixes the 'This script should not be run as root' error in Gitea Actions where containers run as root by default.
234 lines
6.3 KiB
Bash
Executable File
234 lines
6.3 KiB
Bash
Executable File
#!/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
|