# Fast checks always run; native builds run for code/CI changes. # PRs test what they touch; main and nightly test everything. On a pull request the "Select # checks" job maps the changed files to workspace packages (scripts/ci/affected.py), adds the # packages that depend on them, and Clippy, the test archive and the test shards cover only # those. Changes to the lockfile, root manifest, toolchain/cargo/nextest config, .github/, # vendor/, tests/, scripts/ or any file no package owns select the whole workspace, as do # pushes to main, the nightly run and Run workflow. # Tests are built once and run in 4 shards. A few heavy tests (see .config/nextest.toml) are # skipped on pull requests and run on pushes to main and nightly. The Windows jobs (D3D12 shaders # and app startup) run on pull requests only when what they test changes (the GPU crate, the app, # the viewport's GPU glue, the graphics dependencies, their scripts or this file); main and # nightly always run them. Only main saves the build caches; pull requests restore them. # Cross-compilation is opt-in through Run workflow; release builds remain in release.yml. # Pushes to main and merge-queue groups use both pools: Clippy, the doc tests and test shards # 1-2 run on the self-hosted runner (`self-hosted-fast`, warm build directories via # scripts/ci/warm-target.sh), everything else on GitHub's runners. The test archive is built on # GitHub's runners: the self-hosted machine has a newer glibc, so its binaries wouldn't start # on ubuntu-24.04, while the archive runs there unchanged (same /home/runner/work checkout # path). Pull requests, the nightly run and Run workflow use GitHub's runners only; the # self-hosted runner refuses any job that isn't a push to main or a merge-queue group. name: CI on: pull_request: # The merge queue: each queued group runs the full suite before it lands on main. merge_group: push: branches: [main] schedule: - cron: "17 6 * * *" workflow_dispatch: inputs: cross_compile: description: "Also check WebAssembly and RISC-V (before a release)" type: boolean default: false permissions: contents: read concurrency: # A new PR push replaces the old run. Only one run per group may wait, so a busy main would # cancel the waiting nightly (or a Run workflow) before it starts: they get groups of their own. group: ci-${{ github.event_name }}-${{ github.ref }} cancel-in-progress: ${{ github.event_name == 'pull_request' }} env: CARGO_TERM_COLOR: always jobs: dependency-advisories: name: Dependency advisories if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' runs-on: ubuntu-24.04 timeout-minutes: 20 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: dtolnay/rust-toolchain@stable - name: Install advisory scanner run: cargo install cargo-deny --version 0.20.2 --locked - name: Check locked dependencies run: cargo deny --locked check --warn unmaintained advisories bans sources changes: name: Select checks runs-on: ubuntu-24.04 outputs: native: ${{ steps.paths.outputs.native }} kernel: ${{ steps.paths.outputs.kernel }} windows: ${{ steps.paths.outputs.windows }} full: ${{ steps.paths.outputs.full }} packages: ${{ steps.paths.outputs.packages }} steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 - id: paths name: Detect code and CI changes env: EVENT_NAME: ${{ github.event_name }} BASE_SHA: ${{ github.event.pull_request.base.sha }} HEAD_SHA: ${{ github.event.pull_request.head.sha }} run: | native=false kernel=false windows=false full=true packages= if [ "$EVENT_NAME" != pull_request ]; then native=true windows=true else # Compare both old and new paths of renames; unknown paths run native checks. git diff --no-renames --name-only -z "$BASE_SHA...$HEAD_SHA" > "$RUNNER_TEMP/ci-paths" while IFS= read -r -d '' path; do case "$path" in crates/kernel/*|vendor/truck-*) kernel=true ;; esac # What the Windows D3D12 jobs exercise: the GPU crate and its shaders, the app and # its startup, the viewport's wgpu glue, the vendored egui-wgpu, their scripts. case "$path" in crates/gpu/*|apps/solidcraft/*|crates/ui-egui/src/gpu.rs|vendor/egui-wgpu/*) windows=true ;; tools/windows-*.ps1|.github/workflows/ci.yml|rust-toolchain*|.cargo/*) windows=true ;; esac case "$path" in .github/workflows/ci.yml) native=true ;; *.rs|Cargo.toml|Cargo.lock|*/Cargo.toml|.cargo/*|rust-toolchain*) native=true ;; docs/*|*.md|.github/*|packaging/*|LICENSE*|NOTICE|THIRD-PARTY-LICENSES.txt) ;; *) native=true ;; esac done < "$RUNNER_TEMP/ci-paths" # A lockfile change that moves the graphics stack (wgpu, naga, egui, winit, windows). if [ "$windows" = false ] && grep -qxz 'Cargo.lock' "$RUNNER_TEMP/ci-paths" \ && git diff "$BASE_SHA...$HEAD_SHA" -- Cargo.lock \ | grep -Eq '^[ +-]name = "(wgpu[a-z_-]*|naga|egui[a-z_-]*|eframe|winit|windows[a-z_-]*|d3d12)"'; then windows=true fi # Pull requests build and test the touched packages and their dependents. python3 -I scripts/ci/affected.py --paths "$RUNNER_TEMP/ci-paths" > "$RUNNER_TEMP/ci-affected" cat "$RUNNER_TEMP/ci-affected" full=$(sed -n 's/^full=//p' "$RUNNER_TEMP/ci-affected") packages=$(sed -n 's/^packages=//p' "$RUNNER_TEMP/ci-affected") # Code changed but nothing was selected: be safe and test everything. if [ "$native" = true ] && [ "$full" != true ] && [ -z "$packages" ]; then full=true; fi fi { echo "native=$native" echo "kernel=$kernel" echo "windows=$windows" echo "full=$full" echo "packages=$packages" } >> "$GITHUB_OUTPUT" checks: name: Format and repository checks runs-on: ubuntu-24.04 timeout-minutes: 15 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: dtolnay/rust-toolchain@stable with: components: rustfmt - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 with: key: repo-checks save-if: ${{ github.ref == 'refs/heads/main' }} - name: Format run: cargo fmt --all -- --check - name: Asset attribution run: cargo xtask assets - name: UI icon standards and review tool run: cargo xtask icons - name: Licences run: cargo xtask licences --check - name: Dependency layers run: cargo xtask layers - name: Web app offline use and updates (headless Chrome) run: cargo xtask web-offline-test - name: Affected-package selection self-test run: python3 -I scripts/ci/test_affected.py - name: Claim bot tests run: node --test scripts/claim/*.test.js clippy: name: Native Linux Clippy needs: changes if: needs.changes.outputs.native == 'true' runs-on: ${{ (github.event_name == 'merge_group' || (github.event_name == 'push' && github.ref == 'refs/heads/main')) && 'self-hosted-fast' || 'ubuntu-24.04' }} timeout-minutes: 30 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Warm build directory (self-hosted runner) if: runner.environment == 'self-hosted' run: scripts/ci/warm-target.sh clippy - uses: dtolnay/rust-toolchain@stable with: components: clippy # The self-hosted runner keeps its build directory and Cargo home instead. - if: runner.environment == 'github-hosted' uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 with: key: native-clippy save-if: ${{ github.ref == 'refs/heads/main' }} - name: Clippy env: FULL: ${{ needs.changes.outputs.full }} PACKAGES: ${{ needs.changes.outputs.packages }} run: | # Pull requests lint the affected packages (scripts/ci/affected.py); everything else, all. scope=(--workspace) if [ "$FULL" != true ]; then scope=(); for p in $PACKAGES; do scope+=(-p "$p"); done; fi cargo clippy "${scope[@]}" --all-targets --profile ci --locked -- -D warnings build-tests: name: Build tests needs: changes if: needs.changes.outputs.native == 'true' runs-on: ubuntu-24.04 timeout-minutes: 45 env: CARGO_INCREMENTAL: "0" RUSTC_WRAPPER: sccache SCCACHE_GHA_ENABLED: "true" SCCACHE_IGNORE_SERVER_IO_ERROR: "1" steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 with: key: native-tests save-if: ${{ github.ref == 'refs/heads/main' }} - name: Set up compiler cache uses: mozilla-actions/sccache-action@fc920bf0ec8de6ee65d409111f7ec508035751ba # v0.0.11 with: version: v0.16.0 - uses: taiki-e/install-action@1168f6810a3cb30a3514bf5756a3b7f0422c6df8 # v2.87.28 with: tool: cargo-nextest - name: Compile tests into a nextest archive env: FULL: ${{ needs.changes.outputs.full }} PACKAGES: ${{ needs.changes.outputs.packages }} run: | # Pull requests archive only the affected packages (scripts/ci/affected.py). scope=(--workspace) if [ "$FULL" != true ]; then scope=(); for p in $PACKAGES; do scope+=(-p "$p"); done; fi cargo nextest archive "${scope[@]}" --cargo-profile ci --locked --archive-file tests.tar.zst - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 with: name: nextest-archive path: tests.tar.zst retention-days: 1 compression-level: 0 - name: Compiler cache statistics if: always() run: sccache --show-stats tests: name: Native Linux tests (${{ matrix.shard }}/4) needs: [changes, build-tests] runs-on: ${{ ((github.event_name == 'merge_group' || (github.event_name == 'push' && github.ref == 'refs/heads/main')) && matrix.shard <= 2) && 'self-hosted-fast' || 'ubuntu-24.04' }} timeout-minutes: 60 strategy: fail-fast: false matrix: shard: [1, 2, 3, 4] env: # Pictures (snapshots, screenshots, ui.render, the viewport's offscreen tests) are drawn on # the GPU. The runner has none: Mesa's lavapipe (software Vulkan) draws them, and a test that # would skip for want of an adapter fails instead. SOLIDCRAFT_GPU: software SOLIDCRAFT_REQUIRE_GPU: "1" steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Install a software Vulkan driver (lavapipe) # Preinstalled on the self-hosted runner, which has no sudo. if: runner.environment == 'github-hosted' run: | sudo apt-get update sudo apt-get install -y --no-install-recommends mesa-vulkan-drivers libvulkan1 - uses: taiki-e/install-action@1168f6810a3cb30a3514bf5756a3b7f0422c6df8 # v2.87.28 with: tool: cargo-nextest - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 with: name: nextest-archive - name: Run tests env: EVENT_NAME: ${{ github.event_name }} SHARD: ${{ matrix.shard }} run: | # Pull requests skip the heavy tests (default-filter in .config/nextest.toml). all=() # The boolean property tests draw new random inputs every run; they run only in the # nightly property-tests job, so a known kernel bug cannot turn main red at random. if [ "$EVENT_NAME" != pull_request ]; then all=(--ignore-default-filter -E 'not (package(solidcraft-kernel) & binary(boolean_props))') fi # Extract into ./target: tests that run a built binary (env!("CARGO_BIN_EXE_*")) have # the build job's path, which is the same checkout path here. cargo nextest run --archive-file tests.tar.zst --workspace-remap . --extract-to . --extract-overwrite \ --profile ci --partition "slice:$SHARD/4" --no-tests=pass "${all[@]}" - name: Robustness goldens sample (pull requests that touch the kernel) # Every 8th seed of tests/robustness/goldens.json (each seed is a test), a quarter per # shard; pushes to main and the nightly run every seed in the step above. if: github.event_name == 'pull_request' && needs.changes.outputs.kernel == 'true' env: SHARD: ${{ matrix.shard }} run: | cargo nextest run --archive-file tests.tar.zst --workspace-remap . --extract-to . --extract-overwrite \ --profile ci --ignore-default-filter --partition "slice:$SHARD/4" --no-tests=pass \ -E 'package(solidcraft-engine) & test(/^tests::robustness_goldens::seed_(00|08|16|24|32|40|48|56|64|72|80|88)$/)' - name: Upload test timings if: always() uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 with: name: junit-${{ matrix.shard }} path: target/nextest/ci/junit.xml retention-days: 7 action-matrix: # Every ordinary action on every face, edge, vertex and body of the design corpus, against # tests/action_matrix/baseline.json (docs/action-matrix.md). Every test run checks a sample; # the whole matrix runs nightly (or by hand) in shards of about equal cost, cut by # tests/action_matrix/costs.json. Keep SHARDS in step with the matrix below. name: Action matrix (${{ matrix.shard }}/16) needs: build-tests if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' runs-on: ubuntu-24.04 timeout-minutes: 55 strategy: fail-fast: false matrix: shard: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: taiki-e/install-action@1168f6810a3cb30a3514bf5756a3b7f0422c6df8 # v2.87.28 with: tool: cargo-nextest - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 with: name: nextest-archive - name: Run one shard of the matrix # A step limit below the job's, so the outcomes so far are still uploaded. timeout-minutes: 45 env: SHARDS: 16 SHARD: ${{ matrix.shard }} OUT: ${{ github.workspace }}/action-matrix run: | mkdir -p "$OUT" export ACTION_MATRIX_SHARD="$SHARD/$SHARDS" ACTION_MATRIX_RESULTS="$OUT/results-$SHARD.json" \ ACTION_MATRIX_TIMINGS="$OUT/timings-$SHARD.jsonl" ACTION_MATRIX_WORKDIR="$OUT/raw-$SHARD" cargo nextest run --archive-file tests.tar.zst --workspace-remap . --extract-to . --extract-overwrite \ --profile ci --success-output final --run-ignored only -E "binary(action_matrix) & test(=action_matrix_shard)" - name: Upload the outcomes and timings # `cargo xtask action-matrix --from DIR --bless` (with every shard's files in DIR) # records them in the baseline and costs.json. if: always() uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 with: name: action-matrix-${{ matrix.shard }} path: action-matrix retention-days: 14 action-matrix-determinism: # A sample of the matrix run twice on one runner: every action must come out the same. name: Action matrix determinism needs: build-tests if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' runs-on: ubuntu-24.04 timeout-minutes: 45 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: taiki-e/install-action@1168f6810a3cb30a3514bf5756a3b7f0422c6df8 # v2.87.28 with: tool: cargo-nextest - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 with: name: nextest-archive - name: Run a sample twice run: | cargo nextest run --archive-file tests.tar.zst --workspace-remap . --extract-to . --extract-overwrite \ --profile ci --success-output final --run-ignored only -E "binary(action_matrix) & test(=action_matrix_determinism)" property-tests: # The boolean property tests and the atomic command tests with many cases. Pull requests skip # them (.config/nextest.toml); pushes to main run atomic_commands with small defaults (seeds # 0..4) and skip boolean_props, whose random inputs would fail main at random. name: Property tests (many cases) needs: build-tests if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' runs-on: ubuntu-24.04 timeout-minutes: 60 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: taiki-e/install-action@1168f6810a3cb30a3514bf5756a3b7f0422c6df8 # v2.87.28 with: tool: cargo-nextest - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 with: name: nextest-archive - name: Boolean properties and atomic commands # The defaults (8 cases, seeds 0..4) take 159 s and 802 s on a 2-core VM; four times the # cases and twice the seeds are estimated at about 40 minutes there (not yet timed on CI). env: PROPTEST_CASES: "32" ATOMIC_SEEDS: "0..8" run: | cargo nextest run --archive-file tests.tar.zst --workspace-remap . --extract-to . --extract-overwrite \ --profile ci --ignore-default-filter --success-output final -E "binary(boolean_props) | binary(atomic_commands)" doc-tests: name: Doc tests needs: changes if: needs.changes.outputs.native == 'true' runs-on: ${{ (github.event_name == 'merge_group' || (github.event_name == 'push' && github.ref == 'refs/heads/main')) && 'self-hosted-fast' || 'ubuntu-24.04' }} timeout-minutes: 45 env: CARGO_INCREMENTAL: "0" RUSTC_WRAPPER: sccache SCCACHE_GHA_ENABLED: "true" SCCACHE_IGNORE_SERVER_IO_ERROR: "1" steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Warm build directory (self-hosted runner) if: runner.environment == 'self-hosted' run: scripts/ci/warm-target.sh doc-tests - uses: dtolnay/rust-toolchain@stable # The self-hosted runner keeps its build directory and Cargo home instead. - if: runner.environment == 'github-hosted' uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 with: key: doc-tests save-if: ${{ github.ref == 'refs/heads/main' }} - name: Set up compiler cache uses: mozilla-actions/sccache-action@fc920bf0ec8de6ee65d409111f7ec508035751ba # v0.0.11 with: version: v0.16.0 # nextest does not run doc tests. - run: cargo test --workspace --profile ci --locked --doc oracle: name: Reference tests needs: changes if: needs.changes.outputs.native == 'true' runs-on: ubuntu-24.04 timeout-minutes: 60 env: CARGO_INCREMENTAL: "0" RUSTC_WRAPPER: sccache SCCACHE_GHA_ENABLED: "true" SCCACHE_IGNORE_SERVER_IO_ERROR: "1" steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 with: key: oracle save-if: ${{ github.ref == 'refs/heads/main' }} - name: Set up compiler cache uses: mozilla-actions/sccache-action@fc920bf0ec8de6ee65d409111f7ec508035751ba # v0.0.11 with: version: v0.16.0 - name: Build the command line run: cargo build -p solidcraft-cli --profile ci --locked - name: Replay tests/oracle and compare with expected.json run: cargo xtask oracle --cli target/ci/solidcraft-cli - name: Upload the report if: always() uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 with: name: oracle-report path: docs/oracle.md # D3D12's older shader compiler (FXC, used where dxcompiler.dll is absent) is stricter than # DXC, Vulkan and Metal: a shader it cannot compile once crashed the app at startup. Build the # GPU tessellation pipeline with FXC on the runner's WARP software adapter and compare its # results with the CPU, and draw headless pictures with the viewport's pipelines there # (crates/gpu/tests/capture.rs). windows-fxc: name: Windows D3D12 FXC shaders needs: changes if: needs.changes.outputs.windows == 'true' runs-on: windows-latest timeout-minutes: 45 env: WGPU_BACKEND: dx12 WGPU_DX12_COMPILER: fxc # WARP is a software (Cpu) adapter. SOLIDCRAFT_GPU: software SOLIDCRAFT_REQUIRE_GPU: "1" steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 with: key: windows-fxc save-if: ${{ github.ref == 'refs/heads/main' }} # One test at a time: WARP's shader JIT crashes now and then (a null read in # d3d10warp.dll's JIT optimizer, about 1 run in 60) when several devices compile compute # pipelines at once, which the parallel tests do. Minidumps showed it in WARP itself, not # in SolidCraft or FXC; serial runs never hit it. - run: cargo test -p solidcraft-gpu --profile ci --locked -- --test-threads=1 # The Windows app starts D3D12 first and only the backend it uses (a Vulkan driver crashed the # app at startup on Intel). Start the real app on the runner (its D3D12 adapter is WARP) with # several saved settings and safe mode, and check each draws a frame and quits cleanly. windows-startup: name: Windows app startup needs: changes if: needs.changes.outputs.windows == 'true' runs-on: windows-latest timeout-minutes: 60 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 with: key: windows-startup save-if: ${{ github.ref == 'refs/heads/main' }} - name: Backend order and probing on Windows run: cargo test -p solidcraft --profile ci --locked -- startup::tests native_crash::tests native_frame::tests - name: Build the app run: cargo build -p solidcraft --profile ci --locked - name: Start the app under different settings shell: pwsh run: tools/windows-startup-smoke.ps1 -Exe target/ci/solidcraft.exe - name: Resize border from the first frame shell: pwsh run: tools/windows-resize-smoke.ps1 -Exe target/ci/solidcraft.exe # Preserve the existing check name for branch protection, including docs-only PRs. ci: needs: [changes, checks, clippy, build-tests, tests, doc-tests, oracle, windows-fxc, windows-startup] if: always() runs-on: ubuntu-24.04 steps: - name: Verify required checks env: CHANGES: ${{ needs.changes.result }} CHECKS: ${{ needs.checks.result }} NATIVE: ${{ needs.changes.outputs.native }} WINDOWS: ${{ needs.changes.outputs.windows }} CLIPPY: ${{ needs.clippy.result }} BUILD: ${{ needs.build-tests.result }} TESTS: ${{ needs.tests.result }} DOCS: ${{ needs.doc-tests.result }} ORACLE: ${{ needs.oracle.result }} WINDOWS_FXC: ${{ needs.windows-fxc.result }} WINDOWS_STARTUP: ${{ needs.windows-startup.result }} run: | test "$CHANGES" = success test "$CHECKS" = success if [ "$NATIVE" = true ]; then test "$CLIPPY" = success test "$BUILD" = success test "$TESTS" = success test "$DOCS" = success test "$ORACLE" = success fi if [ "$WINDOWS" = true ]; then test "$WINDOWS_FXC" = success test "$WINDOWS_STARTUP" = success fi wasm: name: Compile WebAssembly (manual) if: github.event_name == 'workflow_dispatch' && inputs.cross_compile runs-on: ubuntu-24.04 timeout-minutes: 30 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: dtolnay/rust-toolchain@stable with: targets: wasm32-unknown-unknown - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 with: key: wasm save-if: ${{ github.ref == 'refs/heads/main' }} - run: cargo xtask wasm riscv64-gates: name: Compile RISC-V (manual) if: github.event_name == 'workflow_dispatch' && inputs.cross_compile runs-on: ubuntu-24.04 timeout-minutes: 30 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Check out craft-fonts uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: repository: storytold/craft-fonts ref: ${{ env.CRAFT_FONTS_REF }} path: craft-fonts - uses: dtolnay/rust-toolchain@stable with: targets: riscv64gc-unknown-linux-gnu - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 with: key: riscv64 save-if: ${{ github.ref == 'refs/heads/main' }} - name: Install cross-compilation dependencies run: | # Ubuntu's regular archive serves amd64; RISC-V packages live in ports. # The 24.04 runner uses deb822 sources, so scope every Ubuntu stanza. sudo sed -i '/^Architectures:/d; /^Types:/a Architectures: amd64' /etc/apt/sources.list.d/ubuntu.sources sudo tee /etc/apt/sources.list.d/riscv64.sources >/dev/null <<'EOF' Types: deb URIs: http://ports.ubuntu.com/ubuntu-ports Suites: noble noble-updates noble-backports noble-security Components: main restricted universe multiverse Architectures: riscv64 Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg EOF sudo dpkg --add-architecture riscv64 sudo apt-get update sudo apt-get install -y gcc-riscv64-linux-gnu libasound2-dev:riscv64 libxkbcommon-dev:riscv64 \ libwayland-dev:riscv64 libx11-dev:riscv64 libxrandr-dev:riscv64 libxi-dev:riscv64 libgl1-mesa-dev:riscv64 - name: Cargo check on RISC-V env: CARGO_TARGET_RISCV64GC_UNKNOWN_LINUX_GNU_LINKER: riscv64-linux-gnu-gcc PKG_CONFIG_SYSROOT_DIR: / PKG_CONFIG_PATH: /usr/lib/riscv64-linux-gnu/pkgconfig:/usr/share/pkgconfig PKG_CONFIG_ALLOW_CROSS: 1 run: | . "$HOME/.cargo/env" export CRAFT_FONTS_DIR="$PWD/craft-fonts" cargo check --all-targets --locked --target riscv64gc-unknown-linux-gnu