#!/usr/bin/env bash # build-release - Build and distribute the archangel ISO # # Usage: # ./scripts/build-release # Full build, sanity test, and distribute # ./scripts/build-release --full-test # Full build with comprehensive install tests # ./scripts/build-release --skip-build # Skip build, just distribute existing ISO # ./scripts/build-release --skip-test # Skip all testing # # Distribution targets (configurable via environment variables): # - $LOCAL_ISO_DIR (default: ~/archangel-isos) # - $ARCHSETUP_INBOX (notification for test VM rebuild, if set) # - $DIST_REMOTE_HOST:$DIST_REMOTE_PATH (if set and reachable) set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_DIR="$(dirname "$SCRIPT_DIR")" # Get actual user (not root when running with sudo) if [[ -n "${SUDO_USER:-}" ]]; then REAL_USER="$SUDO_USER" REAL_HOME=$(getent passwd "$SUDO_USER" | cut -d: -f6) else REAL_USER="$USER" REAL_HOME="$HOME" fi # Distribution targets (override via environment variables) DIST_REMOTE_HOST="${DIST_REMOTE_HOST:-}" DIST_REMOTE_PATH="${DIST_REMOTE_PATH:-/mnt/isos}" LOCAL_ISO_DIR="${LOCAL_ISO_DIR:-$REAL_HOME/archangel-isos}" ARCHSETUP_INBOX="${ARCHSETUP_INBOX:-}" # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' CYAN='\033[0;36m' NC='\033[0m' info() { echo -e "${GREEN}[INFO]${NC} $1"; } warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; } step() { echo -e "\n${CYAN}=== $1 ===${NC}\n"; } # Parse arguments SKIP_BUILD=false SKIP_TEST=false FULL_TEST=false while [[ $# -gt 0 ]]; do case $1 in --skip-build) SKIP_BUILD=true; shift ;; --skip-test) SKIP_TEST=true; shift ;; --full-test) FULL_TEST=true; shift ;; -h|--help) echo "Usage: $0 [--skip-build] [--skip-test] [--full-test]" echo "" echo "Options:" echo " --skip-build Skip ISO build, distribute existing ISO" echo " --skip-test Skip QEMU sanity test" echo " --full-test Run comprehensive install tests (single, mirror, raidz1)" exit 0 ;; *) error "Unknown option: $1" ;; esac done # Distribution status tracking DIST_REMOTE_SUCCESS=false LOCAL_SUCCESS=false # Check root for build check_root() { if [[ $EUID -ne 0 ]]; then error "This script must be run as root (for build operations)" fi } # Find the latest ISO find_iso() { ISO_FILE=$(ls -t "$PROJECT_DIR/out/"*.iso 2>/dev/null | head -1) if [[ -z "$ISO_FILE" ]]; then error "No ISO found in $PROJECT_DIR/out/" fi ISO_NAME=$(basename "$ISO_FILE") info "Found ISO: $ISO_NAME" info "Size: $(du -h "$ISO_FILE" | cut -f1)" } # Build the ISO build_iso() { step "Building ISO" cd "$PROJECT_DIR" ./build.sh find_iso } # Run sanity test in QEMU (automated) sanity_test() { step "Sanity Test (Automated)" if ! "$SCRIPT_DIR/sanity-test.sh"; then error "Sanity test failed!" exit 1 fi info "Sanity test passed!" } # Run full installation tests (automated) full_test() { step "Full Installation Tests" if ! "$SCRIPT_DIR/full-test.sh"; then error "Full installation test failed!" exit 1 fi info "All installation tests passed!" } # Distribute to remote host via SCP distribute_remote() { step "Distributing to Remote Host" # Skip if no host configured if [[ -z "$DIST_REMOTE_HOST" ]]; then info "DIST_REMOTE_HOST not set, skipping" return 0 fi # Check if reachable if ! ping -c 1 -W 2 "$DIST_REMOTE_HOST" &>/dev/null; then warn "Remote host ($DIST_REMOTE_HOST) not reachable, skipping" return 0 fi info "Remote host is reachable" # Run SCP as the real user (not root) to use their SSH keys local scp_cmd="scp" if [[ -n "${SUDO_USER:-}" ]]; then scp_cmd="sudo -u $SUDO_USER scp" fi info "Copying to $DIST_REMOTE_HOST:$DIST_REMOTE_PATH/" if $scp_cmd "$ISO_FILE" "$REAL_USER@$DIST_REMOTE_HOST:$DIST_REMOTE_PATH/"; then info "Done: $DIST_REMOTE_HOST:$DIST_REMOTE_PATH/$ISO_NAME" DIST_REMOTE_SUCCESS=true else warn "Failed to copy to remote host (SSH key issue?), skipping" return 0 fi } # Distribute locally distribute_local() { step "Distributing Locally" mkdir -p "$LOCAL_ISO_DIR" info "Copying to $LOCAL_ISO_DIR/" cp "$ISO_FILE" "$LOCAL_ISO_DIR/" info "Done: $LOCAL_ISO_DIR/$ISO_NAME" LOCAL_SUCCESS=true # Notify archsetup project that a new ISO is available if [[ -n "$ARCHSETUP_INBOX" && -d "$ARCHSETUP_INBOX" ]]; then cat > "$ARCHSETUP_INBOX/rebuild-test-vm.txt" << EOF New archangel ISO available: $ISO_NAME Location: $LOCAL_ISO_DIR/ Rebuild the base test VM from this ISO to pick up the new kernel. EOF info "Notified archsetup inbox" fi } # Summary show_summary() { step "Distribution Complete" echo "ISO: $ISO_NAME" echo "" echo "Distributed to:" $LOCAL_SUCCESS && echo " - $LOCAL_ISO_DIR/" $DIST_REMOTE_SUCCESS && echo " - $DIST_REMOTE_HOST:$DIST_REMOTE_PATH/" $DIST_REMOTE_SUCCESS || [[ -z "$DIST_REMOTE_HOST" ]] || echo " - Remote ($DIST_REMOTE_HOST) not reachable, skipped" } # Main main() { check_root if $SKIP_BUILD; then step "Skipping Build" find_iso else build_iso fi if $FULL_TEST; then full_test elif ! $SKIP_TEST; then sanity_test else step "Skipping Tests" fi distribute_local distribute_remote show_summary } main "$@"