OXYGENHUB
# f1d14bb6ec2b oxygenflow / CHANGELOG.md
6.6 KiB · Markdown · last changed feat(cache): unchanged sources keep their times; claims list the caches held (closes #52, refs #51) 23 days ago renderedsource blame history raw
c3db750e Andy McCall 1
# Changelog
2
3
OxygenFlow has no release yet: the runner on Earth runs `main`. This file starts on 2026-10-01; earlier history is in `oxy log`.
4
5
## Unreleased
6
82cf6e91 Andy McCall ↶ 7
- **The build cache pays off (#51, #52, spec §5.4).** A cached disk keeps the content hashes and times of the sources it was built from, and the next job gives every unchanged file its old time back, so cargo rebuilds only the crates that changed instead of every path crate. Claims list the caches a runner holds, and the hub sends a job to the runner holding its cache, as it does for images.
8
89171fca Andy McCall ↶ 9
- **Restarts cost no job (#49, #50, spec §11.5.1).** A job's uploads and declines wait out a hub that is away for up to three minutes (a deploy restarting it), through refused connections as well as server errors, and log lines it could not send go with the next batch instead of being dropped. A runner told to stop drains: it claims nothing more, finishes and reports the jobs it holds, then exits; a second signal stops it at once. With `KillMode=mixed` and a `TimeoutStopSec` longer than the longest job in its unit, deploying a runner no longer has to wait for it to be idle.
10
d60aac6c Andy McCall ↶ 11
- **A build cache (#28, spec §5.4).** A disk mount may name a `cache` and the `key` files it depends on, such as `Cargo.lock`. The runner keeps passing jobs' disks and starts the next job of the same repository, job and bookmark from one, so builds carry their compiled dependencies forward; another bookmark copies it rather than taking it. Failing jobs' disks are never kept, the receipt names what a disk started from, and the pool stays under `cache_gb` (default 64 GiB).
12
ecce3719 Andy McCall ↶ 13
- **Runners share images (#47, docs/jetstream.md §8.1).** A runner with a `[runner.swarm]` section serves the image chunks it holds to other runners in its site, and fetches an image it lacks from them and the hub together, rarest chunks first. The hub is asked only for chunks no peer has or is fetching, so runners starting together split its work. Peers talk over TLS: each runner keeps its own certificate, the hub hands its fingerprint on with the peer, and a fetcher trusts no other. Peers admit each other with a ticket the hub signs, and every chunk is checked against its hash. Uploads are capped (`upload_mib_s`, default 50) at 16 connections. Without the section a runner fetches from the hub alone, as before.
b14aeaae Andy McCall ↶ 14
b11e30f5 Andy McCall ↶ 15
- **A runner declines a job it cannot run (#36, spec §11.5).** Before fetching anything it checks the tier, the architecture, that the image is there and verifies, and that the sandbox's memory is free. If any check fails it hands the job back to the hub with the reason instead of running and failing it.
16
ea56c56e Andy McCall ↶ 17
- **The syscall tier (#36, docs/m0.md §3).** `runtime "syscall"` jobs run without KVM, so boards such as the OrangePi RV2 can take them. The sandbox uses user, mount, PID, network, IPC and UTS namespaces on the image's unpacked tree, read-only. Landlock limits writes to `/src` and `/tmp`, and a seccomp filter refuses network sockets, tracing, mounts, BPF, keys, modules and io_uring. A delegated cgroup v2 group enforces the CPU and memory limits, and a job killed for memory is told so. A runner offers the tier only where all of this works. `flow tiers` shows which tiers a machine can run and why the others cannot, and `flow run` runs syscall jobs too.
18
c5b702e5 Andy McCall ↶ 19
- **A runner offers only the tiers it can run (#36).** It checks that `/dev/kvm` opens before offering the MicroVM tier, says which tiers it serves when it starts, and refuses to start with none, naming why, rather than claiming jobs it would fail.
20
f53e6d47 Andy McCall ↶ 21
- **A runner tries a fetch again after a network hiccup (oxygenhub#111).** Fetching or cloning the job's repository or a subrepo is retried on DNS, connection, timeout and 502/503/504 errors, waiting 2, 4, 8, 16 and 30 seconds; any other error still ends the job at once.
22
1abadd4a Andy McCall ↶ 23
- **Architecture awareness (#36, spec §11.2).** `flow rootfs import` records an image's architecture from its shell's ELF header and refuses an image for another architecture; a claim reports each image's architecture, and a sandbox may say `arch "riscv64"`.
24
720eb819 Andy McCall ↶ 25
- **A job's identity (oxygenhub#103).** `identity "AUDIENCE" { mount-path "/run/secrets/…" }` asks the hub for an OIDC token for that audience, mounted as a file like a secret.
26
e2c12561 Andy McCall ↶ 27
- **Secrets as files (oxygenhub#107).** A job's `secret "name" { mount-path "/run/secrets/…" }` names a secret the hub holds; it comes with the claim and `flow-init` writes it at that path, 0400, on a tmpfs, before the job starts. Never in the environment, the receipt or an artifact (spec §9). `flow run --secret NAME=VALUE` locally.
28
c58efc6a Andy McCall ↶ 29
- **Variables from the hub (oxygenhub#102).** A claim carries `env`, the variables the hub holds for the repository; they join the job's environment under `FLOW_*` and the pipeline's own `env`. `flow run --var NAME=VALUE` does the same locally.
30
02b127d2 Andy McCall ↶ 31
- **A job says how long it may run (#23).** `timeout "90m"` on a job, or on a sandbox for its jobs (hours, minutes, seconds; a minute to a day). The hub caps it at the site's maximum.
32
33
- **A pinned file is re-read from the disk before its hash is called wrong (#22).**
34
1daca0b6 Andy McCall ↶ 35
- **A runner says which jobs it holds (oxygenhub#71).** Each claim lists the jobs the runner is running or still has a result for, so the hub ends at once any job it lost by restarting, instead of an hour later at the time limit.
8c0a4e3a Andy McCall ↶ 36
- **A runner says which images it holds (oxygenhub#73).** Each claim lists the rootfs images in the runner's `cas/` (read each time, so an image imported while it runs counts), and the hub offers only jobs whose image is among them. plex-1 had failed metalgear's jobs for want of one.
37
3007d8f0 Andy McCall ↶ 38
- **A job's result is kept until the hub has it (oxygenhub#71).** The runner offered a finished job's result three times over seven seconds and then dropped it, so a hub that was briefly down (Earth's reset) left the job running forever. The result is now kept on disk (`pending/` in the Flow home) and offered again, every 5 s doubling to a minute, for up to two hours, through any server error or lost connection; a runner that restarts sends what it kept. A refusal (the hub ended the job already) is final.
39
c3db750e Andy McCall 40
- **The Rust build image vendors mimalloc (#20).** Oxygen's new allocator was missing from the image, so oxygen's runs #150 to #153 failed. The image was rebuilt with `images/rust/build.sh`, imported on Earth and pinned in the oxygen, oxygenhub and oxygenflow pipelines. Rebuild it whenever a `Cargo.lock` of those projects changes.
41
- **A hint for shell escapes in a pipeline.** KDL 2.0 strings have no `\033`, `\e` or `\x` escapes; a pipeline that uses one (for ANSI colours, say) is still invalid, but `flow check` and the hub now name the line and say to write ESC as `\u{1b}`.