diff --git a/.github/workflows/test-linux-app.yml b/.github/workflows/test-linux-app.yml index 906228114..db3d54f83 100644 --- a/.github/workflows/test-linux-app.yml +++ b/.github/workflows/test-linux-app.yml @@ -47,8 +47,10 @@ jobs: patchelf \ gstreamer1.0-plugins-base \ gstreamer1.0-plugins-good \ + xwayland-run \ xvfb \ - imagemagick + imagemagick \ + xdotool - name: Install frontend dependencies run: npm ci @@ -80,24 +82,100 @@ jobs: exit 1 fi chmod +x "$APPIMAGE" - Xvfb :99 -screen 0 1440x900x24 & - export DISPLAY=:99 - sleep 2 - "$APPIMAGE" --no-sandbox & + APPIMAGE_ABS=$(realpath "$APPIMAGE") + + # 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 15 - import -window root screenshot.png || true + 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 "✅ AppImage launched successfully" - kill $APP_PID || true + 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 "xwfb-run not found, skipping" + RESULT=1 + fi + + # --- Fallback: plain Xvfb --- + if [ $RESULT -ne 0 ] || [ ! -f /tmp/screenshot.png ]; then + echo "=== Falling back to Xvfb ===" + 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 + + # --- Copy screenshot to workspace --- + cp /tmp/screenshot.png screenshot.png 2>/dev/null || true + + # --- Check results --- + if grep -q "APP_STATUS=crashed" /tmp/display-server.log 2>/dev/null; then echo "❌ AppImage crashed during startup" 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}') + 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 + - 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/display-server.log + /tmp/app.log + if-no-files-found: warn