a3s-box-sdk 2.6.0

Rust SDK for a3s-box. Includes a programmable CI/CD pipeline API (pipelines as code, one MicroVM kernel per step).
Documentation

a3s-box-sdk

The Rust SDK for a3s-box. Today it provides a programmable CI/CD pipeline API (a3s_box_sdk::pipeline) — a pipeline is a Rust program, not a YAML file, and each step runs in its own MicroVM (one Linux kernel per step, so an untrusted step can't escape to the host or a sibling step). More capabilities will be added over time; the crate is intentionally not limited to CI.

Dependency-free: a thin wrapper over the a3s-box CLI (which owns the box lifecycle and state). Set A3S_BOX if a3s-box is not on PATH.

Pipelines

Warm a base box once (clone + install deps), snapshot it, fork per step:

use a3s_box_sdk::pipeline::{warm_base, WarmBase, FileCache, Step};

fn main() -> Result<(), a3s_box_sdk::pipeline::PipelineError> {
    let cache = FileCache::new(".ci-cache")?;          // skip a step when its inputs are unchanged
    let mut base = warm_base(
        WarmBase::new("node:20", "git clone $REPO /w && cd /w && npm ci")   // runs ONCE
            .env("REPO", "https://github.com/me/app")
            .cache(&cache),
    )?;
    base.step(Step::new("lint", "cd /w && npm run lint"))?;
    base.step(Step::new("test", "cd /w && npm test"))?;   // nonzero exit -> Err (fail-fast)
    base.step(Step::new("build", "cd /w && npm run build"))?;
    base.dispose();                                       // drops the snapshot
    Ok(())
}

Step::allow_failure() keeps the pipeline going on a non-zero exit; Step::input(..) adds extra cache-key parts. Parallel steps = spawn threads (each step is blocking).

Why forking is cheap

a3s-box's snapshot restore is copy-on-write: each fork mounts the snapshot's pristine rootfs as a read-only overlay lower with its own upper — near-instant, a few MB per fork, and isolated. So snapshot-per-step fan-out costs almost nothing.

What it hides

CLI footguns verified on a real KVM host, so you don't hit them: run/exec need -- before the command; snapshot restore yields a created box (started before exec); snapshot rm keys on snapshot ID, not name; rm -f of a missing box is a no-op here (idempotent reruns).

Run the example

cargo test -p a3s-box-sdk                                            # offline unit tests
A3S_BOX=/path/to/a3s-box cargo run -p a3s-box-sdk --example pipeline  # live, needs /dev/kvm