Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 132 additions & 0 deletions .github/workflows/sandbox-e2e.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
name: Windows Sandbox E2E Tests

# Windows Sandbox requires full Hyper-V container infrastructure which is NOT
# available on GitHub-hosted runners. The feature reports "Enabled" but
# WindowsSandbox.exe cannot boot VMs (no nested Hyper-V container support).
#
# This workflow:
# - Builds and verifies sandbox binaries on every PR (always works)
# - Attempts to run E2E tests but expects them to fail on hosted runners
# - Succeeds fully on self-hosted runners with Windows Sandbox enabled
# - Can be triggered manually via workflow_dispatch on capable machines
#
# Unlike NanVix/MicroVM which uses WHP (a lightweight hypervisor API that
# works on Azure VMs), Windows Sandbox needs the full container stack.

on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:

jobs:
sandbox-e2e:
name: Sandbox E2E
runs-on: windows-latest
timeout-minutes: 45

steps:
- uses: actions/checkout@v4

- name: Setup Rust toolchain
run: |
rustup update stable
rustup target add x86_64-pc-windows-msvc

- name: Build
working-directory: src
run: cargo build --target x86_64-pc-windows-msvc

- name: Exclude build output from Windows Defender
shell: pwsh
run: |
$binDir = Join-Path $env:GITHUB_WORKSPACE "src\target\x86_64-pc-windows-msvc\debug"
Add-MpPreference -ExclusionPath $binDir
Write-Host "Added Defender exclusion for $binDir"

- name: Verify Sandbox binaries
shell: pwsh
run: |
$binDir = Join-Path $env:GITHUB_WORKSPACE "src\target\x86_64-pc-windows-msvc\debug"
$required = @("wxc-exec.exe", "wxc-sandbox-daemon.exe", "wxc-sandbox-guest.exe")
$missing = $required | Where-Object { -not (Test-Path (Join-Path $binDir $_)) }
if ($missing) {
Write-Host "::error::Missing binaries: $($missing -join ', ')"
exit 1
}
Get-ChildItem $binDir -Include $required -Recurse | Format-Table Name, Length

- name: Check Windows Sandbox availability
id: sandbox-check
shell: pwsh
run: |
# Check if the feature is installed (may be "enabled" but non-functional
# on GitHub-hosted runners due to lack of nested Hyper-V container support).
$info = dism /online /get-featureinfo /featurename:Containers-DisposableClientVM 2>&1 |
Select-String "State"
if ($info -notmatch "Enabled") {
Write-Host "::warning::Windows Sandbox feature is not enabled - skipping E2E tests."
"sandbox_available=false" | Out-File -Append -FilePath $env:GITHUB_OUTPUT
} else {
Write-Host "Windows Sandbox feature is enabled. Will attempt E2E tests."
Write-Host "Note: On GitHub-hosted runners, the feature may be enabled but"
Write-Host "non-functional (WindowsSandbox.exe cannot boot VMs). Tests will"
Write-Host "report a warning if they fail for this reason."
"sandbox_available=true" | Out-File -Append -FilePath $env:GITHUB_OUTPUT
}
exit 0

- name: Run Sandbox E2E Tests
if: steps.sandbox-check.outputs.sandbox_available == 'true'
id: sandbox-tests
continue-on-error: true
shell: pwsh
working-directory: test_scripts
run: |
$wxcExe = Join-Path $env:GITHUB_WORKSPACE "src\target\x86_64-pc-windows-msvc\debug\wxc-exec.exe"
$configDir = Join-Path $env:GITHUB_WORKSPACE "test_configs"
.\run_sandbox_tests.ps1 -WxcExePath $wxcExe -ConfigDir $configDir

- name: Report sandbox test outcome
if: steps.sandbox-check.outputs.sandbox_available == 'true' && !cancelled()
shell: pwsh
run: |
$outcome = "${{ steps.sandbox-tests.outcome }}"
if ($outcome -eq "success") {
Write-Host "All sandbox E2E tests passed!" -ForegroundColor Green
} elseif ($outcome -eq "failure") {
Write-Host "::warning::Sandbox E2E tests failed."
Write-Host "::warning::This is expected on GitHub-hosted runners where Windows Sandbox"
Write-Host "::warning::is enabled but non-functional (no nested Hyper-V container support)."
Write-Host "::warning::Tests pass on self-hosted runners with full Sandbox support."
}

- name: Print performance summary
if: steps.sandbox-check.outputs.sandbox_available == 'true' && !cancelled()
shell: pwsh
run: |
$jsonPath = Join-Path $env:GITHUB_WORKSPACE "sandbox-perf-results.json"
if (Test-Path $jsonPath) {
$data = Get-Content $jsonPath -Raw | ConvertFrom-Json
Write-Host "`n=== Sandbox Performance Summary ==="
Write-Host "Commit: $($data.commit)"
Write-Host "Timestamp: $($data.timestamp)"
Write-Host ""
Write-Host ("{0,-40} {1,10} {2,8}" -f "Test", "Time (ms)", "Status")
Write-Host ("{0,-40} {1,10} {2,8}" -f "----", "---------", "------")
foreach ($r in $data.results) {
Write-Host ("{0,-40} {1,10} {2,8}" -f $r.description, $r.wall_time_ms, $r.status)
}
} else {
Write-Host "No performance results found (tests may not have run)."
}

- name: Upload performance results
if: steps.sandbox-check.outputs.sandbox_available == 'true' && !cancelled()
uses: actions/upload-artifact@v4
with:
name: sandbox-perf-results-${{ github.event.pull_request.number || github.run_number }}
retention-days: 30
path: sandbox-perf-results.json
if-no-files-found: ignore
Loading