Skip to content

Commit 6aa5ff7

Browse files
committed
Tooling: Add VNC mode for easy Linux running
- It runs the app in a VNC thing in a browser on a port. It's a bit weird, the VM feels better, but this is a small change so keeping it.
1 parent e642b03 commit 6aa5ff7

5 files changed

Lines changed: 119 additions & 11 deletions

File tree

apps/desktop/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"test:e2e:linux:native": "wdio run test/e2e-linux/wdio.conf.ts",
2626
"test:e2e:linux:build": "docker build -t cmdr-e2e -f test/e2e-linux/docker/Dockerfile test/e2e-linux/docker",
2727
"test:e2e:linux:shell": "./scripts/e2e-linux.sh --shell",
28+
"test:e2e:linux:vnc": "./scripts/e2e-linux.sh --vnc",
2829
"knip": "knip",
2930
"check:type-drift": "tsx scripts/check-type-drift.ts"
3031
},

apps/desktop/scripts/e2e-linux.sh

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
# ./scripts/e2e-linux.sh # Run tests
99
# ./scripts/e2e-linux.sh --build # Force rebuild Docker image
1010
# ./scripts/e2e-linux.sh --shell # Start interactive shell in container
11+
# ./scripts/e2e-linux.sh --vnc # Interactive VNC mode with hot reload
1112
# ./scripts/e2e-linux.sh --clean # Clean Linux build cache
1213

1314
set -e
@@ -46,6 +47,7 @@ log_error() {
4647
# Parse arguments
4748
FORCE_BUILD=false
4849
INTERACTIVE=false
50+
VNC_MODE=false
4951
CLEAN=false
5052

5153
for arg in "$@"; do
@@ -56,6 +58,9 @@ for arg in "$@"; do
5658
--shell)
5759
INTERACTIVE=true
5860
;;
61+
--vnc)
62+
VNC_MODE=true
63+
;;
5964
--clean)
6065
CLEAN=true
6166
;;
@@ -65,6 +70,7 @@ for arg in "$@"; do
6570
echo "Options:"
6671
echo " --build Force rebuild of Docker image"
6772
echo " --shell Start interactive shell in container"
73+
echo " --vnc Interactive VNC mode with hot reload (pnpm dev)"
6874
echo " --clean Clean Linux build cache (forces rebuild)"
6975
echo " --help Show this help message"
7076
exit 0
@@ -95,6 +101,65 @@ if $FORCE_BUILD || ! docker image inspect "$IMAGE_NAME" &> /dev/null; then
95101
docker build -t "$IMAGE_NAME" -f "$DESKTOP_DIR/test/e2e-linux/docker/Dockerfile" "$DESKTOP_DIR/test/e2e-linux/docker"
96102
fi
97103

