v0.1: QEMU verifier CI (PR #7) #3
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: QEMU verifier | |
| # SPEC.md §10.2: run the sudo-gated integration tests under two kernel | |
| # versions — 5.15 (EFG-parity) and 6.6 LTS (≥5.18 for | |
| # BPF_PROG_TEST_RUN_XDP_LIVE; the host CI job already covers whichever | |
| # kernel ubuntu-latest runners ship with, so this matrix targets | |
| # explicit EFG-parity + a modern LTS). | |
| on: | |
| pull_request: | |
| push: | |
| branches: [main] | |
| env: | |
| CARGO_TERM_COLOR: always | |
| RUST_BACKTRACE: short | |
| # Pin versions so adding a matrix dimension doesn't drift toolchains. | |
| RUST_STABLE: "1.95.0" | |
| RUST_NIGHTLY: "nightly-2026-04-14" | |
| BPF_LINKER_VERSION: "0.10.3" | |
| jobs: | |
| qemu: | |
| name: qemu (kernel ${{ matrix.kernel_tag }}) | |
| runs-on: ubuntu-latest | |
| env: | |
| PACKETFRAME_BPF_REQUIRED: "1" | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| # Canonical's mainline PPA hosts rebuilds of upstream releases. | |
| # We discover the actual .deb URL at runtime (build timestamps | |
| # vary per version) from the directory listing. | |
| kernel_tag: ["v5.15", "v6.6"] | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Install Rust stable + nightly (for BPF) | |
| run: | | |
| rustup install ${RUST_STABLE} --profile minimal | |
| rustup default ${RUST_STABLE} | |
| rustup install ${RUST_NIGHTLY} --profile minimal | |
| rustup component add --toolchain ${RUST_NIGHTLY} rust-src llvm-tools-preview | |
| - name: Cache cargo + BPF target | |
| uses: actions/cache@v5 | |
| with: | |
| path: | | |
| ~/.cargo/bin/ | |
| ~/.cargo/registry/index/ | |
| ~/.cargo/registry/cache/ | |
| ~/.cargo/git/db/ | |
| target/ | |
| crates/modules/fast-path/bpf/target/ | |
| key: ${{ runner.os }}-cargo-qemu-${{ matrix.kernel_tag }}-${{ hashFiles('**/Cargo.lock', 'crates/modules/fast-path/bpf/Cargo.toml') }} | |
| restore-keys: | | |
| ${{ runner.os }}-cargo-qemu-${{ matrix.kernel_tag }}- | |
| ${{ runner.os }}-cargo-qemu- | |
| ${{ runner.os }}-cargo-check- | |
| - name: Install bpf-linker | |
| run: | | |
| if ! command -v bpf-linker >/dev/null 2>&1 || \ | |
| [ "$(bpf-linker --version 2>/dev/null | awk '{print $2}')" != "${BPF_LINKER_VERSION}" ]; then | |
| cargo install --locked --force bpf-linker --version ${BPF_LINKER_VERSION} | |
| fi | |
| - name: Install QEMU + virtme | |
| run: | | |
| set -eux | |
| sudo apt-get update | |
| # virtme-ng's `--run` takes a kernel *build directory*, not a | |
| # pre-built vmlinuz path. Classic `virtme-run` has the stable | |
| # `--kimg <path>` flag that accepts a raw vmlinuz; install that | |
| # via pip (Ubuntu 24.04 dropped the `virtme` apt package). | |
| sudo apt-get install -y qemu-system-x86 busybox-static python3-pip python3-virtualenv | |
| sudo pip3 install --break-system-packages virtme | |
| which virtme-run | |
| - name: Fetch kernel image | |
| run: | | |
| set -eux | |
| # Discover the .deb URL from the PPA directory listing — | |
| # Canonical's mainline builds have timestamped filenames that | |
| # change per revision, so hardcoding the URL is brittle. | |
| BASE="https://kernel.ubuntu.com/mainline/${{ matrix.kernel_tag }}/amd64/" | |
| DEB=$(curl -fsSL "${BASE}" \ | |
| | grep -oE 'linux-image-unsigned-[0-9][^"]*generic_[^"]*_amd64\.deb' \ | |
| | sort -u \ | |
| | head -1) | |
| test -n "${DEB}" | |
| echo "Fetching ${BASE}${DEB}" | |
| curl -fsSL --retry 3 -o /tmp/kernel.deb "${BASE}${DEB}" | |
| dpkg-deb -x /tmp/kernel.deb /tmp/kernel-root | |
| KERNEL=$(find /tmp/kernel-root -name 'vmlinuz-*' | head -1) | |
| test -n "${KERNEL}" | |
| ls -la "${KERNEL}" | |
| file "${KERNEL}" | |
| echo "KERNEL_PATH=${KERNEL}" >> "${GITHUB_ENV}" | |
| - name: Build integration tests | |
| run: | | |
| # Build so the test binaries are ready to exec inside the VM. | |
| # `--no-run` produces the ELFs without executing them on the | |
| # host kernel. | |
| cargo test -p packetframe-fast-path --tests --no-run | |
| - name: Run integration tests in QEMU | |
| timeout-minutes: 15 | |
| run: | | |
| set -eux | |
| # virtme-run boots the target kernel via QEMU with the host | |
| # rootfs mounted 9p. `--script-sh` runs a shell command and | |
| # exits; stdout/stderr are forwarded. `--pwd` preserves the | |
| # repo path so cargo resolves normally. | |
| # | |
| # `--force-initramfs` makes virtme build an initramfs rather | |
| # than rely on the host's (the kernel .deb we downloaded has | |
| # no matching initrd). `--qemu-opts` forces TCG because GHA | |
| # runners may not expose /dev/kvm. | |
| virtme-run \ | |
| --kimg "${KERNEL_PATH}" \ | |
| --memory 1024M \ | |
| --pwd \ | |
| --force-initramfs \ | |
| --qemu-opts -machine accel=tcg \ | |
| --script-sh 'set -eux; uname -a; cargo test -p packetframe-fast-path --tests -- --ignored --nocapture' |