Skip to main content
e2e-local.yml runs them on a persistent AWS EC2 self-hosted runner, because the tests boot real microVMs and need hardware virtualization. Below: how CI provisions the machine, how to read a failure, and the exact commands to reproduce the same run locally.

Prerequisites

  • A working BoxLite install (Python boxlite or Node @boxlite-ai/boxlite) and a machine with hardware virtualization — see Installation.
  • Install build dependencies: CI uses scripts/setup/setup-ubuntu.sh (Ubuntu). Locally you can use the project’s make setup.
  • The repository root has a Makefile (aggregating make/*.mk); the test entry point is make test:integration.
  • Operating the CI infrastructure requires the GitHub gh CLI and admin access to the repository (to dispatch the workflow and configure variables/secrets).

Quick Example (shortest reproduction path)

Reproduce locally (same commands as CI)

Tip: make test:integration actually boots microVMs. On a clean machine the first run compiles the whole toolchain first (roughly 5-10 minutes); subsequent runs reuse the cache and are significantly faster.

make test vs make test:integration:cli

These two targets are not interchangeable:
  • make test is make test:changed: it inspects the working tree, maps changed components to suites, and runs only those. With no detected changes it runs nothing (use make test:all for the full unit + integration matrix). Each changed component maps to its own suite — for example, a CLI change runs make test:integration:cli.
  • make test:integration:cli runs only the CLI integration tests. It depends on runtime:debug (it builds the debug runtime first unless setup already ran), then runs the suite with --no-fail-fast so one failure does not hide the rest:
The CLI tests are real integration tests, not unit tests: each test pulls images, creates boxes, and runs the actual boxlite binary against a microVM. They therefore require the same virtualization environment as the rest of make test:integration (KVM on Linux, Hypervisor.framework on macOS). To keep first-run image pulls cheap and avoid registry rate limits, a shared, pre-warmed cache is set up once per test process and the standard test images (alpine:latest, debian:bookworm-slim, python:alpine) are pre-pulled and reused. For how the CLI test harness itself is structured, see the CLI Development Guide.

Trigger a run in CI

How it runs (workflow structure)

The workflow has four jobs: Note on the single-instance design: the workflow keeps one persistent EC2 instance for this test suite — started before a run and stopped afterward (never terminated) — so the build and image caches remain on the EBS volume. Because there is only one instance, only one e2e run can proceed at a time; a newer run cancels an older queued run.

Triggers

Note on source prefixes: the trigger paths use the real repository layout src/<crate>/ (src/boxlite, src/shared, src/cli, src/guest) and sdks/**, not the old boxlite/src/ prefix.

Instance & auth

Keeping the instance warm is why repeat runs are faster: a clean instance’s first run requires a full compile (roughly 5-10 minutes of initialization), after which it reuses the cached toolchain and build artifacts. Running cost is the instance’s on-demand rate while a run is in progress, plus the persistent root volume; price it against your own account and region. Authentication uses no long-lived secrets:
  • AWS — GitHub OIDC is exchanged for short-lived STS credentials via the boxlite-e2e-github-actions IAM role. No AWS key is stored in the repository.
  • GitHub — a GitHub App (boxlite-e2e-runner) issues runner registration tokens at run time. There is no personal access token.

One-time setup (provisioning)

All AWS and GitHub infrastructure is provisioned by a single script:
It auto-detects the AWS account, the repository, the default VPC, and a public subnet, and creates these AWS resources: And it sets the following on the repository: The GitHub App is created through a script-driven browser manifest flow — follow the prompts to confirm and install the App. EC2_E2E_INSTANCE_ID is written automatically the first time the instance is created; later runs use it to locate the instance directly. Once provisioning is complete, trigger a run:

Parameters & Returns (key parameters)

Workflow environment and inputs (from e2e-local.yml): Relevant make targets available locally:
The authoritative target list is make help (aggregated in make/help.mk); the table above is the common subset.

Troubleshooting

References (source)

The links below point to real files in the repository (these are for contributors to open directly):
  • Workflow: .github/workflows/e2e-local.yml
  • Provisioning script: scripts/ci/setup-ci-runner.sh
  • Build-dependency install: scripts/setup/setup-ubuntu.sh
  • Test entry point (make targets): Makefile + make/*.mk (run make help for all targets)
  • CI overview: .github/workflows/README.md

See also

  • CLI Development Guide — building and testing the BoxLite CLI, including how the CLI integration tests differ from the full matrix.