From 1b080d4097cecdd418176adabf32ea92f2664de2 Mon Sep 17 00:00:00 2001 From: "trop[bot]" <37223003+trop[bot]@users.noreply.github.com> Date: Thu, 19 Mar 2026 09:31:47 -0400 Subject: [PATCH] ci: test linux 64k (#50358) Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com> Co-authored-by: John Kleinschmidt --- .github/workflows/build.yml | 12 +++ .../pipeline-segment-electron-test-64k.yml | 67 ++++++++++++ script/qemu-init.sh | 44 ++++++++ script/run-qemu-64k.sh | 100 ++++++++++++++++++ 4 files changed, 223 insertions(+) create mode 100644 .github/workflows/pipeline-segment-electron-test-64k.yml create mode 100755 script/qemu-init.sh create mode 100755 script/run-qemu-64k.sh diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 42a369454b..a2b72f30aa 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -365,6 +365,18 @@ jobs: generate-symbols: false upload-to-storage: '0' secrets: inherit + + test-linux-arm64-64k: + uses: ./.github/workflows/pipeline-segment-electron-test-64k.yml + permissions: + contents: read + issues: read + pull-requests: read + needs: [checkout-linux, linux-arm64] + with: + test-runs-on: ubuntu-22.04-arm + test-container: '{"image":"ghcr.io/electron/test:arm64v8-${{ needs.checkout-linux.outputs.build-image-sha }}","options":"--user root --privileged --init"}' + secrets: inherit windows-x64: permissions: diff --git a/.github/workflows/pipeline-segment-electron-test-64k.yml b/.github/workflows/pipeline-segment-electron-test-64k.yml new file mode 100644 index 0000000000..58688f3c4b --- /dev/null +++ b/.github/workflows/pipeline-segment-electron-test-64k.yml @@ -0,0 +1,67 @@ +name: Pipeline Segment - Electron Test on Linux ARM64 64k + +on: + workflow_call: + inputs: + test-runs-on: + type: string + description: 'What host to run the tests on' + required: true + test-container: + type: string + description: 'JSON container information for aks runs-on' + required: false + default: '{"image":null}' + +concurrency: + group: electron-test-linux-64k-${{ github.ref_protected == true && github.run_id || github.ref }} + cancel-in-progress: ${{ github.ref_protected != true }} + +permissions: {} + +env: + ELECTRON_OUT_DIR: Default + +jobs: + test-linux-arm64-64k: + env: + BUILD_TYPE: linux + TARGET_ARCH: arm64 + defaults: + run: + shell: bash + runs-on: ${{ inputs.test-runs-on }} + permissions: + contents: read + issues: read + pull-requests: read + steps: + - name: Checkout Electron + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + with: + path: src/electron + fetch-depth: 0 + ref: ${{ github.event.pull_request.head.sha }} + - name: Download Generated Artifacts + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 + with: + name: generated_artifacts_linux_arm64 + path: ./generated_artifacts_linux_arm64 + - name: Restore Generated Artifacts + run: ./src/electron/script/actions/restore-artifacts.sh + - name: Unzip Dist + run: | + cd src/out/Default + unzip -:o dist.zip + + - name: Run Electron Tests in QEMU 64k Container + shell: bash + env: + MOCHA_REPORTER: mocha-multi-reporters + MOCHA_MULTI_REPORTERS: mocha-junit-reporter, tap + ELECTRON_DISABLE_SECURITY_WARNINGS: 1 + DISPLAY: ':99.0' + run: | + container=$(echo '${{ inputs.test-container }}' | jq -r '.image') + src/electron/script/run-qemu-64k.sh --container $container --testfiles "`pwd`/src" + \ No newline at end of file diff --git a/script/qemu-init.sh b/script/qemu-init.sh new file mode 100755 index 0000000000..78592e3d49 --- /dev/null +++ b/script/qemu-init.sh @@ -0,0 +1,44 @@ +#!/bin/sh + +echo "Mounting essential filesystems" +mount -t proc proc /proc +mount -t sysfs sys /sys +mkdir -p /dev/pts +mount -t devpts devpts /dev/pts +mkdir -p /dev/shm +mount -t tmpfs tmpfs /dev/shm +mount -t tmpfs tmpfs /tmp +chmod 1777 /tmp +mount -t tmpfs tmpfs /run +mkdir -p /run/dbus +mkdir -p /run/user/0 +chmod 700 /run/user/0 +mount -t tmpfs tmpfs /var/tmp + +echo "Setting up hostname and machine-id for D-Bus" +echo "electron-test" > /etc/hostname +hostname electron-test +cat /proc/sys/kernel/random/uuid | tr -d '-' > /etc/machine-id + +echo "Setting system clock" +date -s "$(cat /host-time)" + + +export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +export XDG_RUNTIME_DIR=/run/user/0 + +echo "Starting entrypoint" +echo "System: $(uname -s) $(uname -r) $(uname -m), page size: $(getconf PAGESIZE) bytes" +sudo chown -R builduser:builduser /home/builduser +ls -la /home/builduser/src/out/Default/electron +cd /home/builduser/src +runuser -u builduser -- xvfb-run out/Default/electron electron/spec/fixtures/apps/open-new-window-from-link +EXIT_CODE=$? +echo "Test execution finished with exit code $EXIT_CODE" +echo $EXIT_CODE > /exit-code +sync + +echo "Powering off" +# poweroff -f bypasses the init system (this script IS pid 1) and +# directly invokes the reboot() syscall, causing QEMU to exit immediately. +poweroff -f diff --git a/script/run-qemu-64k.sh b/script/run-qemu-64k.sh new file mode 100755 index 0000000000..2ed2fc5732 --- /dev/null +++ b/script/run-qemu-64k.sh @@ -0,0 +1,100 @@ +#!/bin/sh +set -e + +CONTAINER="" +TESTFILES="" +ARGS="" + +while [ $# -gt 0 ]; do + case "$1" in + --container) CONTAINER="$2"; shift 2 ;; + --testfiles) TESTFILES="$2"; shift 2 ;; + --) shift; ARGS="$*"; break ;; + *) echo "Unknown option: $1"; exit 1 ;; + esac +done + +if [ -z "$CONTAINER" ]; then + echo "Usage: $0 --container CONTAINER [-- ARGS...]" + exit 1 +fi + +echo "Installing QEMU system emulation and tools" +sudo apt-get update && sudo apt-get install -y qemu-system-arm binutils + +KERNEL_URL="http://ports.ubuntu.com/ubuntu-ports/pool/main/l/linux/linux-image-unsigned-6.8.0-90-generic-64k_6.8.0-90.91_arm64.deb" +KERNEL_DIR=$(mktemp -d) +ROOTFS_DIR=$(mktemp -d) + +# Download kernel and export container filesystem in parallel +echo "Downloading kernel and exporting container filesystem in parallel" +curl -fL "$KERNEL_URL" -o "$KERNEL_DIR/kernel.deb" & +CURL_PID=$! + +CONTAINER_ID=$(docker create --platform linux/arm64 "$CONTAINER") +docker export "$CONTAINER_ID" | sudo tar -xf - -C "$ROOTFS_DIR" +docker rm -f "$CONTAINER_ID" + +echo "Removing container image to free disk space" +docker rmi "$CONTAINER" || true +docker system prune -f || true + +wait $CURL_PID + +echo "Extracting kernel" +(cd "$KERNEL_DIR" && ar x kernel.deb && tar xf data.tar*) +VMLINUZ="$KERNEL_DIR/boot/vmlinuz-6.8.0-90-generic-64k" +if [ ! -f "$VMLINUZ" ]; then + echo "Error: Could not find kernel at $VMLINUZ" + exit 1 +fi + +sudo cp -r $TESTFILES "$ROOTFS_DIR/home/builduser" + +echo "Storing test arguments and installing init script" +echo "$ARGS" > "$ROOTFS_DIR/test-args" +date -u '+%Y-%m-%d %H:%M:%S' > "$ROOTFS_DIR/host-time" +sudo cp "$TESTFILES/electron/script/qemu-init.sh" "$ROOTFS_DIR/init" +sudo chmod +x "$ROOTFS_DIR/init" + +echo "Creating disk image with root filesystem" +df -h +DISK_IMG=$(mktemp) +truncate -s 10G "$DISK_IMG" +sudo mkfs.ext4 -q -d "$ROOTFS_DIR" "$DISK_IMG" +sudo rm -rf "$ROOTFS_DIR" + +# Use KVM acceleration if available (ARM64 host can run 64K-page guest via KVM) +if [ -e /dev/kvm ] && [ -w /dev/kvm ]; then + echo "KVM available, using hardware acceleration" + ACCEL="-accel kvm -cpu host" +else + echo "KVM not available, using TCG emulation" + ACCEL="-accel tcg,thread=multi -cpu max,pauth-impdef=on" +fi + +echo "Starting QEMU VM with 64K page size kernel" +timeout 1800 qemu-system-aarch64 \ + -M virt \ + $ACCEL \ + -m 4096 \ + -smp 2 \ + -kernel "$VMLINUZ" \ + -append "console=ttyAMA0 root=/dev/vda rw init=/init net.ifnames=0 panic=1" \ + -drive file="$DISK_IMG",format=raw,if=virtio \ + -virtfs local,path="$TESTFILES",mount_tag=testfiles,security_model=none,id=testfiles \ + -netdev user,id=net0 \ + -device virtio-net-pci,netdev=net0 \ + -nographic \ + -no-reboot \ + || true + +echo "Extracting test results from disk image" +MOUNT_DIR=$(mktemp -d) +sudo mount -o loop "$DISK_IMG" "$MOUNT_DIR" +if [ -f "$MOUNT_DIR/results.xml" ]; then + cp "$MOUNT_DIR/results.xml" . +fi +EXIT_CODE=$(cat "$MOUNT_DIR/exit-code" 2>/dev/null || echo 1) +sudo umount "$MOUNT_DIR" +exit $EXIT_CODE