1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
name: ci
on:
push:
branches:
pull_request:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: Install icarus-verilog (RTL bit-exactness gate)
run: sudo apt-get update && sudo apt-get install -y iverilog
- name: One version across every package
run: scripts/check-versions.sh
- name: Every C ABI symbol reaches every binding, or the gap is written down
run: scripts/check-parity.sh
# Parity proves the names exist; this proves they compute the same thing. Bindings whose
# toolchain the runner lacks skip; a binding that is present and produces nothing FAILS.
- name: Every binding compiles one model to the same bytes
run: scripts/check-semantics.sh
# Parity proves a symbol is DECLARED in each binding. For Julia that is an @cfn line, which
# says nothing about whether a function wraps it -- both OMMX functions were once declared and
# exported with no body in between, and the module loaded fine.
- name: Every exported binding name resolves
run: scripts/check-exports.sh
- name: Unit tests
run: cargo test --release
# The GPU crate builds everywhere and its tests skip where there is no adapter, so this
# catches an API break on a runner with no driver -- which is every hosted runner.
- name: GPU backend builds, and its tests skip rather than fail without an adapter
run: cargo test --release -p ferrotherm-gpu
# Same shape: no macmon on a Linux runner, so the measuring tests skip and the parsing and
# refusal logic -- which is most of the crate -- still runs.
- name: Power meter builds, and its tests skip rather than fail without a backend
run: cargo test --release -p ferrotherm-meter
# The OMMX bridge hand-rolls protobuf, so the check that matters is the REFERENCE
# implementation reading what it writes. Installed here on purpose; the test skips without it.
- name: OMMX bridge, checked against the reference implementation
run: |
python3 -m pip install --quiet ommx
OMMX_PYTHON=python3 cargo test --release --test ommx_reference
- name: Examples build
run: cargo build --release --examples
- name: Verification examples (exact-physics gates)
run: |
cargo run --release --example ring_tv
cargo run --release --example onsager
c-abi:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: Build the library the header describes
run: cargo build --release
- name: The header compiles and links against it
run: |
cc -I include include/check.c -L target/release -lferrotherm -o /tmp/check
LD_LIBRARY_PATH=target/release /tmp/check
python:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python:
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: actions/setup-python@v5
with:
# The range we CLAIM, not one point in it. requires-python said >=3.9 while CI tested a
# single version, so the floor was a claim nobody had ever run.
python-version: "${{ matrix.python }}"
- name: Build the library the bindings load
run: cargo build --release
- name: Python tests
run: |
pip install pytest
python -m pytest python/test_model.py -q
wasm:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
targets: wasm32-unknown-unknown
- name: wasm cdylib builds clean
run: cargo build --release --lib --target wasm32-unknown-unknown
# Not a byte comparison against a fresh build: a wasm binary is not reproducible across
# toolchain versions, so that fails on a runner whose rustc differs from the author's and
# says nothing about whether the artefact works. What matters is that every symbol the pages
# reach for is present -- a missing export makes the call `undefined`, and calling undefined
# in a click handler leaves the page looking fine and doing nothing.
- name: the committed wasm exports everything the pages call
run: scripts/check-wasm-exports.sh
zig:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: mlugg/setup-zig@v2
with:
version: 0.16.0
# `zig build test` runs cargo itself and links with an rpath, so there is one command here
# rather than a hand-written link line that can drift from what a consumer would use.
- name: Zig tests
working-directory: zig
run: zig build test --summary all
julia:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: julia-actions/setup-julia@v2
with:
version: "1.12"
- name: Build the library the binding loads
run: cargo build --release
- name: Julia tests
working-directory: julia/Ferrotherm
env:
FERROTHERM_LIB: ${{ github.workspace }}/target/release/libferrotherm.so
run: julia --project=. -e 'using Pkg; Pkg.test()'
editor:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "22"
- name: Install
working-directory: web-tests
run: npm install && npx playwright install --with-deps chromium
- name: Browser tests
working-directory: web-tests
run: npm test