OXYGENHUB

ci: OxygenFlow pipeline, and Git's own files ignored 3bf01e6e95ae

.flow/pipeline.kdl builds the shared server as C11 with every warning an
error and compiles the Python, then runs the conformance suite against
the RRDC fork of x16emu, launched headless in the guest, with pytest's
JUnit report kept for the hub's Tests tab. A run that skips every test
fails: the emulator is always there to reach.

.oxyignore leaves out .git and .git* (.gitignore, .gitattributes,
.gitmodules, .github/) with what .gitignore left out, and .gitignore is
no longer tracked: the history lives in Oxygen now.
Author
Andy McCall @andymccall <[email protected]>
When
· 2026-10-10 20:04 UTC
Signature
✔ signed by Andy McCall
Hash
3bf01e6e95ae465b33c4034797e0a4fd662cd2be41eb4e8b6fcf2ddc46ac4d81
Depends on
961b3c610c66
Depended on by
nothing yet
In bookmarks
main perf-6
Edits
4 atoms, 7 tree operations, 5 files

Browse the tree at this change

added .flow/jobs/build.sh +10 −0
1 +
# The shared server (core/) as a consumer would compile it: C11, POSIX, every
2 +
# warning an error. Then the Python client and the conformance suite.
3 +
set -eu
4 +
out=$(mktemp -d)
5 +
gcc -std=c11 -D_POSIX_C_SOURCE=200809L -Wall -Wextra -Werror -O2 \
6 +
    -c core/retro_control.c -o "$out/retro_control.o"
7 +
echo "core/retro_control.c: compiled cleanly (C11, -Wall -Wextra -Werror)"
8 +
python3 -m py_compile client/emu_control.py conformance/conftest.py conformance/test_conformance.py
9 +
echo "client/ and conformance/: Python compiles"
10 +
rm -rf "$out"
added .flow/jobs/test.sh +22 −0
1 +
# The conformance suite against the reference emulator: the RRDC fork of
2 +
# x16emu in the image, launched headless by the suite on a loopback port.
3 +
set -eu
4 +
export RRDC_PORT=8391
5 +
export RRDC_BOOT_TIMEOUT=60
6 +
export RRDC_EMU_CMD="SDL_VIDEODRIVER=dummy SDL_AUDIODRIVER=dummy /opt/x16emu/x16emu -rom /opt/x16emu/rom.bin -warp -controlport {port}"
7 +
status=0
8 +
python3 -m pytest -v -rs --junitxml=/src/junit.xml conformance || status=$?
9 +
# A suite that skipped every test never reached the emulator: that is a
10 +
# failure here, where one is always there to reach.
11 +
python3 - <<'PY'
12 +
import sys
13 +
import xml.etree.ElementTree as ET
14 +
root = ET.parse("/src/junit.xml").getroot()
15 +
suites = [root] if root.tag == "testsuite" else list(root)
16 +
tests = sum(int(s.get("tests", 0)) for s in suites)
17 +
skipped = sum(int(s.get("skipped", 0)) for s in suites)
18 +
print(f"conformance: {tests} tests, {skipped} skipped")
19 +
if tests == 0 or skipped == tests:
20 +
    sys.exit("conformance: every test skipped: the emulator did not answer on its control port")
21 +
PY
22 +
exit $status
added .flow/pipeline.kdl +48 −0
1 +
// retro-remote-debug-controller's pipeline on OxygenFlow: every push to a
2 +
// bookmark on OxygenHub runs it in Firecracker microVMs; the jobs appear as
3 +
// checks on the change and in the Flow tab.
4 +
schema-version 1
5 +
6 +
// The X16 toolchain image Metal Gear and Super Mario Land build with: gcc,
7 +
// Python with pytest, and the RRDC fork of x16emu with its ROM in
8 +
// /opt/x16emu (the reference emulator of this repository's contract).
9 +
// Re-pin it when theirs is rebuilt.
10 +
sandbox "x16" {
11 +
    runtime "microvm"
12 +
    rootfs "cas://blob/8b6bb0c6452f4c6fef50704a5cc6f27722900686caf55061415f20c21feb5c51"
13 +
    memory-limit "1GiB"
14 +
    cpu-limit 2
15 +
    network "isolated"
16 +
}
17 +
18 +
// The same image with the guest's loopback up: the conformance suite talks
19 +
// to the emulator's control port on 127.0.0.1. Nothing leaves the guest.
20 +
sandbox "x16-loopback" {
21 +
    runtime "microvm"
22 +
    rootfs "cas://blob/8b6bb0c6452f4c6fef50704a5cc6f27722900686caf55061415f20c21feb5c51"
23 +
    memory-limit "2GiB"
24 +
    cpu-limit 2
25 +
    network "loopback"
26 +
}
27 +
28 +
// The shared server compiles cleanly as C11 with every warning an error,
29 +
// and the Python client and suite compile.
30 +
job "build" {
31 +
    sandbox "x16"
32 +
    exec "sh" "-eu" ".flow/jobs/build.sh"
33 +
}
34 +
35 +
// The conformance suite against the reference emulator, launched headless
36 +
// in the guest; pytest's JUnit XML for the hub's Tests tab, kept when the
37 +
// job fails too.
38 +
job "conformance" {
39 +
    sandbox "x16-loopback"
40 +
    depends-on "build"
41 +
    exec "sh" "-eu" ".flow/jobs/test.sh"
42 +
    output {
43 +
        artifact "junit" {
44 +
            path "/src/junit.xml"
45 +
            when "always"
46 +
        }
47 +
    }
48 +
}
added .oxyignore +34 −0
1 +
# Git's own files: the history lives in Oxygen now. `.git*` also covers
2 +
# .gitignore, .gitattributes, .gitmodules and .github/.
3 +
.git
4 +
.git*
5 +
6 +
# Python
7 +
__pycache__/
8 +
*.pyc
9 +
.venv/
10 +
venv/
11 +
.pytest_cache/
12 +
.ruff_cache/
13 +
14 +
# C build artefacts
15 +
*.o
16 +
*.a
17 +
*.so
18 +
build/
19 +
# automake in-tree artefacts (when a consumer compiles core/ where it sits,
20 +
# e.g. the mednafen fork vendoring this as a submodule)
21 +
.deps/
22 +
.dirstamp
23 +
24 +
# Flow test reports written by .flow/jobs/test.sh
25 +
junit.xml
26 +
27 +
# Editor / OS
28 +
.vscode/
29 +
.idea/
30 +
*.swp
31 +
.DS_Store
32 +
33 +
# AI
34 +
.claude
removed .gitignore +0 −0
…
15 unchanged lines