# Workspace gate: the same clippy + test commands CLAUDE.md §6 requires # locally, run on every master push and pull request. Until this workflow # existed, nothing in CI ran the test suite at all — a direct push to # master was entirely unguarded. # # Build caching (2026-07-13): the Gitea actions cache never restored on # this instance — every run back through run 597 logged "No cache found" # even for exact keys saved successfully ("Cache saved successfully") by # a run an hour earlier, including master→master restores. Until the # cache server on the runner host is fixed, Swatinem/rust-cache is pure # overhead here. `rust-host` is a HOST executor (its filesystem persists # between runs — ~/.cargo and the rustup toolchain already carry over), # so we get warm builds by pointing CARGO_TARGET_DIR at a persistent # path on the runner instead of tarring gigabytes through a cache API # that never returns them. Concurrent runs are safe: cargo serialises # on the target-dir lock. name: Test on: push: branches: [master] paths: - 'solitaire_app/**' - 'solitaire_assetgen/**' - 'solitaire_core/**' - 'solitaire_data/**' - 'solitaire_engine/**' - 'solitaire_server/src/**' - 'solitaire_server/tests/**' - 'solitaire_server/migrations/**' - 'solitaire_sync/**' - 'solitaire_wasm/**' - 'solitaire_web/**' - 'Cargo.toml' - 'Cargo.lock' - '.cargo/**' - '.sqlx/**' - '.gitea/workflows/test.yml' pull_request: workflow_dispatch: jobs: # Seconds-long formatting gate in its own job so a rustfmt slip fails # here instead of after a 35-minute cold build (run 600 spent its # whole build budget to report an unformatted file). fmt: runs-on: rust-host steps: - name: Checkout uses: actions/checkout@v4 - name: Install Rust 1.95.0 uses: dtolnay/rust-toolchain@master with: toolchain: 1.95.0 components: rustfmt - name: Format check run: cargo fmt --check test: runs-on: rust-host needs: fmt # Full debuginfo made the solitaire_engine test-binary link peak past the # runner's memory — ld was OOM-killed (signal 9) on runs 447 and 486. # line-tables-only keeps file:line in panic backtraces while cutting the # link's memory footprint enough to fit the runner. # # CARGO_BUILD_JOBS=2: with one job per core, cargo links several large # test binaries concurrently; as the workspace grew (runs 514/516/519) # two+ simultaneous ld processes OOM-killed the runner again even at # line-tables-only. Two jobs keeps at most two links in flight — the # compile-throughput cost is small next to the warm build. # # CARGO_INCREMENTAL=0: incremental artifacts bloat the persistent # target dir for little benefit in CI (rust-cache used to set this # for the same reason). # # CARGO_TARGET_DIR: persistent on the runner host — see the header # comment. The prune step below keeps it from growing unbounded. env: CARGO_PROFILE_DEV_DEBUG: line-tables-only CARGO_BUILD_JOBS: '2' CARGO_INCREMENTAL: '0' CARGO_TARGET_DIR: /home/runner/.cache/ferrous-solitaire/target steps: - name: Checkout uses: actions/checkout@v4 - name: Install Rust 1.95.0 uses: dtolnay/rust-toolchain@master with: toolchain: 1.95.0 components: clippy # Toolchain or lockfile bumps strand stale artifacts nothing will # ever reuse; reset the dir when it crosses 40 GiB rather than # curating it (a cold rebuild every few weeks is cheaper than the # bookkeeping). - name: Prune persistent target dir when oversized run: | limit_kb=$((40 * 1024 * 1024)) used_kb=$(du -sk "$CARGO_TARGET_DIR" 2>/dev/null | cut -f1 || echo 0) echo "persistent target dir: $((used_kb / 1024)) MiB (limit $((limit_kb / 1024)) MiB)" if [ "${used_kb:-0}" -gt "$limit_kb" ]; then echo "over limit — clearing for a fresh cold build" rm -rf "$CARGO_TARGET_DIR" fi # Native link deps for the Bevy crates (engine/app/web) on a bare # ubuntu runner: ALSA + udev for input/audio, X11 + Wayland for winit. - name: Install Bevy native dependencies run: | sudo apt-get update sudo apt-get install -y --no-install-recommends \ libasound2-dev libudev-dev pkg-config libx11-dev libxcursor-dev \ libxrandr-dev libxi-dev libwayland-dev libxkbcommon-dev # SQLX_OFFLINE uses the checked-in `.sqlx/` query cache (no live DB), # same as the web-e2e workflow's server prebuild. - name: Clippy (deny warnings) env: SQLX_OFFLINE: 'true' run: cargo clippy --workspace --all-targets -- -D warnings - name: Test env: SQLX_OFFLINE: 'true' run: cargo test --workspace