a083cc80 Andy McCall 1 month ago ↶
1
# OxygenFlow
2
1a1793bd Andy McCall 1 month ago ↶
3
[ ![ OxygenFlow ] ( https://oxygenhub.io/andymccall/oxygenflow/flow/badge.svg ) ] ( https://oxygenhub.io/andymccall/oxygenflow/flow )
c140d0d8 Andy McCall 1 month ago ↶
4
a083cc80 Andy McCall 1 month ago ↶
5
Hermetic pipelines for Oxygen repositories:
6
7
- a typed pipeline in ` .flow/pipeline.kdl`
8
- jobs run in isolation tiers, Firecracker microVMs by default
9
- the host writes the receipts
10
- results go to OxygenHub as checks and appear on its Flow tab
11
12
The specification is [ docs/spec.md ] ( docs/spec.md ) . What works today is
13
[ docs/m0.md ] ( docs/m0.md ) .
14
15
## A pipeline
16
17
``` kdl
18
schema-version 1
19
20
sandbox "alpine" {
21
runtime "microvm"
22
rootfs "cas://blob/…" // printed by `flow rootfs import`
23
memory-limit "256MiB"
24
network "isolated"
25
}
26
27
job "build" {
28
sandbox "alpine"
29
exec "make"
30
}
31
32
job "test" {
33
sandbox "alpine"
34
depends-on "build"
35
exec "sh" "-eu" "test.sh" // argv, run as written: no shell unless you name one
36
}
37
```
38
39
Each job boots its own microVM:
40
41
- it has no network device
42
- the rootfs is read-only
43
- the workspace is the state being built, read-write at ` /src`
44
- the job runs as a user that is not root
45
46
This repository's own pipeline is [ .flow/pipeline.kdl ] ( .flow/pipeline.kdl ) .
c140d0d8 Andy McCall 1 month ago ↶
47
The stamp at the top of this page is its result on OxygenHub. It shows the
48
run of the state you are viewing, not whatever the bookmark holds now, and
49
it names the state and each job's receipt.
a083cc80 Andy McCall 1 month ago ↶
50
fc10d9e8 Andy McCall 1 month ago ↶
51
## Deploying the runner on Earth
52
53
` make deploy-runner` builds ` flow` and the static ` flow-init` , installs them
54
under ` /home/claude/flow` (keeping the previous files as ` .prev` ), re-pins
55
` flow-init` in ` flow.toml` and restarts the ` flow-runner` service.
56
a083cc80 Andy McCall 1 month ago ↶
57
## Commands
58
59
flow check # validate .flow/pipeline.kdl, print jobs and the pipeline hash
60
flow run [JOB…] # run the pipeline on this directory, locally, in microVMs
61
flow rootfs import T.tgz --sha256 HEX # make a rootfs image; prints the `rootfs` line to pin
a72abeee Andy McCall 1 month ago ↶
62
[--env NAME=value …] # with the image's own environment (a Dockerfile's ENV)
a083cc80 Andy McCall 1 month ago ↶
63
flow rootfs list
64
flow hash FILE # BLAKE3, for pinning in flow.toml
65
flow runner # claim and run jobs for the hub in flow.toml
66
67
## A Flow home
68
69
` $FLOW_HOME` (default ` ~/.local/share/flow` ) holds:
70
71
- ` flow.toml`
72
- the pinned Firecracker binary, guest kernel and ` flow-init`
73
- rootfs images under ` cas/`
74
- scratch space
75
76
Every pinned file is checked against its BLAKE3 before use.
77
78
``` toml
79
[microvm]
80
firecracker = { path = "bin/firecracker", blake3 = "…" }
81
kernel = { path = "kernel/vmlinux", blake3 = "…" }
82
init = { path = "bin/flow-init", blake3 = "…" }
83
84
[runner] # only for `flow runner`
85
hub = "https://hub.example:7343"
86
token = "…" # listed in the hub's [flow] runner_tokens
87
ca = "/path/to/hub-ca.pem" # when the hub's certificate is self-signed
88
name = "runner-1"
bb643c25 Andy McCall 1 month ago ↶
89
max_jobs = 3 # jobs at once (default 1)
90
memory_mib = 24576 # what they may use together; a lone job may use it all
91
cpus = 8
a083cc80 Andy McCall 1 month ago ↶
92
```
93
94
Setting one up needs Linux x86-64 with KVM and e2fsprogs 1.43 or later:
95
96
1. Build ` flow` with ` cargo build --release -p flow` . Build the guest init
97
as a static binary:
98
` RUSTFLAGS="-C target-feature=+crt-static" cargo build --release -p flow-init --target x86_64-unknown-linux-gnu` .
99
2. Download Firecracker v1.17.0 from its GitHub release, and check the
100
published SHA-256. Download the guest kernel
101
` firecracker-ci/v1.15/x86_64/vmlinux-6.1.155` from Firecracker's CI
102
bucket.
103
3. Run ` flow rootfs import alpine-minirootfs-3.24.2-x86_64.tar.gz --sha256 …` .
104
4. Write ` flow.toml` , pinning each file by its ` flow hash` .
105
106
On OxygenHub, ` hub.toml` lists the runner token and the repositories whose
107
pushes run pipelines:
108
109
``` toml
110
[flow]
111
runner_tokens = ["…"]
112
repos = ["owner/*"]
113
```
114
115
## Tests
116
117
` cargo test --workspace` runs every test that needs no VM. The microVM
118
conformance test also runs when ` FLOW_TEST_HOME` names a Flow home and
119
` FLOW_TEST_ROOTFS` is the hash of an Alpine rootfs in it. The test checks
120
literal argv, network isolation, the read-only rootfs, and that dependents
121
are skipped after a failure.
fe128fa6 Andy McCall 1 month ago ↶
122
123
## oxygen as a pinned subrepo
124
125
` flow` builds against ` deps/oxygen` , a subrepo (` oxy submodule` ) pinned to an exact state, so builds are reproducible and OxygenFlow can build this repository without network. ` make pins` moves it to oxygen's ` main` on Earth (push oxygen first); the next commit records the new pin. Format only this workspace, ` cargo fmt -p flow -p flow-core -p flow-init` : ` --all` also reaches ` deps/` . After a fresh clone, ` oxy submodule update --init` fetches it.