#!/bin/bash # Debian Image Builder Script # This script demonstrates the complete Debian image building pipeline set -euo pipefail # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[0;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Configuration SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" OUTPUT_DIR="${PROJECT_ROOT}/output" BUILD_DIR="${PROJECT_ROOT}/build" MANIFEST_DIR="${BUILD_DIR}/manifests" # Default values RELEASE="trixie" ARCH="amd64" IMAGE_TYPE="qcow2" VERBOSE=false CLEAN=false # Function to print colored output print_status() { echo -e "${BLUE}[INFO]${NC} $1" } print_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" } print_warning() { echo -e "${YELLOW}[WARNING]${NC} $1" } print_error() { echo -e "${RED}[ERROR]${NC} $1" } # Function to show usage show_usage() { cat << EOF Usage: $0 [OPTIONS] Build a Debian image using the debian-bootc-image-builder pipeline. OPTIONS: -r, --release RELEASE Debian release (default: trixie) -a, --arch ARCH Architecture (default: amd64) -t, --type TYPE Image type: qcow2, desktop, server, development (default: qcow2) -o, --output DIR Output directory (default: ./output) -v, --verbose Enable verbose output -c, --clean Clean build directory before building -h, --help Show this help message EXAMPLES: $0 --type desktop --release trixie $0 --type server --arch amd64 --verbose $0 --type development --clean EOF } # Function to parse command line arguments parse_args() { while [[ $# -gt 0 ]]; do case $1 in -r|--release) RELEASE="$2" shift 2 ;; -a|--arch) ARCH="$2" shift 2 ;; -t|--type) IMAGE_TYPE="$2" shift 2 ;; -o|--output) OUTPUT_DIR="$2" shift 2 ;; -v|--verbose) VERBOSE=true shift ;; -c|--clean) CLEAN=true shift ;; -h|--help) show_usage exit 0 ;; *) print_error "Unknown option: $1" show_usage exit 1 ;; esac done } # Function to validate inputs validate_inputs() { print_status "Validating inputs..." # Validate release case "$RELEASE" in trixie|bookworm|bullseye) ;; *) print_error "Unsupported release: $RELEASE" print_error "Supported releases: trixie, bookworm, bullseye" exit 1 ;; esac # Validate architecture case "$ARCH" in amd64|arm64|i386) ;; *) print_error "Unsupported architecture: $ARCH" print_error "Supported architectures: amd64, arm64, i386" exit 1 ;; esac # Validate image type case "$IMAGE_TYPE" in qcow2|desktop|server|development) ;; *) print_error "Unsupported image type: $IMAGE_TYPE" print_error "Supported types: qcow2, desktop, server, development" exit 1 ;; esac print_success "Input validation passed" } # Function to setup build environment setup_build_env() { print_status "Setting up build environment..." # Create directories mkdir -p "$OUTPUT_DIR" mkdir -p "$BUILD_DIR" mkdir -p "$MANIFEST_DIR" if [[ "$CLEAN" == true ]]; then print_status "Cleaning build directory..." rm -rf "$BUILD_DIR"/* mkdir -p "$MANIFEST_DIR" fi print_success "Build environment ready" } # Function to run tests run_tests() { print_status "Running tests..." cd "$PROJECT_ROOT" # Run unit tests print_status "Running unit tests..." if make test-unit > /dev/null 2>&1; then print_success "Unit tests passed" else print_error "Unit tests failed" exit 1 fi # Run integration tests print_status "Running integration tests..." if make test-integration > /dev/null 2>&1; then print_success "Integration tests passed" else print_error "Integration tests failed" exit 1 fi print_success "All tests passed" } # Function to generate manifest generate_manifest() { print_status "Generating osbuild manifest for $IMAGE_TYPE image..." local manifest_file="$MANIFEST_DIR/debian-${RELEASE}-${IMAGE_TYPE}.json" # Create a simple manifest for demonstration cat > "$manifest_file" << EOF { "version": "2", "stages": [ { "type": "org.osbuild.debian-filesystem", "options": { "rootfs_type": "ext4", "ostree_integration": true, "home_symlink": true } }, { "type": "org.osbuild.apt", "options": { "packages": [ "linux-image-${ARCH}", "systemd", "initramfs-tools", "grub-efi-${ARCH}", "ostree" ], "release": "${RELEASE}", "arch": "${ARCH}", "repos": [ { "name": "debian", "url": "http://deb.debian.org/debian", "suite": "${RELEASE}", "components": ["main", "contrib", "non-free"] } ] } }, { "type": "org.osbuild.debian-kernel", "options": { "kernel_package": "linux-image-${ARCH}", "initramfs_tools": true, "ostree_integration": true, "modules_autoload": true } }, { "type": "org.osbuild.debian-grub", "options": { "ostree_integration": true, "uefi": true, "secure_boot": false, "timeout": 5, "default_entry": 0 } } EOF # Add image-specific stages case "$IMAGE_TYPE" in desktop) cat >> "$manifest_file" << EOF , { "type": "org.osbuild.debian-desktop-config", "options": { "desktop_environment": "kde", "display_manager": "sddm", "user_sessions": true, "applications": true, "theme": "breeze" } } EOF ;; server) cat >> "$manifest_file" << EOF , { "type": "org.osbuild.debian-server-config", "options": { "security_hardening": true, "firewall": "ufw", "ssh": { "port": 22, "root_login": false, "key_auth_only": false } } } EOF ;; development) cat >> "$manifest_file" << EOF , { "type": "org.osbuild.debian-desktop-config", "options": { "desktop_environment": "kde", "display_manager": "sddm", "user_sessions": true, "applications": true, "theme": "breeze" } }, { "type": "org.osbuild.debian-development-config", "options": { "development_tools": true, "container_runtime": "docker", "dev_user": "debian" } } EOF ;; esac # Close the manifest cat >> "$manifest_file" << EOF ], "assembler": { "type": "org.osbuild.qcow2", "options": { "filename": "debian-${RELEASE}-${IMAGE_TYPE}.qcow2" } } } EOF print_success "Manifest generated: $manifest_file" if [[ "$VERBOSE" == true ]]; then print_status "Manifest contents:" cat "$manifest_file" | jq '.' 2>/dev/null || cat "$manifest_file" fi } # Function to simulate osbuild execution simulate_osbuild() { print_status "Simulating osbuild execution..." local manifest_file="$MANIFEST_DIR/debian-${RELEASE}-${IMAGE_TYPE}.json" local output_file="$OUTPUT_DIR/debian-${RELEASE}-${IMAGE_TYPE}.qcow2" # Create a mock output file print_status "Creating mock QCOW2 image..." dd if=/dev/zero of="$output_file" bs=1M count=100 2>/dev/null || { # Fallback if dd fails print_warning "dd failed, creating empty file" touch "$output_file" } print_success "Mock image created: $output_file" # Show image info if command -v qemu-img >/dev/null 2>&1; then print_status "Image information:" qemu-img info "$output_file" 2>/dev/null || print_warning "qemu-img not available" fi } # Function to run validation run_validation() { print_status "Running validation..." local output_file="$OUTPUT_DIR/debian-${RELEASE}-${IMAGE_TYPE}.qcow2" # Check if output file exists if [[ ! -f "$output_file" ]]; then print_error "Output file not found: $output_file" exit 1 fi # Check file size local file_size=$(stat -c%s "$output_file" 2>/dev/null || stat -f%z "$output_file" 2>/dev/null || echo "0") if [[ "$file_size" -gt 0 ]]; then print_success "Output file size: $file_size bytes" else print_warning "Output file is empty (this is expected for mock builds)" fi print_success "Validation completed" } # Function to show build summary show_summary() { print_status "Build Summary" echo "==================" echo "Release: $RELEASE" echo "Architecture: $ARCH" echo "Image Type: $IMAGE_TYPE" echo "Output Directory: $OUTPUT_DIR" echo "Build Directory: $BUILD_DIR" echo "" echo "Generated Files:" echo "- Manifest: $MANIFEST_DIR/debian-${RELEASE}-${IMAGE_TYPE}.json" echo "- Image: $OUTPUT_DIR/debian-${RELEASE}-${IMAGE_TYPE}.qcow2" echo "" print_success "Build completed successfully!" } # Main function main() { print_status "Starting Debian image build..." print_status "Project root: $PROJECT_ROOT" # Parse arguments parse_args "$@" # Validate inputs validate_inputs # Setup build environment setup_build_env # Run tests run_tests # Generate manifest generate_manifest # Simulate osbuild execution simulate_osbuild # Run validation run_validation # Show summary show_summary } # Run main function with all arguments main "$@"