feat: add Linux desktop automation support via AT-SPI2 #7
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: Linux | |
| on: | |
| pull_request: | |
| push: | |
| branches: | |
| - main | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: ci-${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| smoke-linux: | |
| name: Smoke Tests | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 | |
| env: | |
| # Force X11 mode (Xvfb) — no Wayland on CI. | |
| XDG_SESSION_TYPE: x11 | |
| DISPLAY: ":99" | |
| # Headless GTK: avoid dconf issues, enable accessibility bridge. | |
| GSETTINGS_BACKEND: memory | |
| NO_AT_BRIDGE: "0" | |
| GTK_A11Y: atspi | |
| GTK_MODULES: "gail:atk-bridge" | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| - name: Install Linux desktop dependencies | |
| run: | | |
| # python3-gi, gir1.2-atspi-2.0, at-spi2-core, dbus-x11 are | |
| # pre-installed on Ubuntu GitHub Actions runners. | |
| sudo apt-get update -qq | |
| sudo apt-get install -y -qq \ | |
| xvfb \ | |
| xdotool \ | |
| scrot \ | |
| libatk-adaptor \ | |
| gnome-calculator \ | |
| wmctrl | |
| - name: Setup toolchain | |
| uses: ./.github/actions/setup-node-pnpm | |
| - name: Start Xvfb and D-Bus | |
| run: | | |
| # Start virtual framebuffer (1280x1024, 24-bit color) | |
| Xvfb :99 -screen 0 1280x1024x24 & | |
| sleep 1 | |
| # Start a D-Bus session and export its env vars for subsequent steps. | |
| # dbus-launch forks a persistent daemon, so it survives the step. | |
| eval "$(dbus-launch --sh-syntax)" | |
| echo "DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS" >> "$GITHUB_ENV" | |
| echo "DBUS_SESSION_BUS_PID=$DBUS_SESSION_BUS_PID" >> "$GITHUB_ENV" | |
| - name: Start AT-SPI2 registry | |
| run: | | |
| # The registry must start AFTER DBUS_SESSION_BUS_ADDRESS is available | |
| # (it was written to GITHUB_ENV in the previous step). | |
| ATSPI_REG=$(find /usr -name at-spi2-registryd -type f 2>/dev/null | head -1) | |
| if [ -n "$ATSPI_REG" ]; then | |
| "$ATSPI_REG" & | |
| sleep 2 | |
| echo "AT-SPI2 registry started: $ATSPI_REG" | |
| else | |
| echo "::warning::at-spi2-registryd not found — accessibility tree may be empty" | |
| fi | |
| - name: Verify environment | |
| run: | | |
| echo "=== Display ===" | |
| xdotool getdisplaygeometry | |
| echo "=== D-Bus ===" | |
| echo "DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS" | |
| echo "=== AT-SPI2 Python bindings ===" | |
| python3 -c "import gi; gi.require_version('Atspi', '2.0'); from gi.repository import Atspi; print('OK')" | |
| echo "=== AT-SPI2 tree dump (quick test) ===" | |
| python3 src/platforms/linux/atspi-dump.py --surface desktop --max-nodes 5 | python3 -m json.tool | head -20 | |
| echo "=== xdotool ===" | |
| xdotool version | |
| - name: Run Linux replay smoke test | |
| run: | | |
| pnpm clean:daemon | |
| node --experimental-strip-types src/bin.ts test test/integration/replays/linux \ | |
| --retries 3 \ | |
| --report-junit test/artifacts/replays-linux.junit.xml | |
| - name: Upload Linux artifacts | |
| if: always() | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
| with: | |
| name: linux-artifacts | |
| if-no-files-found: ignore | |
| path: | | |
| test/artifacts/** | |
| test/screenshots/** |