245 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			245 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
#!/bin/bash
 | 
						||
 | 
						||
# Build script for Raspberry Pi Zero/ARM devices
 | 
						||
# Optimized for low memory and no compilation
 | 
						||
 | 
						||
set -e
 | 
						||
 | 
						||
# Colors for output
 | 
						||
RED='\033[0;31m'
 | 
						||
GREEN='\033[0;32m'
 | 
						||
YELLOW='\033[1;33m'
 | 
						||
BLUE='\033[0;34m'
 | 
						||
NC='\033[0m' # No Color
 | 
						||
 | 
						||
# Configuration
 | 
						||
IMAGE_NAME="turmli-calendar"
 | 
						||
CONTAINER_NAME="turmli-calendar"
 | 
						||
 | 
						||
# Print functions
 | 
						||
print_error() {
 | 
						||
    echo -e "${RED}❌ $1${NC}"
 | 
						||
}
 | 
						||
 | 
						||
print_success() {
 | 
						||
    echo -e "${GREEN}✅ $1${NC}"
 | 
						||
}
 | 
						||
 | 
						||
print_info() {
 | 
						||
    echo -e "${BLUE}ℹ️  $1${NC}"
 | 
						||
}
 | 
						||
 | 
						||
print_warning() {
 | 
						||
    echo -e "${YELLOW}⚠️  $1${NC}"
 | 
						||
}
 | 
						||
 | 
						||
# Detect system
 | 
						||
detect_system() {
 | 
						||
    ARCH=$(uname -m)
 | 
						||
    OS=$(cat /etc/os-release | grep "^ID=" | cut -d= -f2 | tr -d '"')
 | 
						||
    VERSION=$(cat /etc/os-release | grep "^VERSION_CODENAME=" | cut -d= -f2 | tr -d '"')
 | 
						||
    
 | 
						||
    print_info "System: ${OS} ${VERSION} on ${ARCH}"
 | 
						||
    
 | 
						||
    # Check if we're on a Raspberry Pi
 | 
						||
    if [ -f /proc/device-tree/model ]; then
 | 
						||
        MODEL=$(tr -d '\0' < /proc/device-tree/model)
 | 
						||
        print_info "Raspberry Pi detected: ${MODEL}"
 | 
						||
    fi
 | 
						||
    
 | 
						||
    # Check available memory
 | 
						||
    if [ -f /proc/meminfo ]; then
 | 
						||
        TOTAL_MEM=$(grep MemTotal /proc/meminfo | awk '{print $2}')
 | 
						||
        TOTAL_MEM_MB=$((TOTAL_MEM / 1024))
 | 
						||
        print_info "Available RAM: ${TOTAL_MEM_MB}MB"
 | 
						||
        
 | 
						||
        if [ $TOTAL_MEM_MB -lt 512 ]; then
 | 
						||
            print_warning "Low memory detected! Build may be slow."
 | 
						||
            print_info "Tip: Consider adding swap space if build fails"
 | 
						||
        fi
 | 
						||
    fi
 | 
						||
}
 | 
						||
 | 
						||
# Check for container runtime
 | 
						||
check_runtime() {
 | 
						||
    if command -v podman &> /dev/null; then
 | 
						||
        RUNTIME="podman"
 | 
						||
        print_success "Using Podman"
 | 
						||
    elif command -v docker &> /dev/null; then
 | 
						||
        RUNTIME="docker"
 | 
						||
        print_success "Using Docker"
 | 
						||
    else
 | 
						||
        print_error "No container runtime found!"
 | 
						||
        print_info "Install Podman (recommended) or Docker:"
 | 
						||
        echo "  sudo apt-get update"
 | 
						||
        echo "  sudo apt-get install podman"
 | 
						||
        exit 1
 | 
						||
    fi
 | 
						||
}
 | 
						||
 | 
						||
# Build the container
 | 
						||
