Development Guide
Prerequisites
Section titled “Prerequisites”- Rust 1.85+ (Edition 2024) — install via rustup
- macOS or Linux — macOS for development via Lima, Linux for native
/dev/kvm - Nix (optional) — only needed for building microVM images
Run the bootstrap script on a fresh machine:
./scripts/dev-setup.shBuilding and Running
Section titled “Building and Running”# Buildjust build
# Run CLIjust run -- --help
# Dev mode (auto-bootstraps Lima + Firecracker)just run -- dev
# Release build (stripped, LTO)just release-buildTesting
Section titled “Testing”# Run all tests with nextestjust test
# Test a single cratejust test-crate mvm-core
# Run tests matching a filterjust test-filter "test_snapshot"
# Full CI gate (lint + test)just ciTest Organization
Section titled “Test Organization”| Location | Type | What it tests |
|---|---|---|
crates/*/src/**/*.rs (#[cfg(test)]) | Unit tests | Internal functions within the crate |
crates/*/tests/*.rs | Integration tests | Public API of each crate |
tests/cli.rs | Binary tests | CLI arg parsing, help output, subcommand structure |
Testing Conventions
Section titled “Testing Conventions”- Unit tests go in
#[cfg(test)] mod tests {}at the bottom of the source file - CLI binary tests go in root
tests/cli.rs - Use
#[serde(default)]when adding fields to structs used in test fixtures
Linting and Formatting
Section titled “Linting and Formatting”just fmt # Format all codejust clippy # Lint (zero warnings required)just lint # Both format check + clippyStyle Rules
Section titled “Style Rules”- Edition 2024:
usestatements don’t needextern crate; let chains supported - No
clippy::too_many_arguments: never suppress this lint — refactor into a params struct - No
format!()informat!()named args: extract to a variable first - Cross-crate imports: always use
mvm_core::,mvm_runtime::, etc.
Architecture Principles
Section titled “Architecture Principles”Host vs. VM
Section titled “Host vs. VM”All Linux operations (networking, Firecracker, cgroups) run inside the Lima VM on macOS:
// This runs a bash script inside the Lima VMmvm_runtime::shell::run_in_vm("ip link add br-tenant-1 type bridge")?;On native Linux, run_in_vm runs directly without Lima.
Key Patterns
Section titled “Key Patterns”- Idempotent operations: every setup step checks if already done before acting
- Config drive for metadata: instance metadata delivered via read-only ext4 disk
- Vsock over SSH: guest communication uses Firecracker vsock, not sshd
Adding New Types
Section titled “Adding New Types”When adding fields to structs in serialized state:
- Add
#[serde(default)]to the new field for backward compatibility cargo test --workspaceto find all broken test constructions- Fix each one
- Add a unit test for the new behavior
| Workflow | Trigger | What it does |
|---|---|---|
ci.yml | Push to main/feat/*, PRs | check, fmt, clippy, test (macOS + Linux), audit |
release.yml | Tags matching v* | Builds 4 platform binaries, creates GitHub Release |
publish-crates.yml | Release published | Publishes to crates.io in dependency order |
pages.yml | Push to main | Deploys docs to GitHub Pages |
Release Process
Section titled “Release Process”# 1. Bump version in root Cargo.toml [workspace.package]# 2. Update CHANGELOG.md# 3. Commit and taggit add -A && git commit -m "release: v0.3.0"git tag v0.3.0
# 4. Push (triggers release.yml)git push && git push --tagsThe deploy guard (scripts/deploy-guard.sh) validates the tag matches the workspace version before publishing.