From bf01930d94ca3c47c57917d297339ff8b829485b Mon Sep 17 00:00:00 2001 From: Elie Habib Date: Thu, 26 Feb 2026 17:52:29 +0400 Subject: [PATCH 1/2] fix(ci): use weston+XWayland for Linux smoke test instead of pure Wayland Previous attempt used GDK_BACKEND=wayland which caused GTK init panic (tao requires X11). Now: weston headless with XWayland provides X11 through a real compositor. Falls back to Xvfb if weston fails. Also uploads weston/app logs as artifacts for debugging. --- .github/workflows/test-linux-app.yml | 100 ++++++++++++++++++++++++--- 1 file changed, 91 insertions(+), 9 deletions(-) diff --git a/.github/workflows/test-linux-app.yml b/.github/workflows/test-linux-app.yml index 906228114..2dc62a4d7 100644 --- a/.github/workflows/test-linux-app.yml +++ b/.github/workflows/test-linux-app.yml @@ -47,8 +47,11 @@ jobs: patchelf \ gstreamer1.0-plugins-base \ gstreamer1.0-plugins-good \ + weston \ + xwayland \ xvfb \ - imagemagick + imagemagick \ + xdotool - name: Install frontend dependencies run: npm ci @@ -80,24 +83,103 @@ jobs: exit 1 fi chmod +x "$APPIMAGE" - Xvfb :99 -screen 0 1440x900x24 & - export DISPLAY=:99 - sleep 2 - "$APPIMAGE" --no-sandbox & + + # --- Try 1: Weston + XWayland --- + # Weston provides a real compositor; XWayland gives GTK the X11 it needs. + # This avoids the blank-screen problem of bare Xvfb. + echo "=== Starting weston (headless + XWayland) ===" + mkdir -p /tmp/weston-run + export XDG_RUNTIME_DIR=/tmp/weston-run + + # Write a minimal weston.ini enabling XWayland + cat > /tmp/weston-run/weston.ini <<'WINI' + [core] + xwayland=true + WINI + # Strip leading whitespace from heredoc + sed -i 's/^[[:space:]]*//' /tmp/weston-run/weston.ini + + weston --backend=headless --config=/tmp/weston-run/weston.ini \ + --width=1440 --height=900 2>&1 | tee /tmp/weston.log & + WESTON_PID=$! + sleep 3 + + WESTON_OK=false + if kill -0 $WESTON_PID 2>/dev/null; then + # Find the XWayland DISPLAY + XWDISPLAY=$(grep -oP 'DISPLAY=:\K[0-9]+' /tmp/weston.log 2>/dev/null || echo "") + if [ -n "$XWDISPLAY" ]; then + export DISPLAY=":$XWDISPLAY" + echo "XWayland running on DISPLAY=$DISPLAY" + WESTON_OK=true + else + echo "Weston started but XWayland DISPLAY not found in logs" + cat /tmp/weston.log || true + fi + else + echo "Weston failed to start" + cat /tmp/weston.log || true + fi + + # --- Fallback: plain Xvfb --- + if [ "$WESTON_OK" = "false" ]; then + echo "=== Falling back to Xvfb ===" + kill $WESTON_PID 2>/dev/null || true + Xvfb :99 -screen 0 1440x900x24 & + export DISPLAY=:99 + sleep 2 + fi + + # --- Launch AppImage --- + echo "=== Launching AppImage on DISPLAY=$DISPLAY ===" + GDK_BACKEND=x11 "$APPIMAGE" --no-sandbox 2>&1 | tee /tmp/app.log & APP_PID=$! - sleep 15 - import -window root screenshot.png || true + sleep 20 + + # --- Screenshot --- + import -window root screenshot.png 2>/dev/null || true + + # --- Verify app is still running --- if kill -0 $APP_PID 2>/dev/null; then - echo "✅ AppImage launched successfully" - kill $APP_PID || true + echo "✅ AppImage launched successfully (PID $APP_PID)" else echo "❌ AppImage crashed during startup" + echo "--- App log ---" + tail -50 /tmp/app.log || true exit 1 fi + # --- Check screenshot has non-black content --- + if [ -f screenshot.png ]; then + COLORS=$(identify -verbose screenshot.png 2>/dev/null | grep "Colors:" | awk '{print $2}') + echo "Screenshot unique colors: ${COLORS:-unknown}" + if [ "${COLORS:-0}" -le 5 ]; then + echo "⚠️ Screenshot appears blank (only $COLORS colors). App may not have rendered." + else + echo "✅ Screenshot has content ($COLORS unique colors)" + fi + fi + + # --- Print app window info --- + xdotool search --name "" getwindowname 2>/dev/null | head -5 || true + + kill $APP_PID 2>/dev/null || true + kill $WESTON_PID 2>/dev/null || true + - name: Upload smoke test screenshot + if: always() uses: actions/upload-artifact@v4 with: name: linux-smoke-test-screenshot path: screenshot.png if-no-files-found: warn + + - name: Upload logs + if: always() + uses: actions/upload-artifact@v4 + with: + name: linux-smoke-test-logs + path: | + /tmp/weston.log + /tmp/app.log + if-no-files-found: warn From bfc81d151897e4c3b83fb60deb2327ce61ddc128 Mon Sep 17 00:00:00 2001 From: Elie Habib Date: Thu, 26 Feb 2026 17:55:40 +0400 Subject: [PATCH 2/2] refactor(ci): use xwfb-run for Linux smoke test display xwfb-run (from xwayland-run package) is purpose-built for this: Xwayland on a headless Wayland compositor, replaces xvfb-run. Falls back to plain Xvfb if xwfb-run is unavailable. Uploads display-server and app logs as artifacts. --- .github/workflows/test-linux-app.yml | 114 +++++++++++++-------------- 1 file changed, 55 insertions(+), 59 deletions(-) diff --git a/.github/workflows/test-linux-app.yml b/.github/workflows/test-linux-app.yml index 2dc62a4d7..db3d54f83 100644 --- a/.github/workflows/test-linux-app.yml +++ b/.github/workflows/test-linux-app.yml @@ -47,8 +47,7 @@ jobs: patchelf \ gstreamer1.0-plugins-base \ gstreamer1.0-plugins-good \ - weston \ - xwayland \ + xwayland-run \ xvfb \ imagemagick \ xdotool @@ -83,72 +82,75 @@ jobs: exit 1 fi chmod +x "$APPIMAGE" + APPIMAGE_ABS=$(realpath "$APPIMAGE") - # --- Try 1: Weston + XWayland --- - # Weston provides a real compositor; XWayland gives GTK the X11 it needs. - # This avoids the blank-screen problem of bare Xvfb. - echo "=== Starting weston (headless + XWayland) ===" - mkdir -p /tmp/weston-run - export XDG_RUNTIME_DIR=/tmp/weston-run - - # Write a minimal weston.ini enabling XWayland - cat > /tmp/weston-run/weston.ini <<'WINI' - [core] - xwayland=true - WINI - # Strip leading whitespace from heredoc - sed -i 's/^[[:space:]]*//' /tmp/weston-run/weston.ini - - weston --backend=headless --config=/tmp/weston-run/weston.ini \ - --width=1440 --height=900 2>&1 | tee /tmp/weston.log & - WESTON_PID=$! - sleep 3 - - WESTON_OK=false - if kill -0 $WESTON_PID 2>/dev/null; then - # Find the XWayland DISPLAY - XWDISPLAY=$(grep -oP 'DISPLAY=:\K[0-9]+' /tmp/weston.log 2>/dev/null || echo "") - if [ -n "$XWDISPLAY" ]; then - export DISPLAY=":$XWDISPLAY" - echo "XWayland running on DISPLAY=$DISPLAY" - WESTON_OK=true - else - echo "Weston started but XWayland DISPLAY not found in logs" - cat /tmp/weston.log || true - fi + # Write the inner test script (runs inside the display server) + cat > /tmp/smoke-test.sh <<'SCRIPT' + #!/bin/bash + set -x + echo "DISPLAY=$DISPLAY WAYLAND_DISPLAY=${WAYLAND_DISPLAY:-unset}" + + GDK_BACKEND=x11 "$APPIMAGE_ABS" --no-sandbox 2>&1 | tee /tmp/app.log & + APP_PID=$! + sleep 20 + + # Screenshot via X11 + import -window root /tmp/screenshot.png 2>/dev/null || true + + # Verify app is still running + if kill -0 $APP_PID 2>/dev/null; then + echo "APP_STATUS=running" + else + echo "APP_STATUS=crashed" + echo "--- App log ---" + tail -50 /tmp/app.log || true + fi + + # Window info + xdotool search --name "" getwindowname 2>/dev/null | head -5 || true + + kill $APP_PID 2>/dev/null || true + SCRIPT + chmod +x /tmp/smoke-test.sh + + export APPIMAGE_ABS + RESULT=0 + + # --- Try 1: xwfb-run (Xwayland on headless Wayland compositor) --- + if command -v xwfb-run &>/dev/null; then + echo "=== Using xwfb-run (Xwayland + headless compositor) ===" + timeout 90 xwfb-run -- bash /tmp/smoke-test.sh 2>&1 | tee /tmp/display-server.log || RESULT=$? else - echo "Weston failed to start" - cat /tmp/weston.log || true + echo "xwfb-run not found, skipping" + RESULT=1 fi # --- Fallback: plain Xvfb --- - if [ "$WESTON_OK" = "false" ]; then + if [ $RESULT -ne 0 ] || [ ! -f /tmp/screenshot.png ]; then echo "=== Falling back to Xvfb ===" - kill $WESTON_PID 2>/dev/null || true Xvfb :99 -screen 0 1440x900x24 & + XVFB_PID=$! export DISPLAY=:99 sleep 2 + bash /tmp/smoke-test.sh 2>&1 | tee /tmp/display-server.log + kill $XVFB_PID 2>/dev/null || true fi - # --- Launch AppImage --- - echo "=== Launching AppImage on DISPLAY=$DISPLAY ===" - GDK_BACKEND=x11 "$APPIMAGE" --no-sandbox 2>&1 | tee /tmp/app.log & - APP_PID=$! - sleep 20 - - # --- Screenshot --- - import -window root screenshot.png 2>/dev/null || true + # --- Copy screenshot to workspace --- + cp /tmp/screenshot.png screenshot.png 2>/dev/null || true - # --- Verify app is still running --- - if kill -0 $APP_PID 2>/dev/null; then - echo "✅ AppImage launched successfully (PID $APP_PID)" - else + # --- Check results --- + if grep -q "APP_STATUS=crashed" /tmp/display-server.log 2>/dev/null; then echo "❌ AppImage crashed during startup" - echo "--- App log ---" - tail -50 /tmp/app.log || true exit 1 fi + if grep -q "APP_STATUS=running" /tmp/display-server.log 2>/dev/null; then + echo "✅ AppImage launched successfully" + else + echo "⚠️ Could not determine app status" + fi + # --- Check screenshot has non-black content --- if [ -f screenshot.png ]; then COLORS=$(identify -verbose screenshot.png 2>/dev/null | grep "Colors:" | awk '{print $2}') @@ -160,12 +162,6 @@ jobs: fi fi - # --- Print app window info --- - xdotool search --name "" getwindowname 2>/dev/null | head -5 || true - - kill $APP_PID 2>/dev/null || true - kill $WESTON_PID 2>/dev/null || true - - name: Upload smoke test screenshot if: always() uses: actions/upload-artifact@v4 @@ -180,6 +176,6 @@ jobs: with: name: linux-smoke-test-logs path: | - /tmp/weston.log + /tmp/display-server.log /tmp/app.log if-no-files-found: warn