build_container() {
 | 
						||
    print_info "Building container image..."
 | 
						||
    
 | 
						||
    # Choose the right Dockerfile
 | 
						||
    if [ -f "Dockerfile.pizero" ] && [[ "$ARCH" == "armv6l" ]]; then
 | 
						||
        DOCKERFILE="Dockerfile.pizero"
 | 
						||
        print_info "Using Pi Zero optimized Dockerfile"
 | 
						||
    elif [ -f "Dockerfile.minimal" ]; then
 | 
						||
        DOCKERFILE="Dockerfile.minimal"
 | 
						||
        print_info "Using minimal Dockerfile (no compilation)"
 | 
						||
    elif [ -f "Dockerfile" ]; then
 | 
						||
        DOCKERFILE="Dockerfile"
 | 
						||
        print_warning "Using standard Dockerfile (may require compilation)"
 | 
						||
    else
 | 
						||
        print_error "No Dockerfile found!"
 | 
						||
        exit 1
 | 
						||
    fi
 | 
						||
    
 | 
						||
    # Build without memory limits (they may not be supported on all systems)
 | 
						||
    ${RUNTIME} build \
 | 
						||
        --file "${DOCKERFILE}" \
 | 
						||
        --tag "${IMAGE_NAME}" \
 | 
						||
        . || {
 | 
						||
        print_error "Build failed!"
 | 
						||
        if [ $TOTAL_MEM_MB -lt 512 ]; then
 | 
						||
            print_info "Try these solutions for low memory:"
 | 
						||
            echo "  1. Add swap space:"
 | 
						||
            echo "     sudo dd if=/dev/zero of=/swapfile bs=1M count=1024"
 | 
						||
            echo "     sudo mkswap /swapfile"
 | 
						||
            echo "     sudo swapon /swapfile"
 | 
						||
            echo "  2. Use pre-built image:"
 | 
						||
            echo "     ${RUNTIME} pull docker.io/yourusername/turmli-calendar:armv6"
 | 
						||
        fi
 | 
						||
        exit 1
 | 
						||
    }
 | 
						||
    
 | 
						||
    print_success "Container image built successfully!"
 | 
						||
}
 | 
						||
 | 
						||
# Run the container
 | 
						||
run_container() {
 | 
						||
    print_info "Starting container..."
 | 
						||
    
 | 
						||
    # Check if container already exists
 | 
						||
    if ${RUNTIME} ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
 | 
						||
        print_info "Container already exists, removing it..."
 | 
						||
        ${RUNTIME} stop ${CONTAINER_NAME} 2>/dev/null || true
 | 
						||
        ${RUNTIME} rm ${CONTAINER_NAME} 2>/dev/null || true
 | 
						||
    fi
 | 
						||
    
 | 
						||
    # Create cache file if it doesn't exist
 | 
						||
    if [ ! -f "calendar_cache.json" ]; then
 | 
						||
        echo "{}" > calendar_cache.json
 | 
						||
        print_info "Created cache file"
 | 
						||
    fi
 | 
						||
    
 | 
						||
    # Run container (without memory limits as they may not be supported)
 | 
						||
    print_info "Starting container..."
 | 
						||
    ${RUNTIME} run -d \
 | 
						||
        --name ${CONTAINER_NAME} \
 | 
						||
        -p 8000:8000 \
 | 
						||
        -v $(pwd)/calendar_cache.json:/app/calendar_cache.json:Z \
 | 
						||
        -e TZ=Europe/Berlin \
 | 
						||
        --restart unless-stopped \
 | 
						||
        ${IMAGE_NAME} || {
 | 
						||
        # If it fails with :Z flag (SELinux label), try without it
 | 
						||
        print_warning "Retrying without SELinux labels..."
 | 
						||
        ${RUNTIME} run -d \
 | 
						||
            --name ${CONTAINER_NAME} \
 | 
						||
            -p 8000:8000 \
 | 
						||
            -v $(pwd)/calendar_cache.json:/app/calendar_cache.json \
 | 
						||
            -e TZ=Europe/Berlin \
 | 
						||
            --restart unless-stopped \
 | 
						||
            ${IMAGE_NAME}
 | 
						||
    }
 | 
						||
    
 | 
						||
    print_success "Container started!"
 | 
						||
    print_info "Access the calendar at: http://$(hostname -I | awk '{print $1}'):8000"
 | 
						||
    print_info "or http://localhost:8000"
 | 
						||
}
 | 
						||
 | 
						||
