395 lines
12 KiB
Bash
395 lines
12 KiB
Bash
|
|
#!/bin/bash
|
|||
|
|
#
|
|||
|
|
# Archipelago Complete ISO Build System
|
|||
|
|
# =====================================
|
|||
|
|
#
|
|||
|
|
# This script builds a complete, flashable ISO from source with one command.
|
|||
|
|
# It handles backend compilation, frontend bundling, and ISO creation.
|
|||
|
|
#
|
|||
|
|
# Usage:
|
|||
|
|
# ./build-iso-complete.sh [options]
|
|||
|
|
#
|
|||
|
|
# Options:
|
|||
|
|
# --local Build everything locally (requires Rust + Node.js)
|
|||
|
|
# --remote HOST Build on remote server (recommended for ARM -> x86 cross-compile)
|
|||
|
|
# --skip-backend Skip backend compilation (use existing binary)
|
|||
|
|
# --skip-frontend Skip frontend build (use existing dist)
|
|||
|
|
# --clean Clean all build artifacts before building
|
|||
|
|
# --help Show this help message
|
|||
|
|
#
|
|||
|
|
# Examples:
|
|||
|
|
# ./build-iso-complete.sh --remote archipelago@192.168.1.228
|
|||
|
|
# ./build-iso-complete.sh --local --clean
|
|||
|
|
#
|
|||
|
|
|
|||
|
|
set -e # Exit on error
|
|||
|
|
|
|||
|
|
# =============================================================================
|
|||
|
|
# Configuration
|
|||
|
|
# =============================================================================
|
|||
|
|
|
|||
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|||
|
|
BUILD_DIR="$SCRIPT_DIR/image-recipe/build"
|
|||
|
|
BACKEND_SRC="$SCRIPT_DIR/core/archipelago"
|
|||
|
|
FRONTEND_SRC="$SCRIPT_DIR/neode-ui"
|
|||
|
|
ISO_SCRIPT="$SCRIPT_DIR/image-recipe/build-debian-iso.sh"
|
|||
|
|
|
|||
|
|
# Colors for output
|
|||
|
|
RED='\033[0;31m'
|
|||
|
|
GREEN='\033[0;32m'
|
|||
|
|
YELLOW='\033[1;33m'
|
|||
|
|
BLUE='\033[0;34m'
|
|||
|
|
NC='\033[0m' # No Color
|
|||
|
|
|
|||
|
|
# Build options (defaults)
|
|||
|
|
BUILD_MODE="remote"
|
|||
|
|
REMOTE_HOST=""
|
|||
|
|
SKIP_BACKEND=false
|
|||
|
|
SKIP_FRONTEND=false
|
|||
|
|
CLEAN_BUILD=false
|
|||
|
|
|
|||
|
|
# =============================================================================
|
|||
|
|
# Helper Functions
|
|||
|
|
# =============================================================================
|
|||
|
|
|
|||
|
|
print_header() {
|
|||
|
|
echo ""
|
|||
|
|
echo -e "${BLUE}╔════════════════════════════════════════════════════════╗${NC}"
|
|||
|
|
echo -e "${BLUE}║${NC} $1"
|
|||
|
|
echo -e "${BLUE}╚════════════════════════════════════════════════════════╝${NC}"
|
|||
|
|
echo ""
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
print_success() {
|
|||
|
|
echo -e "${GREEN}✅ $1${NC}"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
print_error() {
|
|||
|
|
echo -e "${RED}❌ $1${NC}"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
print_warning() {
|
|||
|
|
echo -e "${YELLOW}⚠️ $1${NC}"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
print_info() {
|
|||
|
|
echo -e "${BLUE}ℹ️ $1${NC}"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
show_help() {
|
|||
|
|
head -n 25 "$0" | grep "^#" | sed 's/^# //' | sed 's/^#//'
|
|||
|
|
exit 0
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
check_command() {
|
|||
|
|
if ! command -v "$1" &> /dev/null; then
|
|||
|
|
print_error "$1 is not installed"
|
|||
|
|
return 1
|
|||
|
|
fi
|
|||
|
|
return 0
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# =============================================================================
|
|||
|
|
# Parse Arguments
|
|||
|
|
# =============================================================================
|
|||
|
|
|
|||
|
|
while [[ $# -gt 0 ]]; do
|
|||
|
|
case $1 in
|
|||
|
|
--local)
|
|||
|
|
BUILD_MODE="local"
|
|||
|
|
shift
|
|||
|
|
;;
|
|||
|
|
--remote)
|
|||
|
|
BUILD_MODE="remote"
|
|||
|
|
REMOTE_HOST="$2"
|
|||
|
|
shift 2
|
|||
|
|
;;
|
|||
|
|
--skip-backend)
|
|||
|
|
SKIP_BACKEND=true
|
|||
|
|
shift
|
|||
|
|
;;
|
|||
|
|
--skip-frontend)
|
|||
|
|
SKIP_FRONTEND=true
|
|||
|
|
shift
|
|||
|
|
;;
|
|||
|
|
--clean)
|
|||
|
|
CLEAN_BUILD=true
|
|||
|
|
shift
|
|||
|
|
;;
|
|||
|
|
--help|-h)
|
|||
|
|
show_help
|
|||
|
|
;;
|
|||
|
|
*)
|
|||
|
|
print_error "Unknown option: $1"
|
|||
|
|
show_help
|
|||
|
|
;;
|
|||
|
|
esac
|
|||
|
|
done
|
|||
|
|
|
|||
|
|
# =============================================================================
|
|||
|
|
# Pre-flight Checks
|
|||
|
|
# =============================================================================
|
|||
|
|
|
|||
|
|
print_header "Archipelago Complete ISO Builder"
|
|||
|
|
|
|||
|
|
print_info "Build mode: $BUILD_MODE"
|
|||
|
|
[[ -n "$REMOTE_HOST" ]] && print_info "Remote host: $REMOTE_HOST"
|
|||
|
|
[[ "$SKIP_BACKEND" = true ]] && print_warning "Skipping backend build"
|
|||
|
|
[[ "$SKIP_FRONTEND" = true ]] && print_warning "Skipping frontend build"
|
|||
|
|
[[ "$CLEAN_BUILD" = true ]] && print_warning "Clean build enabled"
|
|||
|
|
|
|||
|
|
echo ""
|
|||
|
|
|
|||
|
|
# Check for required commands
|
|||
|
|
if [[ "$BUILD_MODE" == "remote" ]] && [[ -z "$REMOTE_HOST" ]]; then
|
|||
|
|
print_error "Remote build mode requires --remote HOST"
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
if [[ "$BUILD_MODE" == "remote" ]]; then
|
|||
|
|
if ! check_command ssh; then
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
if ! check_command rsync; then
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# =============================================================================
|
|||
|
|
# Step 1: Clean Build Artifacts (if requested)
|
|||
|
|
# =============================================================================
|
|||
|
|
|
|||
|
|
if [[ "$CLEAN_BUILD" = true ]]; then
|
|||
|
|
print_header "Cleaning Build Artifacts"
|
|||
|
|
|
|||
|
|
if [[ "$SKIP_BACKEND" = false ]]; then
|
|||
|
|
print_info "Cleaning backend..."
|
|||
|
|
rm -rf "$BACKEND_SRC/target"
|
|||
|
|
print_success "Backend cleaned"
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
if [[ "$SKIP_FRONTEND" = false ]]; then
|
|||
|
|
print_info "Cleaning frontend..."
|
|||
|
|
rm -rf "$FRONTEND_SRC/dist"
|
|||
|
|
rm -rf "$FRONTEND_SRC/node_modules/.vite"
|
|||
|
|
print_success "Frontend cleaned"
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
print_info "Cleaning ISO build directory..."
|
|||
|
|
rm -rf "$BUILD_DIR"
|
|||
|
|
rm -rf "$SCRIPT_DIR/image-recipe/iso-workdir"
|
|||
|
|
rm -rf "$SCRIPT_DIR/image-recipe/results"
|
|||
|
|
print_success "ISO build artifacts cleaned"
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# =============================================================================
|
|||
|
|
# Step 2: Build Backend
|
|||
|
|
# =============================================================================
|
|||
|
|
|
|||
|
|
if [[ "$SKIP_BACKEND" = false ]]; then
|
|||
|
|
print_header "Building Backend (Rust)"
|
|||
|
|
|
|||
|
|
if [[ "$BUILD_MODE" == "local" ]]; then
|
|||
|
|
print_info "Building backend locally..."
|
|||
|
|
cd "$BACKEND_SRC"
|
|||
|
|
|
|||
|
|
if ! check_command cargo; then
|
|||
|
|
print_error "Rust/Cargo not installed. Install from: https://rustup.rs"
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
cargo build --release
|
|||
|
|
|
|||
|
|
# Copy to build directory
|
|||
|
|
mkdir -p "$BUILD_DIR/backend"
|
|||
|
|
cp target/release/archipelago "$BUILD_DIR/backend/"
|
|||
|
|
chmod +x "$BUILD_DIR/backend/archipelago"
|
|||
|
|
|
|||
|
|
print_success "Backend built locally"
|
|||
|
|
|
|||
|
|
elif [[ "$BUILD_MODE" == "remote" ]]; then
|
|||
|
|
print_info "Building backend on remote server: $REMOTE_HOST"
|
|||
|
|
|
|||
|
|
# Sync source code to remote
|
|||
|
|
print_info "Syncing source code to remote..."
|
|||
|
|
ssh "$REMOTE_HOST" "mkdir -p ~/archy-build"
|
|||
|
|
rsync -az --delete \
|
|||
|
|
--exclude 'target/' \
|
|||
|
|
--exclude 'node_modules/' \
|
|||
|
|
--exclude '.git/' \
|
|||
|
|
"$BACKEND_SRC/" "$REMOTE_HOST:~/archy-build/core/archipelago/"
|
|||
|
|
|
|||
|
|
# Build on remote
|
|||
|
|
print_info "Compiling backend on remote..."
|
|||
|
|
ssh "$REMOTE_HOST" "cd ~/archy-build/core/archipelago && cargo build --release"
|
|||
|
|
|
|||
|
|
# Copy binary back
|
|||
|
|
mkdir -p "$BUILD_DIR/backend"
|
|||
|
|
print_info "Copying binary back to local..."
|
|||
|
|
scp "$REMOTE_HOST:~/archy-build/core/archipelago/target/release/archipelago" "$BUILD_DIR/backend/"
|
|||
|
|
chmod +x "$BUILD_DIR/backend/archipelago"
|
|||
|
|
|
|||
|
|
print_success "Backend built on remote server"
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# Verify binary
|
|||
|
|
if [[ ! -f "$BUILD_DIR/backend/archipelago" ]]; then
|
|||
|
|
print_error "Backend binary not found after build!"
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
BINARY_SIZE=$(du -h "$BUILD_DIR/backend/archipelago" | awk '{print $1}')
|
|||
|
|
print_success "Backend binary ready ($BINARY_SIZE)"
|
|||
|
|
else
|
|||
|
|
print_warning "Skipping backend build (using existing binary)"
|
|||
|
|
if [[ ! -f "$BUILD_DIR/backend/archipelago" ]]; then
|
|||
|
|
print_error "No existing backend binary found at $BUILD_DIR/backend/archipelago"
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# =============================================================================
|
|||
|
|
# Step 3: Build Frontend
|
|||
|
|
# =============================================================================
|
|||
|
|
|
|||
|
|
if [[ "$SKIP_FRONTEND" = false ]]; then
|
|||
|
|
print_header "Building Frontend (Vue.js)"
|
|||
|
|
|
|||
|
|
cd "$FRONTEND_SRC"
|
|||
|
|
|
|||
|
|
if ! check_command npm; then
|
|||
|
|
print_error "Node.js/npm not installed. Install from: https://nodejs.org"
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# Install dependencies if needed
|
|||
|
|
if [[ ! -d "node_modules" ]] || [[ "$CLEAN_BUILD" = true ]]; then
|
|||
|
|
print_info "Installing dependencies..."
|
|||
|
|
npm install
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# Build frontend
|
|||
|
|
print_info "Building frontend..."
|
|||
|
|
npm run build
|
|||
|
|
|
|||
|
|
# Copy to build directory
|
|||
|
|
mkdir -p "$BUILD_DIR/frontend"
|
|||
|
|
cp -r dist/* "$BUILD_DIR/frontend/"
|
|||
|
|
|
|||
|
|
print_success "Frontend built"
|
|||
|
|
|
|||
|
|
# Verify dist
|
|||
|
|
if [[ ! -d "$BUILD_DIR/frontend" ]] || [[ -z "$(ls -A "$BUILD_DIR/frontend")" ]]; then
|
|||
|
|
print_error "Frontend build directory is empty!"
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
DIST_SIZE=$(du -sh "$BUILD_DIR/frontend" | awk '{print $1}')
|
|||
|
|
print_success "Frontend assets ready ($DIST_SIZE)"
|
|||
|
|
else
|
|||
|
|
print_warning "Skipping frontend build (using existing dist)"
|
|||
|
|
if [[ ! -d "$BUILD_DIR/frontend" ]] || [[ -z "$(ls -A "$BUILD_DIR/frontend")" ]]; then
|
|||
|
|
print_error "No existing frontend build found at $BUILD_DIR/frontend"
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# =============================================================================
|
|||
|
|
# Step 4: Build ISO
|
|||
|
|
# =============================================================================
|
|||
|
|
|
|||
|
|
print_header "Building Bootable ISO"
|
|||
|
|
|
|||
|
|
# Check if running on remote or need to transfer
|
|||
|
|
if [[ "$BUILD_MODE" == "remote" ]]; then
|
|||
|
|
print_info "Transferring build artifacts to remote server..."
|
|||
|
|
|
|||
|
|
# Sync entire project to remote
|
|||
|
|
ssh "$REMOTE_HOST" "mkdir -p ~/archy"
|
|||
|
|
rsync -az --delete \
|
|||
|
|
--exclude '.git/' \
|
|||
|
|
--exclude 'node_modules/' \
|
|||
|
|
--exclude 'core/target/' \
|
|||
|
|
--exclude 'core/parmanode/' \
|
|||
|
|
"$SCRIPT_DIR/" "$REMOTE_HOST:~/archy/"
|
|||
|
|
|
|||
|
|
print_success "Files synced to remote"
|
|||
|
|
|
|||
|
|
print_info "Running ISO build on remote server..."
|
|||
|
|
ssh -t "$REMOTE_HOST" "cd ~/archy/image-recipe && sudo bash build-debian-iso.sh" || {
|
|||
|
|
print_error "ISO build failed on remote server"
|
|||
|
|
exit 1
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
print_success "ISO built on remote server"
|
|||
|
|
|
|||
|
|
# Copy ISO back to local
|
|||
|
|
ISO_NAME="archipelago-debian-12-x86_64.iso"
|
|||
|
|
print_info "Copying ISO back to local machine..."
|
|||
|
|
mkdir -p "$SCRIPT_DIR/image-recipe/results"
|
|||
|
|
scp "$REMOTE_HOST:~/archy/image-recipe/results/$ISO_NAME" "$SCRIPT_DIR/image-recipe/results/"
|
|||
|
|
|
|||
|
|
ISO_PATH="$SCRIPT_DIR/image-recipe/results/$ISO_NAME"
|
|||
|
|
|
|||
|
|
else
|
|||
|
|
# Local build
|
|||
|
|
print_info "Running ISO build locally..."
|
|||
|
|
cd "$SCRIPT_DIR/image-recipe"
|
|||
|
|
sudo bash build-debian-iso.sh
|
|||
|
|
|
|||
|
|
ISO_PATH="$SCRIPT_DIR/image-recipe/results/archipelago-debian-12-x86_64.iso"
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# =============================================================================
|
|||
|
|
# Step 5: Verify and Report
|
|||
|
|
# =============================================================================
|
|||
|
|
|
|||
|
|
print_header "Build Complete!"
|
|||
|
|
|
|||
|
|
if [[ -f "$ISO_PATH" ]]; then
|
|||
|
|
ISO_SIZE=$(du -h "$ISO_PATH" | awk '{print $1}')
|
|||
|
|
ISO_MD5=$(md5 -q "$ISO_PATH" 2>/dev/null || md5sum "$ISO_PATH" | awk '{print $1}')
|
|||
|
|
|
|||
|
|
echo ""
|
|||
|
|
echo -e "${GREEN}✅ ISO ready for flashing!${NC}"
|
|||
|
|
echo ""
|
|||
|
|
echo -e " 📀 ${BLUE}ISO:${NC} $ISO_PATH"
|
|||
|
|
echo -e " 📏 ${BLUE}Size:${NC} $ISO_SIZE"
|
|||
|
|
echo -e " 🔐 ${BLUE}MD5:${NC} $ISO_MD5"
|
|||
|
|
echo ""
|
|||
|
|
echo -e "${YELLOW}Next steps:${NC}"
|
|||
|
|
echo ""
|
|||
|
|
echo " 1. Insert USB drive"
|
|||
|
|
echo " 2. Find device: ${BLUE}diskutil list${NC}"
|
|||
|
|
echo " 3. Flash ISO:"
|
|||
|
|
echo ""
|
|||
|
|
echo " ${BLUE}cd image-recipe && ./write-usb-dd.sh /dev/diskN${NC}"
|
|||
|
|
echo ""
|
|||
|
|
echo " 4. Boot from USB on target device"
|
|||
|
|
echo ""
|
|||
|
|
|
|||
|
|
# Create a flash script for convenience
|
|||
|
|
cat > "$SCRIPT_DIR/flash-to-usb.sh" <<'FLASH_EOF'
|
|||
|
|
#!/bin/bash
|
|||
|
|
# Quick USB flash script
|
|||
|
|
cd "$(dirname "$0")/image-recipe" && ./write-usb-dd.sh "$@"
|
|||
|
|
FLASH_EOF
|
|||
|
|
chmod +x "$SCRIPT_DIR/flash-to-usb.sh"
|
|||
|
|
|
|||
|
|
print_success "Created convenience script: ./flash-to-usb.sh"
|
|||
|
|
|
|||
|
|
else
|
|||
|
|
print_error "ISO not found at expected location: $ISO_PATH"
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# =============================================================================
|
|||
|
|
# Done!
|
|||
|
|
# =============================================================================
|
|||
|
|
|
|||
|
|
echo ""
|
|||
|
|
echo -e "${GREEN}╔════════════════════════════════════════════════════════╗${NC}"
|
|||
|
|
echo -e "${GREEN}║ 🎉 Build Complete - Ready to Flash! ║${NC}"
|
|||
|
|
echo -e "${GREEN}╚════════════════════════════════════════════════════════╝${NC}"
|
|||
|
|
echo ""
|