OXYGENHUB
# e3fb0e9b5e6b oxygenflow / images / rust / README.md
2.9 KiB · Markdown · last changed The cheap checks run as WASM: layout, todos, size and summary are one WASI module (crates/flow-checks, .flow/checks.wasm), so any runner with the WASM tier takes them; the fmt job checks the module is what its source builds; the build image gains wasm32-wasip1 (re-pinned e52c41a1) (closes #96) 9 days ago renderedsource blame history raw
eb5c4db6 Andy McCall ↶ 1
# The OxygenFlow build image
2
3
A root file system for Rust and Node jobs:
4
5
- Rust 1.97.1 with rustfmt and clippy.
6
- Node 24.21.0, checked against its published SHA-256.
7
- git, make and pkg-config.
fad61521 Andy McCall ↶ 8
- Coverage: llvm-tools and cargo-llvm-cov 0.9.1, so a job can write an LCOV report for the hub's Coverage tab.
28cc603f Andy McCall ↶ 9
- Test reports: cargo-nextest 0.9.148, so a job can write JUnit XML for the hub (with `cargo llvm-cov nextest`, both from one run).
85ad9087 Andy McCall ↶ 10
- Release cross-building: the Windows, Linux arm64 and riscv64, and macOS targets, zig 0.16.0 (checked against its SHA-256), cargo-zigbuild and MinGW, with zip, so `scripts/dist.sh` runs in a job.
5544c899 Andy McCall ↶ 11
- WASI: the wasm32-wasip1 target, so the fmt job can check that `.flow/checks.wasm` is what `crates/flow-checks` builds (#96).
eb5c4db6 Andy McCall ↶ 12
- Every crate that oxygen, oxygenhub and oxygenflow use, vendored in `/opt/vendor`.
13
14
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.
15
16
## Building and importing
17
18
```
19
images/rust/build.sh /path/to/oxygenflow-build.tar
20
scp /path/to/oxygenflow-build.tar claude@earth:/home/claude/flow/dl/
21
ssh claude@earth 'cd ~/flow && FLOW_HOME=~/flow bin/flow rootfs import dl/oxygenflow-build.tar'
22
```
23
24
`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.
25
26
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.
27
28
## Using it
29
30
```kdl
31
sandbox "rust" {
32
    runtime "microvm"
33
    rootfs "cas://blob/<hash printed by flow rootfs import>"
34
    memory-limit "8GiB"
35
    cpu-limit 4
36
    network "loopback"   // tests that serve on 127.0.0.1 need it; nothing leaves the guest
37
}
38
39
job "test" {
40
    sandbox "rust"
41
    mount {
42
        source "ephemeral://disk"
43
        target "/src/target"
44
        size "24GiB"
45
    }
46
    env {
47
        CARGO_INCREMENTAL "0"
48
    }
49
    exec "cargo" "test" "--workspace"
50
}
51
```
52
53
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.
54
55
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.