deb-bootc-image-builder/scripts/build_debian_image.sh
2025-08-11 08:59:41 -07:00

431 lines
10 KiB
Bash

#!/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 "$@"