-
-
Notifications
You must be signed in to change notification settings - Fork 296
155 lines (140 loc) · 5.46 KB
/
Copy pathlinux.yml
File metadata and controls
155 lines (140 loc) · 5.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
name: Linux
on:
pull_request:
paths-ignore:
- 'docs/**'
- 'website/**'
- 'README.md'
- 'AGENTS.md'
- 'CHANGELOG.md'
- 'CONTEXT.md'
- 'CONTRIBUTING.md'
- 'LICENSE'
- 'SECURITY.md'
- '.github/actions/build-docs/action.yml'
- '.github/workflows/deploy.yml'
- '.github/workflows/pr-preview.yml'
- '.github/workflows/pr-preview-cleanup.yml'
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
# Unbounded, this step could not fail — it could only stall. On 2026-08-19 a slow mirror
# held apt past the job's 30-minute budget on four main-branch runs and several unrelated
# PRs, which reported as a red check on branches that never ran a line of project code.
# Two bounds fix that: apt retries and times out each mirror request itself (a blip
# self-heals without a manual re-run), and `timeout-minutes` is the backstop for a mirror
# that drips bytes slowly enough to defeat the socket timeout. A healthy install takes
# about a minute, so six is generous.
- name: Install Linux desktop dependencies
timeout-minutes: 6
run: |
set -euo pipefail
APT_OPTS=(
-o Acquire::Retries=2
-o Acquire::http::Timeout=15
-o Acquire::https::Timeout=15
# The runner's own unattended-upgrades timer holds the dpkg lock; wait, don't hang.
-o DPkg::Lock::Timeout=60
)
sudo apt-get update -qq "${APT_OPTS[@]}"
sudo apt-get install -y -qq "${APT_OPTS[@]}" \
xvfb \
xdotool \
scrot \
at-spi2-core \
python3-gi \
gir1.2-atspi-2.0 \
libatk-adaptor \
dbus-x11 \
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 [ -z "$ATSPI_REG" ]; then
echo "::error::at-spi2-registryd not found. Install at-spi2-core."
exit 1
fi
"$ATSPI_REG" &
sleep 2
# Health probe: verify the registry is reachable on the a11y bus
if python3 -c "import gi; gi.require_version('Atspi','2.0'); from gi.repository import Atspi; d=Atspi.get_desktop(0); assert d is not None, 'desktop is None'; print(f'AT-SPI2 OK — {d.get_child_count()} apps')"; then
echo "AT-SPI2 registry healthy"
else
echo "::error::AT-SPI2 registry started but health probe failed"
exit 1
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 linux/atspi-dump.py --surface desktop --max-nodes 5 | python3 -m json.tool | head -20 || echo "::warning::AT-SPI2 tree dump returned no nodes (expected before any app is launched)"
echo "=== xdotool ==="
xdotool version
- name: Run Linux replay smoke test
run: pnpm clean:daemon
- name: Execute Linux replay smoke test
uses: ./.github/actions/run-gate
with:
gate: replay-linux
args: |
--retries
2
--report-junit
test/artifacts/replays-linux.junit.xml
- name: Reset daemon before Linux command evidence
run: pnpm clean:daemon
- name: Execute Linux command evidence
uses: ./.github/actions/run-gate
with:
gate: linux-command-evidence
- 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/**