name: jouleclaw fabrics # Every compute fabric gets built, on hardware that has the device. # # `metal` did not compile at all -- 3063 errors -- because no job ever built # it: 40 architecture files carried `#[cfg(feature = "metal")]` blocks that had # never once been compiled. An unbuilt feature does not stay still, it drifts, # and nothing here would have noticed. So each fabric's error count is pinned # and may fall but never rise. # # A baseline above zero is a debt, not a pass. Zero means the fabric compiles, # which is still not the same as working: none of these runs a kernel yet. # # `rocm` has no job because `rocm = []` declares a feature with no dependencies # and no code. It compiles perfectly while providing nothing, and a green check # would report health it does not have. # # Nightly and path-filtered: the fleet's queue is the scarce resource, and these # numbers move only when someone edits this crate. concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true on: schedule: # 07:00 UTC daily. Forge cron is UTC. - cron: '0 7 * * *' pull_request: paths: - 'jouleclaw/jouleclaw-rs/crates/jouleclaw-omni/**' - 'jouleclaw/jouleclaw-rs/Cargo.toml' - 'jouleclaw/jouleclaw-rs/Cargo.lock' - 'scripts/check-fabric-errors.py' - 'scripts/check-metal-shaders.py' - '.github/workflows/jouleclaw-fabrics.yml' workflow_dispatch: jobs: metal: name: metal (macOS, Apple GPU) # Metal is macOS-only, so this is the one runner that can build it. runs-on: macos timeout-minutes: 60 steps: - uses: actions/checkout@v5 # launchd's PATH omits cargo on the macOS host runner. - name: Put cargo on PATH shell: bash run: echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" - name: metal's error count may fall, never rise shell: bash run: python3 scripts/check-fabric-errors.py metal # compile_pipeline builds every shader at runtime, so an MSL error is # invisible to cargo. xcrun is the same frontend the runtime uses. - name: every Metal shader source must compile shell: bash run: python3 scripts/check-metal-shaders.py # Compiling a kernel says nothing about what it computes. This runner # has a GPU, so the kernels are dispatched and checked against CPU # references here. - name: Metal kernels must compute the right thing shell: bash run: | set -euo pipefail M=jouleclaw/jouleclaw-rs/Cargo.toml # tests/metal_kernels.rs is behind `#![cfg(feature = "metal")]`. If # that cfg ever stops holding the file compiles to nothing, the # target runs 0 tests, and cargo exits 0 -- a green check for a # suite that did not run. Count the tests before trusting the run. n=$(cargo test --manifest-path "$M" -p jouleclaw-omni --features metal \ --test metal_kernels -- --list 2>/dev/null | grep -c ': test$') echo "metal_kernels declares $n tests" if [ "$n" -lt 26 ]; then echo "::error::metal_kernels declares $n tests, expected at least 26." echo "::error::Either the metal cfg stopped holding or tests were removed." exit 1 fi # Run every target, not just that one. `--test metal_kernels` left # the crate's 46 metal-gated *lib* tests unrun: a feature's unit # tests are as invisible to CI as its code was. cargo test --manifest-path "$M" -p jouleclaw-omni --features metal linux-fabrics: name: ${{ matrix.feature }} (linux, RTX 4050 + Vulkan loader) # The host runner, not the docker one: cudarc wants the CUDA toolkit at # /usr/local/cuda and ash wants the system Vulkan loader, and this host has # both beside an actual NVIDIA GPU. These features have only ever been # built on macOS, where neither device exists. runs-on: linux-hw timeout-minutes: 90 strategy: fail-fast: false matrix: feature: [cuda, vulkan] steps: # This host has no Node, so actions/checkout cannot run here. - name: Fetch the source shell: bash run: | set -euo pipefail want="${{ github.event.pull_request.head.sha || github.sha }}" rm -rf src && mkdir src && cd src git init -q # Fetch the commit itself, not the ref: a later commit on the ref # that this workflow's paths do not match would be fetched instead. git fetch -q --depth 1 http://100.64.224.0:3400/Transaction-Science/open-standards.git "$want" git checkout -q FETCH_HEAD got="$(git rev-parse HEAD)" [ "$got" = "$want" ] || { echo "::error::fetched $got, not $want"; exit 1; } - name: ${{ matrix.feature }}'s error count may fall, never rise shell: bash working-directory: src run: | # nvcc is not on this host's PATH, and cudarc's # cuda-version-from-build-system feature asks nvcc which CUDA this is. export PATH="$HOME/.cargo/bin:/usr/local/cuda/bin:$PATH" python3 scripts/check-fabric-errors.py ${{ matrix.feature }}