- Node 24.21.0, checked against its published SHA-256.
7
- git, make and pkg-config.
8
- Every crate that oxygen, oxygenhub and oxygenflow use, vendored in `/opt/vendor`.
9
10
OxygenFlow jobs have no network (`network "isolated"`). So cargo is pointed at the vendored crates by `/.cargo/config.toml`, which cargo reads for any directory under `/`, including `/src`. `CARGO_HOME` stays at its default, `$HOME/.cargo`, which is under `/tmp` and writable. The toolchain's binaries are linked into `/usr/local/bin`, because the guest's `PATH` is fixed and nothing at run time needs rustup.
`build.sh` vendors the crates of the three workspaces next to this repository with `cargo vendor --locked`, then builds the image. Docker is used only on the machine that builds it, as a way to assemble a file system: the image is exported as a plain tarball. On the runner, `flow rootfs import` makes an ext4 image pinned by BLAKE3, which Firecracker boots read-only.
21
22
Rebuild and re-import whenever a `Cargo.lock` of those projects changes, then pin the new hash in the pipelines that use the image. A crate missing from the image fails the job with cargo's "no matching package" error, not with a network error.
23
24
##Using it
25
26
```kdl
27
sandbox "rust" {
28
runtime "microvm"
29
rootfs "cas://blob/<hash printed by flow rootfs import>"
30
memory-limit "8GiB"
31
cpu-limit 4
32
network "loopback" // tests that serve on 127.0.0.1 need it; nothing leaves the guest
33
}
34
35
job "test" {
36
sandbox "rust"
37
mount {
38
source "ephemeral://disk"
39
target "/src/target"
40
size "24GiB"
41
}
42
env {
43
CARGO_INCREMENTAL "0"
44
}
45
exec "cargo" "test" "--workspace"
46
}
47
```
48
49
Measured on Earth (4 cores, the job given all of them and 8 GiB): oxygen's `cargo fmt --check`, `clippy -D warnings` and `cargo test --workspace` from a cold build take 135 s.
50
51
The build tree goes on an `ephemeral://disk` mount. The workspace itself has only 512 MiB to spare, and a `tmpfs` would take the build tree out of the job's memory.