Skip to content

Commit 6d824c8

Browse files
committed
chore(ci): add xvfb to Linux deps, increase E2E timeouts, document Linux CI gotchas
1 parent 5809bf9 commit 6d824c8

3 files changed

Lines changed: 49 additions & 5 deletions

File tree

.github/copilot-instructions.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,44 @@ The project uses **electron** - a local MCP tool for inspecting and debugging th
290290

291291
---
292292

293+
## CI / Linux E2E pipeline debugging
294+
295+
### Architecture constraints on Apple Silicon
296+
297+
Full E2E simulation on Apple Silicon (arm64 Mac) is **not feasible** locally:
298+
299+
- `act` with arm64 catthehacker images: wdio downloads an x86_64 Chromedriver → `rosetta error: failed to open elf at /lib64/ld-linux-x86-64.so.2`
300+
- `act --container-architecture linux/amd64` (QEMU): act injects its own arm64 node into the amd64 container → `node: executable file not found in $PATH`
301+
- Native arm64 Docker containers: Electron runs, but Chromedriver is always fetched as x86_64
302+
303+
**Definitive validation requires pushing to GitHub and letting the real `ubuntu-latest` (x86_64) runners execute the E2E suite.**
304+
305+
### Known Linux CI gotchas
306+
307+
- **D-Bus deadlock**: `autoUpdater.checkForUpdates()` in `electron-updater` makes a blocking D-Bus IPC call on Linux when the system D-Bus daemon is running (always present on `ubuntu-latest`). In E2E mode, this deadlocks the Electron main process before the renderer loads. **Fix**: guard `startUpdateCheck()` with `if (!isE2EMode)` in `app/src/main/index.ts`. The `isE2EMode` flag is set when `process.argv.includes('--sproutgit-e2e')`, which wdio passes when launching Electron.
308+
- **Headless display**: Electron requires a display server on Linux. Wrap the E2E command with `xvfb-run --auto-servernum --server-args="-screen 0 1280x800x24"` and ensure `xvfb` is installed in the apt-get step.
309+
- **Sandbox**: pass `--no-sandbox --disable-setuid-sandbox` to Electron in CI (already in `wdio.conf.ts`).
310+
311+
### Proving a Linux-specific hang locally (arm64 Docker)
312+
313+
To confirm whether a code path causes a main-process freeze on Linux with D-Bus present, use the cached `sproutgit-dbus-proof-arm64:latest` Docker image:
314+
315+
```bash
316+
# Build the app inside the container, start Xvfb + D-Bus, run Electron for 5s,
317+
# and check whether the renderer emitted any log lines.
318+
docker run --rm \
319+
-v "$(pwd):/src:ro" \
320+
-v "/tmp/your-proof.sh:/proof.sh:ro" \
321+
sproutgit-dbus-proof-arm64:latest \
322+
bash /proof.sh
323+
```
324+
325+
Key detection heuristic: after 5 seconds, if no `[renderer]` lines appear in the Electron log, the main process is frozen (D-Bus deadlock). If `[renderer]` lines appear, the app is alive.
326+
327+
The image already has: ubuntu 24.04, Node 22, pnpm, xvfb, dbus, all Electron system deps. Rebuild it with `docker build -t sproutgit-dbus-proof-arm64:latest .` from a Dockerfile that installs those deps if it becomes stale.
328+
329+
---
330+
293331
## Common pitfalls
294332

295333
- **Don't import from `old/`** — it's the Tauri/SvelteKit source for reference only.

.github/workflows/ci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ jobs:
180180
run: |
181181
sudo apt-get update -q
182182
sudo apt-get install -y -q \
183+
xvfb \
183184
libgbm1 libnss3 libatk1.0-0 libatk-bridge2.0-0 \
184185
libdrm2 libxkbcommon0 libxdamage1 libxrandr2 libxfixes3 \
185186
libxcomposite1 libxcursor1 libxi6 libxss1 libxtst6 \

e2e/wdio.conf.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,14 @@ export const config: WebdriverIO.Config = {
5555
logLevel: 'info',
5656
bail: 0,
5757

58-
// Default timeout for waitForDisplayed / expect assertions (5s baseline).
59-
waitforTimeout: 15_000,
60-
61-
connectionRetryTimeout: 20_000,
58+
// On Linux the renderer can be slow to initialise (QEMU emulation on CI or
59+
// amd64 runners without hardware GPU acceleration). Use 4× the base timeout
60+
// so QEMU-based Docker runs and real CI both stay reliable.
61+
// On macOS/Windows native builds the app renders in <2s so the limit is
62+
// never reached for passing tests.
63+
waitforTimeout: process.platform === 'linux' ? 60_000 : 15_000,
64+
65+
connectionRetryTimeout: process.platform === 'linux' ? 60_000 : 20_000,
6266
connectionRetryCount: 3,
6367

6468
services: ['electron'],
@@ -70,7 +74,8 @@ export const config: WebdriverIO.Config = {
7074
ui: 'bdd',
7175
// Safety-net timeout per test; individual element waits are capped by waitforTimeout.
7276
// Screenshot pipeline runs 5 shots × 2 themes and can take up to 2 minutes.
73-
timeout: process.env['CAPTURE_SCREENSHOTS'] ? 120_000 : 30_000,
77+
// Linux gets 4× headroom for QEMU emulation (Docker) and CPU-limited CI runners.
78+
timeout: process.env['CAPTURE_SCREENSHOTS'] ? 120_000 : process.platform === 'linux' ? 120_000 : 30_000,
7479
},
7580

7681
// Always build the Electron app before running tests so the test binary is

0 commit comments

Comments
 (0)