Skip to content

Add YAML workflow language and execution #852

Add YAML workflow language and execution

Add YAML workflow language and execution #852

Workflow file for this run

name: Rust CI
on:
push:
branches: [ main, ci ]
pull_request:
branches: [ main ]
# A second push to the same branch makes the in-flight run obsolete. The
# three-OS test matrix is the expensive part, so cancelling early matters
# more here than it did when every job was a single ubuntu runner.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
format:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: Swatinem/rust-cache@v2
- name: Install stable toolchain
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- name: Run cargo fmt
run: cargo fmt --all --check
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: Swatinem/rust-cache@v2
- name: Install stable toolchain
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- name: Run cargo check
run: cargo check
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: Swatinem/rust-cache@v2
- name: Install stable toolchain
uses: dtolnay/rust-toolchain@stable
with:
components: clippy
# `--all-targets` so test code is linted too, not just what ships. It
# is the larger half of some modules, and was going unchecked.
- name: Run cargo clippy
run: cargo clippy --all-targets -- -D warnings
# Unit tests on all three supported platforms. `format`/`lint`/`audit`
# stay ubuntu-only on purpose: rustfmt, clippy and the advisory database
# are platform-independent, so running them three times would only spend
# runner minutes to reach the same verdict. What is genuinely per-platform
# is whether the code compiles and behaves the same — that is this job.
#
# No weights are fetched here, and no test that needs a real GGUF runs. CI
# is a compile-and-behaviour gate; anything that would have it download or
# cache multi-gigabyte weights belongs on a developer machine, behind
# `--ignored` and `ORANGU_TEST_MODEL`.
test:
name: test (${{ matrix.os }})
runs-on: ${{ matrix.os }}
timeout-minutes: 30
strategy:
# One platform failing should not hide whether the other two pass —
# that is the whole point of testing on three.
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- uses: actions/checkout@v5
- name: Install stable toolchain
uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
with:
key: ${{ matrix.os }}
- name: Run cargo test
run: cargo test
# `coop_tiles_are_vec4_only_where_component_stores_work` already probes
# the one thing that decides whether the tiled GEMM's *weight* tile can
# be `vec4` here: whether four threads writing four components of one
# shared vector all survive a barrier. On Metal the answer has been no,
# so `coop_vec4_tiles` gives that tile the scalar form.
#
# The probe reports its verdict through `eprintln!`, which `cargo test`
# captures and then discards on a pass — so the fact is computed on
# every run and recorded nowhere. That matters now for a specific
# reason: the "no" was measured on an Apple Paravirtual device, and this
# runner is `aarch64-apple-darwin`. If real Apple silicon does honour
# component stores, half of the tiled GEMM is leaving its `vec4` reads
# on the table for a reason that no longer holds.
#
# So run it once more with `--nocapture` purely to surface the answer.
# Not a gate — the test itself is already the gate, and it is in the
# ordinary suite above. This step only makes what it learned readable.
- name: Report Metal shared-memory store behaviour
if: matrix.os == 'macos-latest'
shell: bash
run: |
set -euo pipefail
# Both filters after `--`: `cargo test` takes only one positional
# test name, libtest takes several.
cargo test --bin orangu-server -- --nocapture \
engine::backend::vulkan::tests::coop_tiles_are_vec4_only_where_component_stores_work \
engine::backend::vulkan::tests::shared_vec4_whole_stores_survive_a_barrier \
| tee probe.log
grep -q '^test result: ok\. 2 passed' probe.log
if grep -q 'passes the component-store probe' probe.log; then
echo "::notice::This Metal device DOES honour component-wise stores into shared vec4 memory — vec4 tile_w may now be available here (see vulkan_shaders::coop_vec4_tiles)"
else
echo "::notice::This Metal device does not honour component-wise stores into shared vec4 memory; scalar tile_w remains correct"
fi
rm -f probe.log
# `cargo audit` reads the committed `Cargo.lock` and `.cargo/audit.toml`, so
# this job reaches exactly the verdict a local `cargo audit` does.
#
# The `rustsec/audit-check` action that used to run here did not. It called
# `cargo generate-lockfile` first, which throws away the checked-out
# lockfile and re-resolves every dependency to the newest semver-compatible
# version — it audited 709 packages where the lockfile pins 721. A
# vulnerable version pinned in `Cargo.lock`, which is the one that actually
# ships, would be silently upgraded away before the audit saw it and the job
# would go green. Auditing a resolution nothing builds from is worse than
# not auditing, because it looks like coverage.
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: Install stable toolchain
uses: dtolnay/rust-toolchain@stable
# Caches `~/.cargo/bin` too, so `cargo audit` is only built when the
# lockfile moves rather than on every run.
- uses: Swatinem/rust-cache@v2
with:
key: audit
- name: Install cargo-audit
run: cargo install cargo-audit --locked
- name: Run cargo audit
run: cargo audit