name: CI on: push: branches: - master pull_request: workflow_dispatch: jobs: build-and-test: runs-on: ubuntu-latest timeout-minutes: 30 steps: - name: Check out source uses: actions/checkout@v4 - name: Install Lore CLI run: | scripts/install-lore.sh "$RUNNER_TEMP/lore-bin" echo "$RUNNER_TEMP/lore-bin" >> "$GITHUB_PATH" - name: Select Lore asset branch run: | branch=main if [[ "$GITHUB_EVENT_NAME" == pull_request ]]; then branch="$(python3 -c 'import json, os; e=json.load(open(os.environ["GITHUB_EVENT_PATH"], encoding="utf-8")); p=e["pull_request"]; print(p["head"]["ref"] if p["head"]["repo"]["full_name"] == os.environ["GITHUB_REPOSITORY"] else "main")')" fi echo "LORE_BRANCH=$branch" >> "$GITHUB_ENV" echo "Using Lore branch: $branch" - name: Fetch assets from Lore env: LORE_CI_USERNAME: ${{ secrets.LORE_CI_USERNAME }} LORE_CI_PASSWORD: ${{ secrets.LORE_CI_PASSWORD }} LORE_AUTH_URL: https://auth.eirexe.moe run: scripts/update-assets.sh "$LORE_BRANCH" - name: Install Rust toolchain run: | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | \ sh -s -- -y --profile minimal echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" "$HOME/.cargo/bin/rustup" toolchain install nightly-2026-09-14 --profile minimal - name: Cache Rust dependencies and build artifacts uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 with: prefix-key: v2-rust shared-key: linux-nightly cache-bin: false - name: Install Linux dependencies run: | sudo apt-get update sudo apt-get install --no-install-recommends -y \ clang \ libasound2-dev \ libudev-dev \ libusb-1.0-0-dev \ libwayland-dev \ libx11-dev \ libxkbcommon-dev \ libxkbcommon-x11-0 \ mesa-vulkan-drivers \ mold \ pkg-config - name: Build run: cargo build --locked -j 4 - name: Run unit tests run: cargo test --locked --lib -j 4 production-build: runs-on: ubuntu-latest timeout-minutes: 45 steps: - name: Check out source uses: actions/checkout@v4 - name: Install Lore CLI run: | scripts/install-lore.sh "$RUNNER_TEMP/lore-bin" echo "$RUNNER_TEMP/lore-bin" >> "$GITHUB_PATH" - name: Select Lore asset branch run: | branch=main if [[ "$GITHUB_EVENT_NAME" == pull_request ]]; then branch="$(python3 -c 'import json, os; e=json.load(open(os.environ["GITHUB_EVENT_PATH"], encoding="utf-8")); p=e["pull_request"]; print(p["head"]["ref"] if p["head"]["repo"]["full_name"] == os.environ["GITHUB_REPOSITORY"] else "main")')" fi echo "LORE_BRANCH=$branch" >> "$GITHUB_ENV" echo "Using Lore branch: $branch" - name: Fetch assets from Lore env: LORE_CI_USERNAME: ${{ secrets.LORE_CI_USERNAME }} LORE_CI_PASSWORD: ${{ secrets.LORE_CI_PASSWORD }} LORE_AUTH_URL: https://auth.eirexe.moe run: scripts/update-assets.sh "$LORE_BRANCH" - name: Install Rust toolchain run: | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | \ sh -s -- -y --profile minimal echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" "$HOME/.cargo/bin/rustup" toolchain install nightly-2026-09-14 --profile minimal - name: Install Windows build tooling run: | "$HOME/.cargo/bin/rustup" target add x86_64-pc-windows-msvc --toolchain nightly-2026-09-14 "$HOME/.cargo/bin/cargo" install cargo-xwin --locked - name: Cache production Rust dependencies and build artifacts uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 with: prefix-key: v2-rust shared-key: linux-nightly-production cache-bin: false - name: Install Linux dependencies run: | sudo apt-get update sudo apt-get install --no-install-recommends -y \ clang-19 \ libasound2-dev \ libudev-dev \ libusb-1.0-0-dev \ libwayland-dev \ libx11-dev \ libxkbcommon-dev \ libxkbcommon-x11-0 \ lld-19 \ llvm-19 \ mesa-vulkan-drivers \ mold \ pkg-config sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-19 100 sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-19 100 echo "/usr/lib/llvm-19/bin" >> "$GITHUB_PATH" rm -f "$HOME/.cache/cargo-xwin/clang-cl" - name: Install pinned Blender run: | scripts/install-blender.sh "$RUNNER_TEMP/blender" echo "BLENDER=$RUNNER_TEMP/blender/blender" >> "$GITHUB_ENV" - name: Preprocess assets run: cargo run --locked --bin process-assets --no-default-features --features debug_features -j 4 - name: Verify processed battlefield asset run: | python3 - <<'PY' import json import struct path = "imported_assets/Default/stages/battlefield/bf2.blend" with open(path, "rb") as asset: header = asset.read(12) if len(header) != 12: raise SystemExit(f"processed asset is truncated: {path}") magic, version, length = struct.unpack("<4sII", header) if magic != b"glTF" or version != 2 or length != asset.seek(0, 2): raise SystemExit(f"processed asset is not a valid GLB: {path}") asset.seek(12) json_length, chunk_type = struct.unpack("