OXYGENHUB
# bb643c252515 oxygenflow / README.md
3.4 KiB · Markdown · last changed The runner runs up to max_jobs jobs at once within a memory and vCPU budget, asking the hub only for jobs that fit (a lone job may use the whole budget); preparing workspaces stays one at a time 1 month ago renderedsource blame history raw
1
# OxygenFlow
2
3
Hermetic pipelines for Oxygen repositories:
4
5
- a typed pipeline in `.flow/pipeline.kdl`
6
- jobs run in isolation tiers, Firecracker microVMs by default
7
- the host writes the receipts
8
- results go to OxygenHub as checks and appear on its Flow tab
9
10
The specification is [docs/spec.md]docs/spec.md. What works today is
11
[docs/m0.md]docs/m0.md.
12
13
## A pipeline
14
15
```kdl
16
schema-version 1
17
18
sandbox "alpine" {
19
    runtime "microvm"
20
    rootfs "cas://blob/…"      // printed by `flow rootfs import`
21
    memory-limit "256MiB"
22
    network "isolated"
23
}
24
25
job "build" {
26
    sandbox "alpine"
27
    exec "make"
28
}
29
30
job "test" {
31
    sandbox "alpine"
32
    depends-on "build"
33
    exec "sh" "-eu" "test.sh"   // argv, run as written: no shell unless you name one
34
}
35
```
36
37
Each job boots its own microVM:
38
39
- it has no network device
40
- the rootfs is read-only
41
- the workspace is the state being built, read-write at `/src`
42
- the job runs as a user that is not root
43
44
This repository's own pipeline is [.flow/pipeline.kdl].flow/pipeline.kdl.
45
46
## Commands
47
48
    flow check                 # validate .flow/pipeline.kdl, print jobs and the pipeline hash
49
    flow run [JOB…]            # run the pipeline on this directory, locally, in microVMs
50
    flow rootfs import T.tgz --sha256 HEX   # make a rootfs image; prints the `rootfs` line to pin
51
    flow rootfs list
52
    flow hash FILE             # BLAKE3, for pinning in flow.toml
53
    flow runner                # claim and run jobs for the hub in flow.toml
54
55
## A Flow home
56
57
`$FLOW_HOME` (default `~/.local/share/flow`) holds:
58
59
- `flow.toml`
60
- the pinned Firecracker binary, guest kernel and `flow-init`
61
- rootfs images under `cas/`
62
- scratch space
63
64
Every pinned file is checked against its BLAKE3 before use.
65
66
```toml
67
[microvm]
68
firecracker = { path = "bin/firecracker", blake3 = "…" }
69
kernel = { path = "kernel/vmlinux", blake3 = "…" }
70
init = { path = "bin/flow-init", blake3 = "…" }
71
72
[runner]                     # only for `flow runner`
73
hub = "https://hub.example:7343"
74
token = "…"                  # listed in the hub's [flow] runner_tokens
75
ca = "/path/to/hub-ca.pem"   # when the hub's certificate is self-signed
76
name = "runner-1"
77
max_jobs = 3                 # jobs at once (default 1)
78
memory_mib = 24576           # what they may use together; a lone job may use it all
79
cpus = 8
80
```
81
82
Setting one up needs Linux x86-64 with KVM and e2fsprogs 1.43 or later:
83
84
1. Build `flow` with `cargo build --release -p flow`. Build the guest init
85
   as a static binary:
86
   `RUSTFLAGS="-C target-feature=+crt-static" cargo build --release -p flow-init --target x86_64-unknown-linux-gnu`.
87
2. Download Firecracker v1.17.0 from its GitHub release, and check the
88
   published SHA-256. Download the guest kernel
89
   `firecracker-ci/v1.15/x86_64/vmlinux-6.1.155` from Firecracker's CI
90
   bucket.
91
3. Run `flow rootfs import alpine-minirootfs-3.24.2-x86_64.tar.gz --sha256 …`.
92
4. Write `flow.toml`, pinning each file by its `flow hash`.
93
94
On OxygenHub, `hub.toml` lists the runner token and the repositories whose
95
pushes run pipelines:
96
97
```toml
98
[flow]
99
runner_tokens = ["…"]
100
repos = ["owner/*"]
101
```
102
103
## Tests
104
105
`cargo test --workspace` runs every test that needs no VM. The microVM
106
conformance test also runs when `FLOW_TEST_HOME` names a Flow home and
107
`FLOW_TEST_ROOTFS` is the hash of an Alpine rootfs in it. The test checks
108
literal argv, network isolation, the read-only rootfs, and that dependents
109
are skipped after a failure.