# Check container status
 | 
						||
check_status() {
 | 
						||
    print_info "Checking container status..."
 | 
						||
    
 | 
						||
    if ${RUNTIME} ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | grep -q ${CONTAINER_NAME}; then
 | 
						||
        ${RUNTIME} ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | grep -E "NAMES|${CONTAINER_NAME}"
 | 
						||
        
 | 
						||
        # Test if the app is responding
 | 
						||
        print_info "Testing application..."
 | 
						||
        sleep 3
 | 
						||
        if curl -s -f http://localhost:8000/api/events > /dev/null 2>&1; then
 | 
						||
            print_success "Application is running and healthy!"
 | 
						||
        else
 | 
						||
            print_warning "Application not responding yet, checking logs..."
 | 
						||
            ${RUNTIME} logs --tail 20 ${CONTAINER_NAME}
 | 
						||
        fi
 | 
						||
    else
 | 
						||
        print_warning "Container is not running"
 | 
						||
    fi
 | 
						||
}
 | 
						||
 | 
						||
# Show logs
 | 
						||
show_logs() {
 | 
						||
    ${RUNTIME} logs -f ${CONTAINER_NAME}
 | 
						||
}
 | 
						||
 | 
						||
# Main script
 | 
						||
case "${1:-build}" in
 | 
						||
    build)
 | 
						||
        detect_system
 | 
						||
        check_runtime
 | 
						||
        build_container
 | 
						||
        ;;
 | 
						||
    run)
 | 
						||
        detect_system
 | 
						||
        check_runtime
 | 
						||
        run_container
 | 
						||
        check_status
 | 
						||
        ;;
 | 
						||
    start)
 | 
						||
        detect_system
 | 
						||
        check_runtime
 | 
						||
        build_container
 | 
						||
        run_container
 | 
						||
        check_status
 | 
						||
        ;;
 | 
						||
    status)
 | 
						||
        check_runtime
 | 
						||
        check_status
 | 
						||
        ;;
 | 
						||
    logs)
 | 
						||
        check_runtime
 | 
						||
        show_logs
 | 
						||
        ;;
 | 
						||
    stop)
 | 
						||
        check_runtime
 | 
						||
        print_info "Stopping container..."
 | 
						||
        ${RUNTIME} stop ${CONTAINER_NAME}
 | 
						||
        print_success "Container stopped"
 | 
						||
        ;;
 | 
						||
    help)
 | 
						||
        echo "Raspberry Pi Build Script for Turmli Calendar"
 | 
						||
        echo ""
 | 
						||
        echo "Usage: $0 [COMMAND]"
 | 
						||
        echo ""
 | 
						||
        echo "Commands:"
 | 
						||
        echo "  build   - Build the container image (default)"
 | 
						||
        echo "  run     - Run the container"
 | 
						||
        echo "  start   - Build and run"
 | 
						||
        echo "  status  - Check container status"
 | 
						||
        echo "  logs    - Show container logs"
 | 
						||
        echo "  stop    - Stop the container"
 | 
						||
        echo "  help    - Show this help"
 | 
						||
        echo ""
 | 
						||
        echo "This script is optimized for Raspberry Pi Zero and other"
 | 
						||
        echo "low-resource ARM devices. It uses Pydantic v1 to avoid"
 | 
						||
        echo "Rust compilation requirements."
 | 
						||
        ;;
 | 
						||
    *)
 | 
						||
        echo "Unknown command: $1"
 | 
						||
        echo "Run '$0 help' for usage"
 | 
						||
        exit 1
 | 
						||
        ;;
 | 
						||
esac |