mirror of
https://github.com/software-mansion/argent.git
synced 2026-09-14 19:27:14 +08:00
7400179b5b
## What Makes Argent run on Windows. iOS Simulator is macOS-only (Apple), so on Windows that means the **Android + Chromium** host control plane. The blocker was twofold: (1) no Windows `simulator-server` binary, and (2) POSIX-only assumptions in the tool-server. Companion radon PR builds the binary and runs the Android emulator E2E on Windows: software-mansion/radon#134. ## Changes **Windows-aware tool-server / resolver / bundling** - New shared `commandOnPath()` helper — `where` on Windows, `command -v` via `/bin/sh` on POSIX. `android-binary`, `check-deps`, and `vega-cli` previously hardcoded `/bin/sh`, which never matches on Windows. - `android-binary`: append `.exe` to `adb`/`emulator` in the `$ANDROID_HOME` fallback; probe `%LOCALAPPDATA%\Android\Sdk` (Android Studio's Windows default). - simulator-server resolver + dispatcher + `bundle-tools` + `download-simulator-server.sh`: ship and resolve `simulator-server.exe` on `win32` (new `simulatorServerBinaryName()`), add `win32` to the bundled host keys, add the `simulator-server-argent-windows.exe` download target with PE arch validation. - `stop-metro`: resolve listening PIDs via `netstat -ano` on Windows (`lsof` is POSIX-only and threw ENOENT). - `adb.ts`: AVD root resolution used `$HOME` + `startsWith("/")` (rejects `C:\…`); now `os.homedir()` + `path.isAbsolute()`. - **`boot-device`**: the emulator was spawned `detached` with `stdio:"ignore"`; on Windows a detached emulator with NUL stdout/stderr never reaches `sys.boot_completed` (verified on `windows-latest`: the identical flag set boots fine with real handles, hangs with NUL). Redirect the detached emulator's output to a temp log file on win32. POSIX keeps `"ignore"`. **Tests** — cross-platform unit coverage for `commandOnPath` (both branches), win32 `.exe` Android resolution, win32 `.exe` simulator-server resolution, and a win32 AVD drive-path case; dep-gate tests now mock at the `commandOnPath` boundary so they're platform-agnostic. **CI** — `windows-e2e.yml` (`windows-chromium` on `windows-latest`): runs the resolver/dep unit tests natively on Windows, confirms `adb.exe` resolution via the SDK root, then drives a **real headless Chrome over CDP** through the tool-server (discover → screenshot → describe → tap → observe the DOM mutation). Flow in `scripts/ci/windows-chromium-e2e.mjs` (also runnable locally / in Docker). The `simulator-server.exe` build + the full **Android-emulator E2E on Windows** live in radon CI (the binary's source is the private radon repo). ## Verification (all green) - **Chromium control plane on real Windows** (`windows-latest`): `✓ discovered chromium-cdp-9222 → ✓ screenshot → ✓ describe → ✓ gesture-tap → ✓ DOM mutation observed`. Resolver/dep unit tests run natively; `adb.exe` resolves via the SDK root (it's *not* on PATH on the runner — the gap the resolver closes). - **Android emulator on real Windows** (radon#134, `windows-latest` / WHPX): the real Argent path — `boot-device` → `{ booted: true }` → screenshot via `simulator-server.exe` → gesture-tap — all green. (The boot-device fix above is what makes the detached emulator reach `boot_completed`.) - **Local clean-room E2E**: the Chromium flow runs green in a headless Linux Docker container (fresh `npm ci`, no host pollution). - **No regressions**: full tool-server suite (1624) + native-devtools-ios (16); ESLint/Prettier/typecheck clean; **Wayland E2E** (Linux AVD boot) and **Vega VVD E2E** still pass (they exercise the changed `adb.ts` / `boot-device.ts` / `vega-cli.ts` paths). ## Notes Android-emulator E2E needs WHPX nested virtualization — confirmed available on the current hosted `windows-latest` image (Server 2025); the emulator boots hardware-accelerated in ~3 min. --------- Co-authored-by: Ignacy Łątka <claude-hubert.gancarczyk@swmansion.com> Co-authored-by: Ignacy Łątka <latekvo@users.noreply.github.com>
191 lines
8.9 KiB
YAML
191 lines
8.9 KiB
YAML
name: Windows E2E
|
|
|
|
# Proves Argent runs on Windows. iOS Simulator is macOS-only (Apple), so
|
|
# "Argent on Windows" means the Android + Chromium host control plane.
|
|
#
|
|
# This job, windows-chromium, has the tool-server drive a real headless Chrome
|
|
# over CDP (discover → screenshot → describe → tap → observe the DOM change).
|
|
# Chromium control is pure host-side TypeScript, so a hosted Windows runner (no
|
|
# virtualization) verifies it fully. It also runs the cross-platform resolver
|
|
# unit tests natively on Windows and confirms adb.exe resolution.
|
|
#
|
|
# The simulator-server.exe itself (the binary the Android path spawns) lives in
|
|
# the private radon repo, so it can't be built here without a cross-repo token.
|
|
# Its Windows build + smoke-run is verified in radon CI instead — see the
|
|
# build_argent_windows job in radon's simulator-server-ci workflow (companion
|
|
# PR). WHPX is available on windows-latest (Server 2025), so an Android emulator
|
|
# does boot on a hosted runner — that is where the boot-device stdio fix was
|
|
# verified. The full Android emulator E2E still lives in radon CI alongside that
|
|
# binary rather than here, because this repo can't build simulator-server.exe
|
|
# without a cross-repo token; that path is therefore out of scope for this job.
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
pull_request:
|
|
branches:
|
|
- main
|
|
paths:
|
|
- "packages/tool-server/src/utils/command-on-path.ts"
|
|
- "packages/tool-server/src/utils/android-binary.ts"
|
|
- "packages/tool-server/src/utils/adb.ts"
|
|
- "packages/tool-server/src/utils/check-deps.ts"
|
|
- "packages/tool-server/src/utils/vega-cli.ts"
|
|
- "packages/tool-server/src/utils/chromium-discovery.ts"
|
|
- "packages/tool-server/src/tools/simulator/stop-metro.ts"
|
|
- "packages/tool-server/src/tools/devices/boot-device.ts"
|
|
- "packages/tool-server/src/utils/device-shutdown.ts"
|
|
# The unit tests this job runs — editing one must re-run it here.
|
|
- "packages/tool-server/test/command-on-path.test.ts"
|
|
- "packages/tool-server/test/android-binary-windows.test.ts"
|
|
- "packages/tool-server/test/adb-resolve-avd-path.test.ts"
|
|
- "packages/tool-server/test/check-deps.test.ts"
|
|
- "packages/tool-server/test/http-dep-gate.test.ts"
|
|
- "packages/tool-server/test/stop-metro-netstat.test.ts"
|
|
- "packages/tool-server/test/device-shutdown.test.ts"
|
|
- "packages/native-devtools-ios/src/index.ts"
|
|
- "packages/native-devtools-ios/test/index.test.ts"
|
|
- "packages/argent/scripts/bundle-tools.cjs"
|
|
- "packages/argent/scripts/argent-simulator-server.cjs"
|
|
- "scripts/dev.cjs"
|
|
- "scripts/download-simulator-server.sh"
|
|
- "scripts/ci/windows-chromium-e2e.mjs"
|
|
- "scripts/ci/e2e-chromium-page.html"
|
|
- ".github/workflows/windows-e2e.yml"
|
|
|
|
jobs:
|
|
windows-chromium:
|
|
name: Chromium control plane + resolver unit tests (Windows)
|
|
runs-on: windows-latest
|
|
timeout-minutes: 20
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Set up Node.js
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: "20"
|
|
|
|
- name: Install dependencies
|
|
run: npm ci
|
|
|
|
- name: Fix rollup native bindings (win32)
|
|
# vitest 4 transforms via rollup, whose platform binary is an optional
|
|
# dep npm ci sometimes skips; install the win32 one explicitly.
|
|
run: npm install @rollup/rollup-win32-x64-msvc --no-save
|
|
|
|
- name: Build workspace
|
|
run: npx tsc --build
|
|
|
|
- name: Resolver unit tests on Windows (tool-server)
|
|
# The win32 branches added for Windows support, exercised on a real
|
|
# Windows host (real `where.exe`, real `.exe` access semantics) rather
|
|
# than a mocked platform. The broader suite has POSIX-only fixtures, so
|
|
# this is the curated cross-platform subset.
|
|
working-directory: packages/tool-server
|
|
run: >
|
|
npx vitest run
|
|
test/command-on-path.test.ts
|
|
test/android-binary-windows.test.ts
|
|
test/adb-resolve-avd-path.test.ts
|
|
test/check-deps.test.ts
|
|
test/http-dep-gate.test.ts
|
|
test/stop-metro-netstat.test.ts
|
|
test/device-shutdown.test.ts
|
|
|
|
- name: Resolver unit tests on Windows (native-devtools-ios)
|
|
working-directory: packages/native-devtools-ios
|
|
run: npx vitest run
|
|
|
|
- name: adb.exe resolves on Windows
|
|
# windows-latest ships the Android SDK with ANDROID_HOME/ANDROID_SDK_ROOT
|
|
# set but does NOT put platform-tools on PATH — exactly the gap the
|
|
# Windows resolver closes (`.exe` suffix + SDK-root fallback). Resolve
|
|
# adb the way the tool-server does, then run the *resolved* path (a bare
|
|
# `adb` wouldn't be found, which is the whole point).
|
|
shell: pwsh
|
|
run: |
|
|
$adb = node -e "require('./packages/tool-server/dist/utils/android-binary.js').resolveAndroidBinary('adb').then(p => process.stdout.write(p || ''))"
|
|
Write-Host "resolved adb -> $adb"
|
|
if ([string]::IsNullOrWhiteSpace($adb) -or -not $adb.ToLower().EndsWith('adb.exe')) {
|
|
Write-Error "expected resolveAndroidBinary('adb') to return an adb.exe path"
|
|
exit 1
|
|
}
|
|
if (-not (Test-Path $adb)) { Write-Error "resolved adb path does not exist: $adb"; exit 1 }
|
|
& $adb version
|
|
|
|
- name: Locate Chrome
|
|
id: chrome
|
|
run: |
|
|
$candidates = @(
|
|
"$env:ProgramFiles\Google\Chrome\Application\chrome.exe",
|
|
"${env:ProgramFiles(x86)}\Google\Chrome\Application\chrome.exe",
|
|
"$env:LOCALAPPDATA\Google\Chrome\Application\chrome.exe"
|
|
)
|
|
$chrome = $candidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
|
if (-not $chrome) { Write-Error "Google Chrome not found on this runner"; exit 1 }
|
|
Write-Host "Chrome: $chrome"
|
|
"path=$chrome" >> $env:GITHUB_OUTPUT
|
|
|
|
# Launch Chrome + the tool-server AND run the E2E in one step. On Windows
|
|
# runners, `Start-Process` background processes don't reliably survive into
|
|
# a later step (unlike `nohup` on Linux), so both must stay in scope for
|
|
# the duration of the E2E — hence a single step rather than three.
|
|
- name: Launch Chrome + tool-server and run Chromium E2E
|
|
env:
|
|
ARGENT_E2E_URL: http://127.0.0.1:3033
|
|
run: |
|
|
$page = "file:///" + ((Resolve-Path scripts/ci/e2e-chromium-page.html).Path -replace '\\','/')
|
|
$udd = Join-Path $env:RUNNER_TEMP "chrome-e2e-profile"
|
|
$chromeLog = Join-Path $env:RUNNER_TEMP "chrome.log"
|
|
Start-Process -FilePath "${{ steps.chrome.outputs.path }}" -ArgumentList @(
|
|
"--headless=new","--remote-debugging-port=9222","--user-data-dir=$udd",
|
|
"--no-first-run","--no-default-browser-check","--disable-gpu",$page
|
|
) -RedirectStandardOutput $chromeLog -RedirectStandardError "$chromeLog.err" | Out-Null
|
|
$cdpUp = $false
|
|
for ($i = 0; $i -lt 30; $i++) {
|
|
try {
|
|
$r = Invoke-WebRequest -UseBasicParsing "http://127.0.0.1:9222/json/version" -TimeoutSec 2
|
|
if ($r.StatusCode -eq 200) { Write-Host "CDP up at t+${i}s"; $cdpUp = $true; break }
|
|
} catch {}
|
|
Start-Sleep -Seconds 1
|
|
}
|
|
if (-not $cdpUp) { Get-Content "$chromeLog.err" -ErrorAction SilentlyContinue; Write-Error "Chrome CDP never came up on :9222"; exit 1 }
|
|
|
|
$env:ARGENT_PORT = "3033"
|
|
New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.argent" | Out-Null
|
|
$tsLog = Join-Path $env:RUNNER_TEMP "tool-server.log"
|
|
Start-Process -FilePath "node" -ArgumentList @("packages/tool-server/dist/index.js","start") `
|
|
-RedirectStandardOutput $tsLog -RedirectStandardError "$tsLog.err" | Out-Null
|
|
$tsUp = $false
|
|
for ($i = 0; $i -lt 40; $i++) {
|
|
try {
|
|
$r = Invoke-WebRequest -UseBasicParsing "http://127.0.0.1:3033/tools" -TimeoutSec 2
|
|
if ($r.StatusCode -eq 200) { Write-Host "tool-server up at t+${i}s"; $tsUp = $true; break }
|
|
} catch {}
|
|
Start-Sleep -Seconds 1
|
|
}
|
|
if (-not $tsUp) {
|
|
Write-Host "--- tool-server.log ---"; Get-Content $tsLog -ErrorAction SilentlyContinue
|
|
Write-Host "--- tool-server.err ---"; Get-Content "$tsLog.err" -ErrorAction SilentlyContinue
|
|
Write-Error "tool-server never came up on :3033"; exit 1
|
|
}
|
|
|
|
$env:ARGENT_E2E_OUT = Join-Path $env:RUNNER_TEMP "e2e"
|
|
node scripts/ci/windows-chromium-e2e.mjs
|
|
|
|
- name: Upload artifacts
|
|
if: always()
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: windows-chromium-e2e
|
|
path: |
|
|
${{ runner.temp }}/e2e/*.png
|
|
${{ runner.temp }}/tool-server.log
|
|
${{ runner.temp }}/tool-server.log.err
|
|
${{ runner.temp }}/chrome.log
|
|
${{ runner.temp }}/chrome.log.err
|
|
if-no-files-found: warn
|
|
retention-days: 7
|