104+
# VNC mode: runs pnpm dev inside Docker with VNC for interactive debugging.
105+
# Does NOT require a pre-built binary — uses Vite + Tauri hot reload instead.
106+
if $VNC_MODE; then
107+
log_info "Starting VNC mode with hot reload..."
108+
109+
# Temporarily clear .cargo/config.toml if present (local path patches don't exist in Docker)
110+
CARGO_CONFIG="$DESKTOP_DIR/src-tauri/.cargo/config.toml"
111+
CARGO_CONFIG_BAK=""
112+
if [ -f "$CARGO_CONFIG" ]; then
113+
CARGO_CONFIG_BAK="${CARGO_CONFIG}.docker-bak"
114+
cp "$CARGO_CONFIG" "$CARGO_CONFIG_BAK"
115+
> "$CARGO_CONFIG"
116+
trap 'mv "${CARGO_CONFIG_BAK}" "${CARGO_CONFIG}" 2>/dev/null || true' EXIT
117+
fi
118+
119+
docker run -it --rm \
120+
-v "$REPO_ROOT:/app" \
121+
-v "$CARGO_VOLUME:/root/.cargo" \
122+
-v "$TARGET_VOLUME:/target" \
123+
-v "$ROOT_NODE_MODULES_VOLUME:/app/node_modules" \
124+
-v "$DESKTOP_NODE_MODULES_VOLUME:/app/apps/desktop/node_modules" \
125+
-w /app \
126+
-p 5990:5990 \
127+
-p 6090:6090 \
128+
-e VNC=1 \
129+
-e CARGO_TARGET_DIR=/target \
130+
-e TAURI_DEV_HOST=0.0.0.0 \
131+
-e RUST_LOG=smb=warn,sspi=warn,info \
132+
"$IMAGE_NAME" \
133+
bash -c '
134+
set -e
135+
136+
# Install dev packages needed for Tauri build
137+
apt-get update > /dev/null && apt-get install -y \
138+
libwebkit2gtk-4.1-dev \
139+
libayatana-appindicator3-dev \
140+
librsvg2-dev \
141+
libacl1-dev \
142+
patchelf \
143+
> /dev/null
144+
145+
# Install dependencies if needed (node_modules is a Docker volume)
146+
if [ ! -f "/app/node_modules/.linux-installed" ]; then
147+
echo "Installing Linux node_modules..."
148+
pnpm install --frozen-lockfile
149+
touch /app/node_modules/.linux-installed
150+
fi
151+
152+
echo "Starting Cmdr in dev mode (Vite HMR + Tauri)..."
153+
echo "Frontend edits on macOS will hot reload in ~1-3s."
154+
echo "Rust edits require Ctrl+C and re-run."
155+
echo ""
156+
pnpm dev
157+
'
158+
159+
log_info "VNC session ended."
160+
exit 0
161+
fi
162+
98163
# Check if a Linux binary exists in the Docker volume
99164
# Override entrypoint to avoid Xvfb output
100165
check_linux_build() {

apps/desktop/test/e2e-linux/docker/Dockerfile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ RUN apt-get update && apt-get install -y \
4242
libcairo2 \
4343
libatk1.0-0 \
4444
libgdk-pixbuf-2.0-0 \
45+
# VNC for interactive debugging (--vnc mode)
46+
x11vnc \
47+
novnc \
48+
python3-websockify \
4549
# Useful utilities
4650
ca-certificates \
4751
# Clean up

apps/desktop/test/e2e-linux/docker/entrypoint.sh

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,21 @@ if ! kill -0 $XVFB_PID 2>/dev/null; then
3939
fi
4040
echo "Xvfb is running (PID: $XVFB_PID)"
4141

42-
# Change to the app directory if we're mounted
43-
if [ -d "/app/apps/desktop" ]; then
42+
# Start VNC server if requested (for interactive debugging with --vnc mode)
43+
if [ "${VNC:-}" = "1" ]; then
44+
echo "Starting VNC server..."
45+
x11vnc -display :99 -forever -nopw -shared -rfbport 5990 -q &
46+
/usr/share/novnc/utils/novnc_proxy --vnc localhost:5990 --listen 6090 &>/dev/null &
47+
echo ""
48+
echo "╔═══════════════════════════════════════════════════════════════════╗"
49+
echo "║ Open in browser: http://localhost:6090/vnc.html?autoconnect=true ║"
50+
echo "║ Native VNC: vnc://localhost:5990 (no password) ║"
51+
echo "╚═══════════════════════════════════════════════════════════════════╝"
52+
echo ""
53+
fi
54+
55+
# Change to the app directory if we're mounted (skip in VNC mode — it runs from repo root)
56+
if [ -d "/app/apps/desktop" ] && [ "${VNC:-}" != "1" ]; then
4457
cd /app/apps/desktop
4558
fi
4659

docs/tooling/e2e-testing-guide.md

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -84,15 +84,15 @@ pnpm test:e2e:linux:native
8484

8585
## Test files
8686

87-
| File | Description |
88-
|---------------------------------------|------------------------------------------------|
89-
| `test/e2e-smoke/smoke.test.ts` | Playwright tests for basic UI (browser-based) |
90-
| `test/e2e-linux/app.spec.ts` | WebDriverIO tests for Tauri app (Linux) |
91-
| `test/e2e-linux/wdio.conf.ts` | WebDriverIO configuration |
92-
| `test/e2e-linux/docker/Dockerfile` | Docker image for Linux E2E tests |
93-
| `test/e2e-linux/docker/entrypoint.sh` | Xvfb/dbus setup for headless GUI |
94-
| `scripts/e2e-linux.sh` | Main script for Docker-based E2E tests |
95-
| `playwright.config.ts` | Playwright configuration |
87+
| File | Description |
88+
|---------------------------------------|-----------------------------------------------------|
89+
| `test/e2e-smoke/smoke.test.ts` | Playwright tests for basic UI (browser-based) |
90+
| `test/e2e-linux/app.spec.ts` | WebDriverIO tests for Tauri app (Linux) |
91+
| `test/e2e-linux/wdio.conf.ts` | WebDriverIO configuration |
92+
| `test/e2e-linux/docker/Dockerfile` | Docker image for Linux E2E tests |
93+
| `test/e2e-linux/docker/entrypoint.sh` | Xvfb/dbus setup for headless GUI |
94+
| `scripts/e2e-linux.sh` | Main script for Docker-based E2E tests (+ VNC mode) |
95+
| `playwright.config.ts` | Playwright configuration |
9696

9797
## Writing tests
9898

@@ -153,6 +153,31 @@ Inside the container, you can:
153153
- Check the display: `echo $DISPLAY`
154154
- Inspect the environment
155155

156+
### VNC mode (visual debugging with hot reload)
157+
158+
VNC mode runs `pnpm dev` inside the Docker container with a VNC server, so you can see and
159+
interact with the Cmdr GUI in a browser while editing code on macOS:
160+
161+
Honestly, it's a bit weird, the VM feels better, but this is a small change so good to have this as a quick backup.
162+
163+
```bash
164+
cd apps/desktop
165+
pnpm test:e2e:linux:vnc
166+
```
167+
168+
Once it starts, open the URL printed in the terminal (http://localhost:6090/vnc.html?autoconnect=true).
169+
You can also connect with a native VNC client (macOS Screen Sharing) at `vnc://localhost:5990`.
170+
171+
How it works:
172+
- The container runs Xvfb + x11vnc + noVNC, forwarding the virtual display to your browser
173+
- `pnpm dev` starts Vite + Tauri inside the container
174+
- Source code is mounted from your host, so `.svelte`/`.ts` edits trigger Vite HMR (~1–3s reload)
175+
- Rust changes require restarting (`Ctrl+C` + re-run)
176+
- Terminal streams all Rust/Vite logs
177+
178+
This is useful for debugging issues specific to the Linux/WebKitGTK environment, like keyboard
179+
events or GTK focus behavior that differ from macOS.
180+
156181
### Build caching
157182

158183
The script uses Docker volumes to cache:

0 commit comments

Comments
 (0)