Skip to content
Open
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
64 changes: 64 additions & 0 deletions .github/workflows/e2e-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -205,3 +205,67 @@ jobs:
- name: Print AppArmor denials
if: always()
run: sudo dmesg | grep -E 'apparmor=.*DENIED|profile="unprivileged_userns"' | tail -100 || true

e2e-vm:
name: E2E (rust-vm)
# libkrun needs KVM, so this job must run directly on a GitHub-hosted
# Linux VM. GitHub-hosted macOS runners do not support nested
# virtualization, and a job container would hide the host KVM device.
runs-on: ubuntu-24.04
timeout-minutes: 90
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
MISE_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
ref: ${{ inputs['checkout-ref'] || github.sha }}
persist-credentials: false

- name: Enable KVM access
run: |
set -euo pipefail
if [[ ! -c /dev/kvm ]]; then
echo "::error::The GitHub-hosted runner did not expose /dev/kvm"
lscpu
grep -m1 -E '^(flags|Features)' /proc/cpuinfo || true
ls -la /dev
exit 1
fi
sudo chmod 0666 /dev/kvm
ls -l /dev/kvm
test -r /dev/kvm
test -w /dev/kvm

- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
build-essential \
clang \
cmake \
libclang-dev \
libssl-dev \
libz3-dev \
openssh-client \
pkg-config \
socat \
zstd

- name: Install mise
run: |
curl https://mise.run | MISE_VERSION=v2026.4.25 sh
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
echo "$HOME/.local/share/mise/shims" >> "$GITHUB_PATH"

- name: Install tools
run: mise install --locked

- name: Cache Rust target and registry
uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2
with:
shared-key: e2e-vm-linux-amd64
cache-on-failure: "true"

- name: Run VM E2E
run: mise run --no-deps --skip-deps e2e:vm
3 changes: 2 additions & 1 deletion CI.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ Merge queue validation is a second integration gate for `main`. After a PR has p

Three opt-in labels enable the long-running E2E suites:

- `test:e2e` runs the standard E2E suite in `Branch E2E Checks`
- `test:e2e` runs the standard Docker, rootless Podman, Kubernetes, and VM E2E
suites in `Branch E2E Checks`
- `test:e2e-gpu` runs GPU E2E in `Branch E2E Checks`
- `test:e2e-kubernetes` runs Kubernetes E2E with the HA Helm overlay
(`replicaCount: 2` and bundled PostgreSQL) in `Branch E2E Checks`
Expand Down
7 changes: 7 additions & 0 deletions TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ Suites:
- Common suite (`--features e2e`) - driver-neutral CLI behavior, sandbox lifecycle, sync, port forwarding, policy, and provider tests.
- Docker suite (`--features e2e-docker`) - common suite plus Docker-only coverage such as Dockerfile image builds, Docker preflight checks, and managed Docker gateway resume.
- Docker GPU suite (`--features e2e-docker-gpu`) - Docker suite plus GPU sandbox smoke coverage.
- VM suite (`--features e2e-vm`) - runs e2e tests on a VM.

GPU device-selection tests compare OpenShell sandboxes against a plain Docker or
Podman container that requests `--device nvidia.com/gpu=all`. The probe image
Expand All @@ -173,6 +174,12 @@ Run the Podman-backed Rust CLI e2e suite:
mise run e2e:podman
```

Run the VM-backed Rust CLI e2e suite:

```shell
mise run e2e:vm
```

Run a single test directly with cargo:

```shell
Expand Down
3 changes: 2 additions & 1 deletion architecture/build.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,8 @@ The high-level CI model:

1. PR-context gate jobs publish required statuses for the PR head commit.
2. Standard branch checks run from trusted mirror branches.
3. Label-gated E2E, GPU, and Kubernetes checks run from trusted mirror branches.
3. Label-gated Docker, Podman, VM, GPU, and Kubernetes E2E checks run from
trusted mirror branches.
4. Merge-group checks run against GitHub's temporary queue branch for the final integration state.
5. Gate jobs verify that the mirror branch matches the PR head, or that the merge-group workflow ran for the queued SHA, and that the expected non-gate workflow actually ran.
6. Release workflows rebuild and publish binaries, wheels, images, and docs.
Expand Down
1 change: 1 addition & 0 deletions e2e/rust/e2e-vm.sh
Original file line number Diff line number Diff line change
Expand Up @@ -315,4 +315,5 @@ if [ -n "${E2E_TEST_OVERRIDE}" ]; then
else
run_e2e_test smoke
run_e2e_test host_gateway_alias
run_e2e_test vm_gateway_resume
fi
5 changes: 4 additions & 1 deletion e2e/rust/tests/vm_gateway_resume.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,11 @@ async fn vm_gateway_restart_resumes_running_sandbox() {
.await
.expect("gateway should start healthy");

// The gateway restart terminates the VM process before re-adopting its
// overlay. Flush the marker before reporting readiness so the assertion
// verifies durable overlay state rather than guest page-cache timing.
let script = format!(
"echo before-restart > {RESUME_FILE}; echo {READY_MARKER}; while true; do sleep 1; done"
"echo before-restart > {RESUME_FILE}; sync; echo {READY_MARKER}; while true; do sleep 1; done"
);
let mut sandbox = SandboxGuard::create_keep(&["sh", "-lc", &script], READY_MARKER)
.await
Expand Down
Loading