name: QEMU Boot Test on: push: branches: [ main, copilot/* ] pull_request: branches: [ main ] workflow_dispatch: jobs: qemu-boot-test: runs-on: ubuntu-latest permissions: contents: read actions: write # For uploading artifacts steps: - name: Checkout repository uses: actions/checkout@v4 - name: Install dependencies run: | set -e # Exit on any error sudo apt-get update sudo apt-get install -y \ build-essential \ clang \ cmake \ nasm \ qemu-system-x86 \ ovmf \ mtools \ xorriso \ imagemagick \ python3 \ python3-pip # Install Conan pip3 install conan # Configure Conan conan profile detect --force - name: Install Conan dependencies run: | conan install . --build=missing - name: Configure CMake run: | mkdir -p build cd build CC=clang CXX=clang++ cmake .. -DCMAKE_TOOLCHAIN_FILE=../build/Release/generators/conan_toolchain.cmake - name: Build bootloader and kernel run: | cd build cmake --build . - name: Create bootable image run: | cd build cmake --build . --target image - name: Start QEMU and capture screenshot run: | set -e # Exit on any error # Start Xvfb for headless screenshot capture export DISPLAY=:99 Xvfb :99 -screen 0 1920x1080x24 & XVFB_PID=$! sleep 2 # Verify disk image exists (created by cmake build) if [ ! -f build/build/metalos.img ]; then echo "Error: build/build/metalos.img not found!" exit 1 fi # Create directory for logs mkdir -p build/logs # Start QEMU in the background with a timeout timeout 30s qemu-system-x86_64 \ -bios /usr/share/OVMF/OVMF_CODE.fd \ -drive format=raw,file=build/build/metalos.img \ -m 512M \ -display gtk \ -serial file:build/logs/serial.log \ -no-reboot & QEMU_PID=$! # Wait for boot (adjust timing as needed) sleep 10 # Take screenshot using ImageMagick (optional - don't fail if this doesn't work) # Using subshell to prevent 'set -e' from affecting this optional step { import -window root build/logs/qemu-screenshot.png; } || echo "Screenshot capture failed (non-fatal)" # Gracefully stop QEMU (don't fail if already stopped) kill $QEMU_PID 2>/dev/null || true wait $QEMU_PID 2>/dev/null || true # Stop Xvfb (don't fail if already stopped) kill $XVFB_PID 2>/dev/null || true echo "Boot test completed" - name: Show serial output if: always() run: | if [ -f build/logs/serial.log ]; then echo "=== QEMU Serial Output ===" cat build/logs/serial.log else echo "No serial output captured" fi - name: Upload screenshot if: always() uses: actions/upload-artifact@v4 with: name: qemu-screenshot path: build/logs/qemu-screenshot.png if-no-files-found: warn - name: Upload serial log if: always() uses: actions/upload-artifact@v4 with: name: serial-log path: build/logs/serial.log if-no-files-found: warn - name: Upload built disk image if: always() uses: actions/upload-artifact@v4 with: name: metalos-disk-image path: build/build/metalos.img if-no-files-found: warn