diff options
| author | Craig Jennings <c@cjennings.net> | 2025-11-13 23:26:21 -0600 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2025-11-13 23:26:21 -0600 |
| commit | 2e10a8856d0bdd4c8f77c53320221ad1b8deaa13 (patch) | |
| tree | 95832c3b74fc523fe9d8319e25c5ea5bf1d40433 /scripts/testing/run-test.sh | |
| parent | fd9cce59993556400b635256d712a65d87f5d72d (diff) | |
fix(archsetup): implement critical bug fixes and test improvements
This commit addresses several high-priority bugs and enhances the testing infrastructure:
**Bug Fixes:**
1. Add root permission check at script start to fail fast with clear error message
2. Disable debug package installation by adding --nodebug flag to all yay calls
3. Replace unsafe `git pull --force` with safe rm + fresh clone to prevent data loss
4. Add geoclue package with correct systemd service configuration for geolocation
5. Add completion marker for reliable automated test detection
**Testing Infrastructure:**
- Add comprehensive VM-based testing framework in scripts/testing/
- Fix test script pgrep infinite loop using grep bracket self-exclusion pattern
- Add network diagnostics and pre-flight checks
- Support snapshot-based testing for reproducible test runs
**Package Management:**
- Remove anki (build hangs 98+ minutes)
- Remove adwaita-color-schemes (CMake build issues)
Test Results: 0 errors, 1,363 packages installed in 40 minutes
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Diffstat (limited to 'scripts/testing/run-test.sh')
| -rwxr-xr-x | scripts/testing/run-test.sh | 382 |
1 files changed, 382 insertions, 0 deletions
diff --git a/scripts/testing/run-test.sh b/scripts/testing/run-test.sh new file mode 100755 index 0000000..4bcb55b --- /dev/null +++ b/scripts/testing/run-test.sh @@ -0,0 +1,382 @@ +#!/bin/bash +# Run archsetup test in a VM using snapshots +# Author: Craig Jennings <craigmartinjennings@gmail.com> +# License: GNU GPLv3 +# +# This script: +# 1. Reverts base VM to clean snapshot +# 2. Starts the base VM +# 3. Transfers archsetup and dotfiles +# 4. Executes archsetup in the VM +# 5. Captures logs and validates results +# 6. Generates test report +# 7. Reverts to clean snapshot for next run + +set -e + +# Get script directory +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" + +# Source utilities +source "$SCRIPT_DIR/lib/logging.sh" +source "$SCRIPT_DIR/lib/vm-utils.sh" +source "$SCRIPT_DIR/lib/network-diagnostics.sh" + +# Parse arguments +KEEP_VM=false +ARCHSETUP_SCRIPT="$PROJECT_ROOT/archsetup" +SNAPSHOT_NAME="clean-install" +SKIP_SLOW_PACKAGES=false + +while [[ $# -gt 0 ]]; do + case $1 in + --keep) + KEEP_VM=true + shift + ;; + --script) + ARCHSETUP_SCRIPT="$2" + shift 2 + ;; + --snapshot) + SNAPSHOT_NAME="$2" + shift 2 + ;; + --skip-slow-packages) + SKIP_SLOW_PACKAGES=true + shift + ;; + *) + echo "Usage: $0 [--keep] [--script /path/to/archsetup] [--snapshot name] [--skip-slow-packages]" + echo " --keep Keep VM in post-test state (for debugging)" + echo " --script Specify custom archsetup script to test" + echo " --snapshot Snapshot name to revert to (default: clean-install)" + echo " --skip-slow-packages Skip slow packages (texlive-meta, topgrade) for faster testing" + exit 1 + ;; + esac +done + +# Configuration +TIMESTAMP=$(date +'%Y%m%d-%H%M%S') +VM_NAME="archsetup-base" +TEST_RESULTS_DIR="$PROJECT_ROOT/test-results/$TIMESTAMP" +ROOT_PASSWORD="archsetup" + +# Initialize logging +mkdir -p "$TEST_RESULTS_DIR" +LOGFILE="$TEST_RESULTS_DIR/test.log" +init_logging "$LOGFILE" + +section "ArchSetup Test Run: $TIMESTAMP" + +# Verify archsetup script exists +if [ ! -f "$ARCHSETUP_SCRIPT" ]; then + fatal "ArchSetup script not found: $ARCHSETUP_SCRIPT" +fi + +# Check if VM exists +if ! vm_exists "$VM_NAME"; then + fatal "Base VM not found: $VM_NAME" + info "Create it first: ./scripts/testing/create-base-vm.sh" +fi + +# Check if snapshot exists +section "Preparing Test Environment" + +step "Checking for snapshot: $SNAPSHOT_NAME" +if ! virsh --connect "$LIBVIRT_URI" snapshot-list "$VM_NAME" --name 2>/dev/null | grep -q "^$SNAPSHOT_NAME$"; then + fatal "Snapshot '$SNAPSHOT_NAME' not found on VM $VM_NAME" + info "Available snapshots:" + virsh --connect "$LIBVIRT_URI" snapshot-list "$VM_NAME" 2>/dev/null || info " (none)" + info "" + info "Create snapshot with:" + info " virsh snapshot-create-as $VM_NAME $SNAPSHOT_NAME --description 'Clean Arch install'" +fi +success "Snapshot $SNAPSHOT_NAME exists" + +# Shut down VM if running +if vm_is_running "$VM_NAME"; then + warn "VM $VM_NAME is currently running - shutting down for snapshot revert" + stop_vm "$VM_NAME" +fi + +# Revert to clean snapshot +step "Reverting to snapshot: $SNAPSHOT_NAME" +if restore_snapshot "$VM_NAME" "$SNAPSHOT_NAME"; then + success "Reverted to clean state" +else + fatal "Failed to revert snapshot" +fi + +# Start VM +start_timer "boot" +step "Starting VM and waiting for SSH..." +if ! start_vm "$VM_NAME"; then + fatal "Failed to start VM" +fi + +sleep 10 # Give VM time to boot + +# Get VM IP address +VM_IP="" +for i in {1..30}; do + VM_IP=$(get_vm_ip "$VM_NAME" 2>/dev/null || true) + if [ -n "$VM_IP" ]; then + break + fi + sleep 2 +done + +if [ -z "$VM_IP" ]; then + error "Could not get VM IP address" + info "VM may not have booted correctly" + fatal "VM boot failed" +fi + +success "VM is running at $VM_IP" +stop_timer "boot" + +# Wait for SSH +step "Waiting for SSH to become available..." +for i in {1..60}; do + if sshpass -p "$ROOT_PASSWORD" ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \ + -o ConnectTimeout=2 "root@$VM_IP" "echo connected" &>/dev/null; then + break + fi + sleep 2 +done + +success "SSH is available" + +# Run network diagnostics +if ! run_network_diagnostics "$VM_IP"; then + fatal "Network diagnostics failed - aborting test" +fi + +# Transfer files to VM (simulating git clone) +section "Simulating Git Clone" + +step "Creating shallow git clone on VM" +info "This simulates: git clone --depth 1 <repo> /home/cjennings/code/archsetup" + +# Create a temporary git bundle from current repo +BUNDLE_FILE=$(mktemp) +git bundle create "$BUNDLE_FILE" HEAD >> "$LOGFILE" 2>&1 + +# Transfer bundle and extract on VM +sshpass -p "$ROOT_PASSWORD" ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \ + "root@$VM_IP" "rm -rf /tmp/archsetup-test && mkdir -p /tmp/archsetup-test" >> "$LOGFILE" 2>&1 + +sshpass -p "$ROOT_PASSWORD" scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \ + "$BUNDLE_FILE" "root@$VM_IP:/tmp/archsetup.bundle" >> "$LOGFILE" 2>&1 + +# Clone from bundle on VM (simulates git clone) +sshpass -p "$ROOT_PASSWORD" ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \ + "root@$VM_IP" "cd /tmp && git clone --depth 1 /tmp/archsetup.bundle archsetup-test && rm /tmp/archsetup.bundle" >> "$LOGFILE" 2>&1 + +rm -f "$BUNDLE_FILE" +success "Repository cloned to VM (simulating git clone --depth 1)" + +# Execute archsetup +section "Executing ArchSetup" + +start_timer "archsetup" +step "Starting archsetup script in detached session on VM..." +info "This will take 30-60 minutes depending on network speed" +info "Log file: $LOGFILE" + +# Start archsetup in a detached session on the VM (resilient to SSH disconnections) +REMOTE_LOG="/tmp/archsetup-test/archsetup-output.log" +ARCHSETUP_ARGS="" +if $SKIP_SLOW_PACKAGES; then + ARCHSETUP_ARGS="--skip-slow-packages" + info "Running archsetup with --skip-slow-packages flag" +fi +sshpass -p "$ROOT_PASSWORD" ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \ + "root@$VM_IP" "cd /tmp/archsetup-test && nohup bash archsetup $ARCHSETUP_ARGS > $REMOTE_LOG 2>&1 & echo \$!" \ + >> "$LOGFILE" 2>&1 + +if [ $? -ne 0 ]; then + fatal "Failed to start archsetup on VM" +fi + +success "ArchSetup started in background on VM" + +# Poll for completion +step "Monitoring archsetup progress (polling every 30 seconds)..." +POLL_COUNT=0 +MAX_POLLS=180 # 90 minutes max (180 * 30 seconds) + +while [ $POLL_COUNT -lt $MAX_POLLS ]; do + # Check if archsetup process is still running + # Use ps to avoid pgrep matching its own SSH command + if sshpass -p "$ROOT_PASSWORD" ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \ + "root@$VM_IP" "ps aux | grep '[b]ash archsetup' > /dev/null" 2>/dev/null; then + # Still running, wait and continue + sleep 30 + POLL_COUNT=$((POLL_COUNT + 1)) + + # Show progress every 5 minutes + if [ $((POLL_COUNT % 10)) -eq 0 ]; then + ELAPSED_MINS=$((POLL_COUNT / 2)) + info "Still running... ($ELAPSED_MINS minutes elapsed)" + fi + else + # Process finished + break + fi +done + +if [ $POLL_COUNT -ge $MAX_POLLS ]; then + error "ArchSetup timed out after 90 minutes" + ARCHSETUP_EXIT_CODE=124 +else + # Get exit code from the remote log + step "Retrieving archsetup exit status..." + ARCHSETUP_EXIT_CODE=$(sshpass -p "$ROOT_PASSWORD" ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \ + "root@$VM_IP" "grep -q 'ARCHSETUP_EXECUTION_COMPLETE' /var/log/archsetup-*.log 2>/dev/null && echo 0 || echo 1" 2>/dev/null) + + if [ "$ARCHSETUP_EXIT_CODE" = "0" ]; then + success "ArchSetup completed successfully" + else + error "ArchSetup may have encountered errors (check logs)" + fi +fi + +# Copy the remote output log +step "Retrieving archsetup output from VM..." +sshpass -p "$ROOT_PASSWORD" scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \ + "root@$VM_IP:$REMOTE_LOG" "$TEST_RESULTS_DIR/archsetup-output.log" 2>> "$LOGFILE" || \ + warn "Could not copy remote output log" + +# Append remote output to main test log +if [ -f "$TEST_RESULTS_DIR/archsetup-output.log" ]; then + cat "$TEST_RESULTS_DIR/archsetup-output.log" >> "$LOGFILE" +fi + +stop_timer "archsetup" + +# Capture logs and artifacts from VM +section "Capturing Test Artifacts" + +step "Copying archsetup log from VM" +sshpass -p "$ROOT_PASSWORD" scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \ + "root@$VM_IP:/var/log/archsetup-*.log" "$TEST_RESULTS_DIR/" 2>> "$LOGFILE" || \ + warn "Could not copy archsetup log" + +step "Copying package lists from VM" +sshpass -p "$ROOT_PASSWORD" scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \ + "root@$VM_IP:/root/.local/src/archsetup-*.txt" "$TEST_RESULTS_DIR/" 2>> "$LOGFILE" || \ + warn "Could not copy package lists" + +# Run validation +section "Validating Installation" + +VALIDATION_PASSED=true + +# Check if user was created +step "Checking if user 'cjennings' was created" +if sshpass -p "$ROOT_PASSWORD" ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \ + "root@$VM_IP" "id cjennings" &>> "$LOGFILE"; then + success "User cjennings exists" +else + error "User cjennings not found" + VALIDATION_PASSED=false +fi + +# Check if dotfiles were stowed +step "Checking if dotfiles are stowed" +if sshpass -p "$ROOT_PASSWORD" ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \ + "root@$VM_IP" "test -L /home/cjennings/.profile" &>> "$LOGFILE"; then + success "Dotfiles appear to be stowed" +else + warn "Dotfiles may not be properly stowed" + VALIDATION_PASSED=false +fi + +# Check if yay is installed +step "Checking if yay (AUR helper) is installed" +if sshpass -p "$ROOT_PASSWORD" ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \ + "root@$VM_IP" "/usr/bin/which yay" &>> "$LOGFILE"; then + success "yay is installed" +else + error "yay not found" + VALIDATION_PASSED=false +fi + +# Check if DWM was built +step "Checking if DWM is installed" +if sshpass -p "$ROOT_PASSWORD" ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \ + "root@$VM_IP" "test -f /usr/local/bin/dwm" &>> "$LOGFILE"; then + success "DWM is installed" +else + error "DWM not found" + VALIDATION_PASSED=false +fi + +# Generate test report +section "Generating Test Report" + +REPORT_FILE="$TEST_RESULTS_DIR/test-report.txt" +cat > "$REPORT_FILE" << EOFREPORT +======================================== +ArchSetup Test Report +======================================== + +Test ID: $TIMESTAMP +Date: $(date +'%Y-%m-%d %H:%M:%S') +Test Method: Snapshot-based + +VM Configuration: + Name: $VM_NAME + IP: $VM_IP + Snapshot: $SNAPSHOT_NAME + +Results: + ArchSetup Exit Code: $ARCHSETUP_EXIT_CODE + Validation: $(if $VALIDATION_PASSED; then echo "PASSED"; else echo "FAILED"; fi) + +Artifacts: + Log file: $LOGFILE + Report: $REPORT_FILE + Results: $TEST_RESULTS_DIR/ + +EOFREPORT + +info "Test report saved: $REPORT_FILE" + +# Cleanup or keep VM +section "Cleanup" + +if $KEEP_VM; then + info "VM is still running in post-test state (--keep flag was used)" + info "Connect with:" + info " Console: virsh console $VM_NAME" + info " SSH: ssh root@$VM_IP" + info "" + info "To revert to clean state when done:" + info " virsh shutdown $VM_NAME" + info " virsh snapshot-revert $VM_NAME $SNAPSHOT_NAME" +else + step "Shutting down VM and reverting to clean snapshot" + stop_vm "$VM_NAME" + if restore_snapshot "$VM_NAME" "$SNAPSHOT_NAME"; then + success "VM reverted to clean state" + else + warn "Failed to revert snapshot - VM may be in modified state" + fi +fi + +# Final summary +section "Test Complete" + +if [ $ARCHSETUP_EXIT_CODE -eq 0 ] && $VALIDATION_PASSED; then + success "TEST PASSED" + exit 0 +else + error "TEST FAILED" + info "Check logs in: $TEST_RESULTS_DIR" + exit 1 +fi |
