From 6fdebd61f5988166fa74ce5fba4be556c7fd48b9 Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Mon, 24 Aug 2026 11:00:22 -0700 Subject: [PATCH 01/50] [bfops/test-runner]: Test runner caching --- .github/workflows/ci.yml | 1608 +------------------------------------- 1 file changed, 1 insertion(+), 1607 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c2395eeb346..cf16b35d321 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,59 +22,9 @@ permissions: pull-requests: read jobs: - merge_queue_noop: - name: Detect merge queue no-op - runs-on: ubuntu-latest - outputs: - skip: ${{ steps.compare.outputs.skip }} - steps: - - name: Checkout merge queue commit - uses: actions/checkout@v4 - - - name: Compare merge queue commit to PR head - id: compare - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - HEAD_REF: ${{ github.event.merge_group.head_ref }} - shell: bash - run: | - set -euo pipefail - - echo "skip=false" >>"$GITHUB_OUTPUT" - - if [[ "${GITHUB_EVENT_NAME}" != "merge_group" ]]; then - echo "Not a merge_group event; running CI normally." - exit 0 - fi - - if [[ ! "${HEAD_REF}" =~ /pr-([0-9]+)- ]]; then - echo "Could not parse PR number from merge group head ref: ${HEAD_REF}" - exit 0 - fi - - pr_number="${BASH_REMATCH[1]}" - pr_head_sha="$(gh api "repos/${GITHUB_REPOSITORY}/pulls/${pr_number}" --jq '.head.sha')" - pr_head_repo="$(gh api "repos/${GITHUB_REPOSITORY}/pulls/${pr_number}" --jq '.head.repo.full_name')" - - if [[ -z "${pr_head_sha}" || "${pr_head_sha}" == "null" || -z "${pr_head_repo}" || "${pr_head_repo}" == "null" ]]; then - echo "Could not resolve PR head SHA for PR #${pr_number}; running CI normally." - exit 0 - fi - - git fetch --no-tags --depth=1 "https://github.com/${pr_head_repo}.git" "${pr_head_sha}" - - if git diff --quiet "${pr_head_sha}" "${GITHUB_SHA}" --; then - echo "Merge queue commit ${GITHUB_SHA} has the same tree as PR #${pr_number} head ${pr_head_sha}; skipping duplicate CI." - echo "skip=true" >>"$GITHUB_OUTPUT" - else - echo "Merge queue commit ${GITHUB_SHA} differs from PR #${pr_number} head ${pr_head_sha}; running CI normally." - fi - upload-build-artifacts-linux: - needs: [merge_queue_noop, lints] - if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} name: Upload build artifacts (Linux) - runs-on: spacetimedb-new-runner-2 + runs-on: spacetimedb-new-runner-2-staging timeout-minutes: 15 env: CARGO_TARGET_DIR: ${{ github.workspace }}/target @@ -107,97 +57,6 @@ jobs: name: Set default rust toolchain run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) - - &verify-openssl-assembler - name: Verify OpenSSL assembler - if: runner.os == 'Windows' - shell: pwsh - run: nasm -v - - # These keys intentionally spell out stable native-build inputs instead of - # hashing the workspace. Keep the versions in sync with Cargo.lock and bump - # v1 if a fixed feature set or build configuration changes. This manual - # versioning is temporary until a better caching mechanism replaces it. - # - V8 uses its default features and has profile-specific native output. - # - OpenSSL is the vendored static build with legacy enabled. Windows uses - # NASM, which is represented by a separate cache-key suffix. - # - jemalloc is an optimized static PIC build with profiling, stats, and - # its default background-thread support. - # - Zstd is an optimized static build with legacy support and dictionary - # APIs. It is reused across Cargo profiles. - - &set-native-cache-keys - name: Set native cache keys - id: native-cache-keys - shell: bash - run: | - target="$(rustc -vV | sed -n 's/^host: //p')" - openssl_suffix="" - if [[ "${OPENSSL_RUST_USE_NASM:-}" == "1" ]]; then - openssl_suffix="-nasm" - fi - echo "v8-release-key=rusty-v8-v1-145.0.0-${target}" >>"$GITHUB_OUTPUT" - echo "v8-debug-key=rusty-v8-debug-v1-145.0.0-${target}" >>"$GITHUB_OUTPUT" - echo "openssl-key=openssl-v1-300.5.3+3.5.4-${target}${openssl_suffix}" >>"$GITHUB_OUTPUT" - if [[ "$RUNNER_OS" == "Linux" ]]; then - cc="${CC:-cc}" - cc_hash="$("$cc" --version | sha256sum | cut -c1-16)" - echo "jemalloc-key=jemalloc-v1-0.6.1+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7-${target}-${cc_hash}" >>"$GITHUB_OUTPUT" - echo "zstd-key=zstd-v1-2.0.16+zstd.1.5.7-${target}-${cc_hash}" >>"$GITHUB_OUTPUT" - fi - - - &cache-rusty-v8 - name: Cache rusty_v8 - uses: actions/cache@v4 - with: &v8-release-cache - path: ${{ env.CARGO_TARGET_DIR }}/release/gn_out/obj - key: ${{ steps.native-cache-keys.outputs.v8-release-key }} - - - &cache-openssl - name: Cache OpenSSL - id: cache-openssl - uses: actions/cache@v4 - with: &openssl-cache - path: ${{ github.workspace }}/.ci-cache/openssl - key: ${{ steps.native-cache-keys.outputs.openssl-key }} - - - &configure-cached-openssl - name: Configure cached OpenSSL - if: steps.cache-openssl.outputs.cache-hit == 'true' - shell: bash - run: | - # Reuse the cached vendored output as a prebuilt OpenSSL installation. - echo "OPENSSL_NO_VENDOR=1" >>"$GITHUB_ENV" - echo "OPENSSL_DIR=${{ github.workspace }}/.ci-cache/openssl" >>"$GITHUB_ENV" - - - name: Cache jemalloc - id: cache-jemalloc - if: runner.os == 'Linux' - uses: actions/cache@v4 - with: &jemalloc-cache - path: ${{ github.workspace }}/.ci-cache/jemalloc - key: ${{ steps.native-cache-keys.outputs.jemalloc-key }} - - - &configure-cached-jemalloc - name: Configure cached jemalloc - if: runner.os == 'Linux' && steps.cache-jemalloc.outputs.cache-hit == 'true' - shell: bash - run: echo "JEMALLOC_OVERRIDE=${{ github.workspace }}/.ci-cache/jemalloc/libjemalloc_pic.a" >>"$GITHUB_ENV" - - - name: Cache Zstd - id: cache-zstd - if: runner.os == 'Linux' - uses: actions/cache@v4 - with: &zstd-cache - path: ${{ github.workspace }}/.ci-cache/zstd - key: ${{ steps.native-cache-keys.outputs.zstd-key }} - - - &configure-cached-zstd - name: Configure cached Zstd - if: runner.os == 'Linux' && steps.cache-zstd.outputs.cache-hit == 'true' - shell: bash - run: | - echo "ZSTD_SYS_USE_PKG_CONFIG=1" >>"$GITHUB_ENV" - echo "PKG_CONFIG_PATH=${{ github.workspace }}/.ci-cache/zstd/lib/pkgconfig${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}" >>"$GITHUB_ENV" - - name: Build CLI and standalone shell: bash run: | @@ -206,61 +65,6 @@ jobs: -p spacetimedb-standalone \ --features spacetimedb-standalone/allow_loopback_http_for_tests - - &prepare-openssl-cache - name: Prepare OpenSSL cache - if: steps.cache-openssl.outputs.cache-hit != 'true' - shell: bash - run: | - shopt -s nullglob - openssl_installs=(target/release/build/openssl-sys-*/out/openssl-build/install) - if (( ${#openssl_installs[@]} != 1 )); then - echo "Expected one vendored OpenSSL installation, found ${#openssl_installs[@]}." - exit 1 - fi - mkdir -p .ci-cache/openssl - cp -R "${openssl_installs[0]}/." .ci-cache/openssl/ - - - name: Prepare jemalloc cache - if: runner.os == 'Linux' && steps.cache-jemalloc.outputs.cache-hit != 'true' - shell: bash - run: | - shopt -s nullglob - jemalloc_archives=(target/release/build/tikv-jemalloc-sys-*/out/lib/libjemalloc_pic.a) - if (( ${#jemalloc_archives[@]} != 1 )); then - echo "Expected one jemalloc archive, found ${#jemalloc_archives[@]}." - exit 1 - fi - mkdir -p .ci-cache/jemalloc - cp "${jemalloc_archives[0]}" .ci-cache/jemalloc/ - echo "JEMALLOC_OVERRIDE=${{ github.workspace }}/.ci-cache/jemalloc/libjemalloc_pic.a" >>"$GITHUB_ENV" - - - name: Prepare Zstd cache - if: runner.os == 'Linux' && steps.cache-zstd.outputs.cache-hit != 'true' - shell: bash - run: | - shopt -s nullglob - zstd_outputs=(target/release/build/zstd-sys-*/out) - if (( ${#zstd_outputs[@]} != 1 )); then - echo "Expected one vendored Zstd build, found ${#zstd_outputs[@]}." - exit 1 - fi - mkdir -p .ci-cache/zstd/lib/pkgconfig .ci-cache/zstd/include - cp "${zstd_outputs[0]}/libzstd.a" .ci-cache/zstd/lib/ - cp "${zstd_outputs[0]}"/include/*.h .ci-cache/zstd/include/ - printf '%s\n' \ - 'prefix=${pcfiledir}/../..' \ - 'libdir=${prefix}/lib' \ - 'includedir=${prefix}/include' \ - '' \ - 'Name: libzstd' \ - 'Description: Zstandard compression library' \ - 'Version: 1.5.7' \ - 'Libs: -L${libdir} -lzstd' \ - 'Cflags: -I${includedir}' \ - > .ci-cache/zstd/lib/pkgconfig/libzstd.pc - echo "ZSTD_SYS_USE_PKG_CONFIG=1" >>"$GITHUB_ENV" - echo "PKG_CONFIG_PATH=${{ github.workspace }}/.ci-cache/zstd/lib/pkgconfig${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}" >>"$GITHUB_ENV" - - name: Package build artifacts shell: bash run: | @@ -286,1413 +90,3 @@ jobs: if-no-files-found: error overwrite: true retention-days: 14 - - upload-build-artifacts-windows: - needs: [merge_queue_noop, lints] - if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} - name: Upload build artifacts (Windows) - runs-on: spacetimedb-windows-runner - timeout-minutes: 15 - env: - CARGO_TARGET_DIR: ${{ github.workspace }}/target - RUST_BACKTRACE: full - ARTIFACT_SUFFIX: windows - EXE_SUFFIX: .exe - OPENSSL_RUST_USE_NASM: "1" - steps: *upload-build-artifact-steps - - smoketest_build_linux: - needs: [upload-build-artifacts-linux] - name: Build smoketests (Linux) - runs-on: spacetimedb-new-runner-2 - timeout-minutes: 15 - env: - CARGO_TARGET_DIR: ${{ github.workspace }}/target - RUST_BACKTRACE: full - ARTIFACT_SUFFIX: linux - EXE_SUFFIX: "" - SMOKETEST_SUITE: standalone - steps: &smoketest-build-steps - - *find-git-ref - - - *checkout-sources - - - uses: dsherret/rust-toolchain-file@v1 - - *set-default-rust-toolchain - - - *set-native-cache-keys - - *verify-openssl-assembler - - &restore-openssl - name: Restore OpenSSL - id: cache-openssl - uses: actions/cache/restore@v4 - with: *openssl-cache - - *configure-cached-openssl - - - name: Install cargo-nextest - uses: taiki-e/install-action@nextest - - - name: Build smoketest dependencies and archive test binaries - shell: bash - run: | - cargo run --timings --package ci-smoketests -- --suite "${SMOKETEST_SUITE}" archive --archive-file smoketest-nextest.tar.zst - - shopt -s nullglob - precompiled_modules=(target/wasm32-unknown-unknown/release/smoketest_module_*.wasm) - if (( ${#precompiled_modules[@]} == 0 )); then - echo "No precompiled smoketest modules were produced." - exit 1 - fi - - tar -czf smoketest-support.tar.gz \ - "target/debug/ci-smoketests${EXE_SUFFIX}" \ - "${precompiled_modules[@]}" - - - name: Upload Cargo timing reports - if: always() - uses: actions/upload-artifact@v4 - with: - name: smoketest-build-cargo-timings-${{ env.ARTIFACT_SUFFIX }} - path: ${{ env.CARGO_TARGET_DIR }}/cargo-timings/ - if-no-files-found: warn - overwrite: true - retention-days: 14 - - - name: Upload smoketest build - uses: actions/upload-artifact@v4 - with: - name: smoketest-build-${{ env.ARTIFACT_SUFFIX }} - path: | - smoketest-nextest.tar.zst - smoketest-support.tar.gz - if-no-files-found: error - overwrite: true - retention-days: 14 - - smoketest_build_windows: - needs: [upload-build-artifacts-windows] - name: Build smoketests (Windows) - runs-on: spacetimedb-windows-runner - timeout-minutes: 15 - env: - CARGO_TARGET_DIR: ${{ github.workspace }}/target - RUST_BACKTRACE: full - ARTIFACT_SUFFIX: windows - EXE_SUFFIX: .exe - OPENSSL_RUST_USE_NASM: "1" - SMOKETEST_SUITE: all - steps: *smoketest-build-steps - - smoketest_partitions_linux: - needs: [smoketest_build_linux] - name: Smoketests (Linux ${{ matrix.partition }}/1) - strategy: - fail-fast: false - matrix: - partition: [1] - runs-on: spacetimedb-new-runner-2 - timeout-minutes: 30 - env: - CARGO_TARGET_DIR: ${{ github.workspace }}/target - RUST_BACKTRACE: full - SPACETIMEDB_CPP_DIR: ${{ github.workspace }}/crates/bindings-cpp - ARTIFACT_SUFFIX: linux - PARTITION_COUNT: 1 - steps: &smoketest-partition-steps - - *find-git-ref - - - *checkout-sources - - - uses: dsherret/rust-toolchain-file@v1 - - *set-default-rust-toolchain - - - uses: actions/setup-dotnet@v4 - with: - global-json-file: global.json - - # Node.js and pnpm are required for the TypeScript smoketests. - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: 18 - - - uses: ./.github/actions/setup-pnpm - - - name: Install TypeScript SDK dependencies - run: pnpm --filter spacetimedb install - - # Install emscripten for C++ module compilation tests. - - name: Install emscripten (Linux) - if: runner.os == 'Linux' - shell: bash - run: | - git clone https://github.com/emscripten-core/emsdk.git ~/emsdk - cd ~/emsdk - ./emsdk install 4.0.21 - ./emsdk activate 4.0.21 - - - name: Install emscripten (Windows) - if: runner.os == 'Windows' - shell: pwsh - run: | - git clone https://github.com/emscripten-core/emsdk.git $env:USERPROFILE\emsdk - cd $env:USERPROFILE\emsdk - .\emsdk install 4.0.21 - .\emsdk activate 4.0.21 - - - name: Install psql - if: runner.os == 'Windows' - shell: pwsh - run: | - # Fail properly if any individual command fails - $ErrorActionPreference = 'Stop' - $PSNativeCommandUseErrorActionPreference = $true - choco install psql -y --no-progress - # Check for existence, since `choco` doesn't seem to fail the step if it fails to install.. - # See https://github.com/clockworklabs/SpacetimeDB/pull/4399 for more background. - Get-Command psql - - - name: Update dotnet workloads - if: runner.os == 'Windows' - shell: pwsh - run: | - # Fail properly if any individual command fails - $ErrorActionPreference = 'Stop' - $PSNativeCommandUseErrorActionPreference = $true - - cd modules - # the sdk-manifests on windows-latest are messed up, so we need to update them - dotnet workload config --update-mode manifests - dotnet workload update --from-previous-sdk - # Explicitly install wasi-experimental for .NET 8 SDK (needed for test_build_csharp_module) - # Create temp global.json to target .NET 8 SDK for workload install - $sdk8Json = '{"sdk":{"version":"8.0.400","rollForward":"latestFeature"}}' - $sdk8Json | Out-File -FilePath global.json -Encoding utf8 - dotnet workload install wasi-experimental - Remove-Item global.json - - - name: Override NuGet packages - shell: bash - run: | - dotnet pack -c Release crates/bindings-csharp/BSATN.Runtime - dotnet pack -c Release crates/bindings-csharp/Runtime - cd sdks/csharp - ./tools~/write-nuget-config.sh ../.. - - - name: Install cargo-nextest - uses: taiki-e/install-action@nextest - - - name: Download build artifacts - uses: actions/download-artifact@v4 - with: - name: build-artifacts-${{ env.ARTIFACT_SUFFIX }} - path: build-artifacts - - - name: Extract build artifacts - shell: bash - run: | - tar -xzf build-artifacts/build-support.tar.gz - exe_suffix="" - if [[ "${RUNNER_OS}" == "Windows" ]]; then - exe_suffix=".exe" - fi - test -f "${CARGO_TARGET_DIR}/release/spacetimedb-cli${exe_suffix}" - test -f "${CARGO_TARGET_DIR}/release/spacetimedb-standalone${exe_suffix}" - - - name: Download smoketest build - uses: actions/download-artifact@v4 - with: - name: smoketest-build-${{ env.ARTIFACT_SUFFIX }} - - - name: Extract smoketest support files - shell: bash - run: tar -xzf smoketest-support.tar.gz - - # Serial execution avoids contention between the C# tests over generated bindings. - - name: Run smoketest partition (Linux) - if: runner.os == 'Linux' - shell: bash - run: | - if [ -f ~/emsdk/emsdk_env.sh ]; then - source ~/emsdk/emsdk_env.sh - fi - ./target/debug/ci-smoketests run-archive \ - --archive-file smoketest-nextest.tar.zst \ - -- \ - --partition hash:${{ matrix.partition }}/${{ env.PARTITION_COUNT }} - - # Due to Emscripten PATH issues this remains separate from the Linux command. - - name: Run smoketest partition (Windows) - if: runner.os == 'Windows' - shell: pwsh - run: | - if (Test-Path "$env:USERPROFILE\emsdk\emsdk_env.ps1") { - & "$env:USERPROFILE\emsdk\emsdk_env.ps1" | Out-Null - } - .\target\debug\ci-smoketests.exe run-archive ` - --archive-file smoketest-nextest.tar.zst ` - -- ` - --partition hash:${{ matrix.partition }}/${{ env.PARTITION_COUNT }} - - - name: Upload timing reports - if: always() - uses: actions/upload-artifact@v4 - with: - name: cargo-timings-smoketests-${{ matrix.name }} - path: ${{ env.CARGO_TARGET_DIR }}/cargo-timings/ - retention-days: 14 - - smoketest_partitions_windows: - needs: [smoketest_build_windows] - name: Smoketests (Windows ${{ matrix.partition }}/4) - strategy: - fail-fast: false - matrix: - partition: [1, 2, 3, 4] - runs-on: spacetimedb-windows-runner - timeout-minutes: 30 - env: - CARGO_TARGET_DIR: ${{ github.workspace }}/target - RUST_BACKTRACE: full - SPACETIMEDB_CPP_DIR: ${{ github.workspace }}/crates/bindings-cpp - ARTIFACT_SUFFIX: windows - PARTITION_COUNT: 4 - steps: *smoketest-partition-steps - - # this is a no-op version of the above check with a trivially-passing body. - # we can't just let the check be entirely skipped because each matrix target is a required check, - # and skipping this check means that the matrix isn't "populated" so the required checks wouldn't be met. - smoketests_noop: - needs: [merge_queue_noop] - if: ${{ needs.merge_queue_noop.outputs.skip == 'true' }} - name: Smoketests (${{ matrix.name }}) - strategy: - matrix: - include: - - name: Linux 1/1 - - name: Windows 1/4 - - name: Windows 2/4 - - name: Windows 3/4 - - name: Windows 4/4 - runs-on: ubuntu-latest - steps: - - name: Skip duplicate merge queue smoketest - run: echo "Merge queue commit has the same tree as the PR head; smoketest already ran for the PR." - - test: - needs: [merge_queue_noop, lints] - if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} - name: Test Suite - runs-on: spacetimedb-new-runner-2 - - env: - CARGO_TARGET_DIR: ${{ github.workspace }}/target - RUST_BACKTRACE: full - steps: - - name: Find Git ref - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - PR_NUMBER="${{ github.event.inputs.pr_number || null }}" - if test -n "${PR_NUMBER}"; then - GIT_REF="$( gh pr view --repo clockworklabs/SpacetimeDB $PR_NUMBER --json headRefName --jq .headRefName )" - else - GIT_REF="${{ github.ref }}" - fi - echo "GIT_REF=${GIT_REF}" >>"$GITHUB_ENV" - - - name: Checkout sources - uses: actions/checkout@v4 - with: - ref: ${{ env.GIT_REF }} - - - uses: dsherret/rust-toolchain-file@v1 - - name: Set default rust toolchain - run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) - - *set-native-cache-keys - - &restore-jemalloc - name: Restore jemalloc - id: cache-jemalloc - if: runner.os == 'Linux' - uses: actions/cache/restore@v4 - with: *jemalloc-cache - - *configure-cached-jemalloc - - &restore-zstd - name: Restore Zstd - id: cache-zstd - if: runner.os == 'Linux' - uses: actions/cache/restore@v4 - with: *zstd-cache - - *configure-cached-zstd - - &restore-rusty-v8-debug - name: Restore rusty_v8 (debug) - uses: actions/cache/restore@v4 - with: &v8-debug-cache - path: ${{ env.CARGO_TARGET_DIR }}/debug/gn_out/obj - key: ${{ steps.native-cache-keys.outputs.v8-debug-key }} - - &restore-rusty-v8 - name: Restore rusty_v8 - uses: actions/cache/restore@v4 - with: *v8-release-cache - - *restore-openssl - - *configure-cached-openssl - - - uses: actions/setup-dotnet@v3 - with: - global-json-file: global.json - - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: 22 - - - uses: ./.github/actions/setup-pnpm - with: - run_install: true - - # Install cmake and emscripten for C++ module compilation tests. - - name: Install cmake and emscripten - run: | - sudo apt-get update - sudo apt-get install -y cmake - git clone https://github.com/emscripten-core/emsdk.git ~/emsdk - cd ~/emsdk - ./emsdk install 4.0.21 - ./emsdk activate 4.0.21 - - - name: Install wasm-bindgen CLI - run: | - REQUIRED_WASM_BINDGEN_VERSION="$( - awk ' - $1 == "name" && $3 == "\"wasm-bindgen\"" { in_pkg = 1; next } - in_pkg && $1 == "version" { - gsub(/"/, "", $3); - print $3; - exit; - } - ' Cargo.lock - )" - if [ -z "${REQUIRED_WASM_BINDGEN_VERSION}" ]; then - echo "Failed to determine wasm-bindgen version from Cargo.lock" - exit 1 - fi - - INSTALLED_WASM_BINDGEN_VERSION="$(wasm-bindgen --version 2>/dev/null | awk '{print $2}' || true)" - if [ "${INSTALLED_WASM_BINDGEN_VERSION}" != "${REQUIRED_WASM_BINDGEN_VERSION}" ]; then - cargo install --locked --force wasm-bindgen-cli --version "${REQUIRED_WASM_BINDGEN_VERSION}" - fi - - wasm-bindgen --version - - # Source emsdk environment to make emcc (Emscripten compiler) available in PATH. - - name: Run tests - run: | - source ~/emsdk/emsdk_env.sh - cargo ci test - - - name: Upload timing reports - if: always() - uses: actions/upload-artifact@v4 - with: - name: cargo-timings-test - path: ${{ env.CARGO_TARGET_DIR }}/cargo-timings/ - retention-days: 14 - - index_scan_bench: - needs: [merge_queue_noop, lints] - if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} - name: Index Scan Bench - runs-on: spacetimedb-benchmark-runner - concurrency: - group: ci-benchmark-runner - queue: max - timeout-minutes: 60 - env: - CARGO_TARGET_DIR: ${{ github.workspace }}/target - RUST_BACKTRACE: full - steps: - - name: Find Git ref - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - PR_NUMBER="${{ github.event.inputs.pr_number || null }}" - if test -n "${PR_NUMBER}"; then - GIT_REF="$( gh pr view --repo clockworklabs/SpacetimeDB $PR_NUMBER --json headRefName --jq .headRefName )" - else - GIT_REF="${{ github.ref }}" - fi - echo "GIT_REF=${GIT_REF}" >>"$GITHUB_ENV" - - - name: Checkout sources - uses: actions/checkout@v4 - with: - ref: ${{ env.GIT_REF }} - - - uses: dsherret/rust-toolchain-file@v1 - - name: Set default rust toolchain - run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) - - - *set-native-cache-keys - - *restore-jemalloc - - *configure-cached-jemalloc - - *restore-zstd - - *configure-cached-zstd - - *restore-rusty-v8 - - *restore-openssl - - *configure-cached-openssl - - - name: Run index scan benchmark regression check - run: cargo run --release -p spacetimedb-index-scan-gate - - lints: - needs: [merge_queue_noop] - if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} - name: Lints - runs-on: spacetimedb-new-runner-2 - env: - CARGO_TARGET_DIR: ${{ github.workspace }}/target - RUST_BACKTRACE: full - steps: - - name: Checkout sources - uses: actions/checkout@v3 - - - uses: dsherret/rust-toolchain-file@v1 - - name: Set default rust toolchain - run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) - - run: echo ::add-matcher::.github/workflows/rust_matcher.json - - - *set-native-cache-keys - - *restore-jemalloc - - *configure-cached-jemalloc - - *restore-zstd - - *configure-cached-zstd - - name: Cache rusty_v8 (debug) - uses: actions/cache@v4 - with: *v8-debug-cache - - *restore-openssl - - *configure-cached-openssl - - - uses: actions/setup-dotnet@v3 - with: - global-json-file: global.json - - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: 22 - - - uses: ./.github/actions/setup-pnpm - with: - run_install: true - - - name: Run ci lint - run: cargo ci lint - - - name: Upload timing reports - if: always() - uses: actions/upload-artifact@v4 - with: - name: cargo-timings-public-lints - path: ${{ env.CARGO_TARGET_DIR }}/cargo-timings/ - retention-days: 14 - - codeowners_check: - if: ${{ github.event_name == 'pull_request' }} - name: CODEOWNERS check - runs-on: spacetimedb-new-runner-2 - permissions: - contents: read - pull-requests: read - env: - CARGO_TARGET_DIR: ${{ github.workspace }}/target - RUST_BACKTRACE: full - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - uses: dsherret/rust-toolchain-file@v1 - - name: Set default rust toolchain - run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) - - - name: Run CODEOWNERS check - run: | - cargo ci other-workflows codeowners-check \ - --base-ref "origin/${{ github.event.pull_request.base.ref }}" \ - --pr-number "${{ github.event.pull_request.number }}" - - - name: Upload timing reports - if: always() - uses: actions/upload-artifact@v4 - with: - name: cargo-timings-codeowners-check - path: ${{ env.CARGO_TARGET_DIR }}/cargo-timings/ - retention-days: 14 - - wasm_bindings: - needs: [merge_queue_noop] - if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} - name: Build and test wasm bindings - runs-on: spacetimedb-new-runner-2 - env: - CARGO_TARGET_DIR: ${{ github.workspace }}/target - RUST_BACKTRACE: full - steps: - - uses: actions/checkout@v3 - - - uses: dsherret/rust-toolchain-file@v1 - - name: Set default rust toolchain - run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) - - run: echo ::add-matcher::.github/workflows/rust_matcher.json - - - *set-native-cache-keys - - *restore-jemalloc - - *configure-cached-jemalloc - - *restore-zstd - - *configure-cached-zstd - - *restore-openssl - - *configure-cached-openssl - - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: 22 - - - uses: ./.github/actions/setup-pnpm - - - name: Run bindgen tests - run: cargo ci wasm-bindings - - - name: Upload timing reports - if: always() - uses: actions/upload-artifact@v4 - with: - name: cargo-timings-wasm-bindings - path: ${{ env.CARGO_TARGET_DIR }}/cargo-timings/ - retention-days: 14 - - publish_checks: - needs: [merge_queue_noop] - if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} - name: Check that packages are publishable - runs-on: spacetimedb-new-runner-2 - permissions: read-all - env: - RUST_BACKTRACE: full - steps: - - uses: actions/checkout@v3 - - uses: dsherret/rust-toolchain-file@v1 - - name: Set default rust toolchain - run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) - - name: Run checks - run: cargo ci publish-checks - - - name: Upload timing reports - if: always() - uses: actions/upload-artifact@v4 - with: - name: cargo-timings-publish-checks - path: ${{ github.workspace }}/target/cargo-timings/ - retention-days: 14 - - update: - needs: [merge_queue_noop] - if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} - name: Test spacetimedb-update flow (${{ matrix.target }}) - permissions: read-all - strategy: - matrix: - include: - - { target: x86_64-unknown-linux-gnu, runner: spacetimedb-new-runner-2 } - - { target: aarch64-apple-darwin, runner: macos-latest } - - { target: x86_64-pc-windows-msvc, runner: windows-latest } - runs-on: ${{ matrix.runner }} - env: - RUST_BACKTRACE: full - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Install Rust - uses: dsherret/rust-toolchain-file@v1 - - name: Set default rust toolchain - run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) - - - *set-native-cache-keys - - *restore-zstd - - *configure-cached-zstd - - - name: Install rust target - run: rustup target add ${{ matrix.target }} - - - name: Test spacetimedb-update - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: cargo ci update-flow --target=${{ matrix.target }} --github-token-auth - - - name: Upload timing reports - if: always() - uses: actions/upload-artifact@v4 - with: - name: cargo-timings-update-flow-${{ matrix.target }} - path: ${{ github.workspace }}/target/cargo-timings/ - retention-days: 14 - - # this is a no-op version of the above check with a trivially-passing body. - # we can't just let the check be entirely skipped because each matrix target is a required check, - # and skipping this check means that the matrix isn't "populated" so the required checks wouldn't be met. - update_noop: - needs: [merge_queue_noop] - if: ${{ needs.merge_queue_noop.outputs.skip == 'true' }} - name: Test spacetimedb-update flow (${{ matrix.target }}) - permissions: read-all - strategy: - matrix: - include: - - { target: x86_64-unknown-linux-gnu } - - { target: aarch64-apple-darwin } - - { target: x86_64-pc-windows-msvc } - runs-on: ubuntu-latest - steps: - - name: Skip duplicate merge queue update test - run: echo "Merge queue commit has the same tree as the PR head; update-flow already ran for the PR." - - unreal_engine_tests: - name: Unreal Engine Tests - # This can't go on e.g. ubuntu-latest because that runner runs out of disk space. ChatGPT suggested that the general solution tends to be to use - # a custom runner. - runs-on: spacetimedb-new-runner-2 - # Disable the tests because they are very flaky at the moment. - # TODO: Remove this line and re-enable the `if` line just below here. - if: false - # Skip if this is an external contribution. GitHub secrets will be empty, so the step would fail anyway. - # if: ${{ github.event_name != 'pull_request' || !github.event.pull_request.head.repo.fork }} - container: - image: ghcr.io/epicgames/unreal-engine:dev-5.6 - credentials: - # Note(bfops): I don't think that `github.actor` needs to match the user that the token is for, because I'm using a token for my account and - # it seems to be totally happy. - # However, the token needs to be for a user that has access to the EpicGames org (see - # https://dev.epicgames.com/documentation/en-us/unreal-engine/downloading-source-code-in-unreal-engine?application_version=5.6) - username: ${{ github.actor }} - password: ${{ secrets.GHCR_TOKEN }} - # Run as root because otherwise we get permission denied for various directories inside the container. I tried doing dances to allow it to run - # without this (reassigning env vars and stuff), but was unable to get it to work and it felt like an uphill battle. - options: --user 0:0 - env: - RUST_BACKTRACE: full - steps: - # Uncomment this before merging so that it will run properly if run manually through the GH actions flow. It was playing weird with rolled back - # commits though. - # - name: Find Git ref - # env: - # GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # shell: bash - # run: | - # PR_NUMBER="${{ github.event.inputs.pr_number || null }}" - # if test -n "${PR_NUMBER}"; then - # GIT_REF="$( gh pr view --repo clockworklabs/SpacetimeDB $PR_NUMBER --json headRefName --jq .headRefName )" - # else - # GIT_REF="${{ github.ref }}" - # fi - # echo "GIT_REF=${GIT_REF}" >>"$GITHUB_ENV" - - name: Checkout sources - uses: actions/checkout@v4 - with: - ref: ${{ env.GIT_REF }} - - uses: dsherret/rust-toolchain-file@v1 - - name: Set default rust toolchain - run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) - - name: Run Unreal Engine tests - working-directory: sdks/unreal - env: - UE_ROOT_PATH: /home/ue4/UnrealEngine - run: | - - apt-get update - apt-get install -y acl curl ca-certificates - - REPO="$GITHUB_WORKSPACE" - # Let ue4 read/write the workspace & tool caches without changing ownership - for p in "$REPO" "${RUNNER_TEMP:-/__t}" "${RUNNER_TOOL_CACHE:-/__t}"; do - [ -d "$p" ] && setfacl -R -m u:ue4:rwX -m d:u:ue4:rwX "$p" || true - done - - # Rust tool caches live under the runner tool cache so they persist - export CARGO_HOME="${RUNNER_TOOL_CACHE:-/__t}/cargo" - export RUSTUP_HOME="${RUNNER_TOOL_CACHE:-/__t}/rustup" - mkdir -p "$CARGO_HOME" "$RUSTUP_HOME" - chown -R ue4:ue4 "$CARGO_HOME" "$RUSTUP_HOME" - - # Make sure the UE build script is executable (and parents traversable) - UE_DIR="${UE_ROOT_PATH:-/home/ue4/UnrealEngine}" - chmod a+rx "$UE_DIR" "$UE_DIR/Engine" "$UE_DIR/Engine/Build" "$UE_DIR/Engine/Build/BatchFiles/Linux" || true - chmod a+rx "$UE_DIR/Engine/Build/BatchFiles/Linux/Build.sh" || true - - # Run the build & tests as ue4 (who owns the UE tree) - sudo -E -H -u ue4 env \ - HOME=/home/ue4 \ - XDG_CONFIG_HOME=/home/ue4/.config \ - CARGO_HOME="$CARGO_HOME" \ - RUSTUP_HOME="$RUSTUP_HOME" \ - PATH="$CARGO_HOME/bin:$PATH" \ - bash -lc ' - set -euxo pipefail - # Install rustup for ue4 if needed (uses the shared caches) - if ! command -v cargo >/dev/null 2>&1; then - curl -sSf https://sh.rustup.rs | sh -s -- -y - fi - rustup show >/dev/null - git config --global --add safe.directory "$GITHUB_WORKSPACE" || true - - cd "$GITHUB_WORKSPACE/sdks/unreal" - cargo --version - cargo test -- --test-threads=1 - ' - - cli_docs: - needs: [merge_queue_noop] - if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} - name: Check CLI docs - permissions: read-all - runs-on: spacetimedb-new-runner-2 - env: - CARGO_TARGET_DIR: ${{ github.workspace }}/target - RUST_BACKTRACE: full - steps: - - name: Find Git ref - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - shell: bash - run: | - PR_NUMBER="${{ github.event.inputs.pr_number || null }}" - if test -n "${PR_NUMBER}"; then - GIT_REF="$( gh pr view --repo clockworklabs/SpacetimeDB $PR_NUMBER --json headRefName --jq .headRefName )" - else - GIT_REF="${{ github.ref }}" - fi - echo "GIT_REF=${GIT_REF}" >>"$GITHUB_ENV" - - - name: Checkout sources - uses: actions/checkout@v4 - with: - ref: ${{ env.GIT_REF }} - - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: 22 - - - uses: ./.github/actions/setup-pnpm - with: - run_install: true - - - uses: dsherret/rust-toolchain-file@v1 - - name: Set default rust toolchain - run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) - - - *set-native-cache-keys - - *restore-jemalloc - - *configure-cached-jemalloc - - *restore-zstd - - *configure-cached-zstd - - *restore-openssl - - *configure-cached-openssl - - - name: Check for docs change - run: | - cargo ci cli-docs - - - name: Upload timing reports - if: always() - uses: actions/upload-artifact@v4 - with: - name: cargo-timings-cli-docs - path: ${{ env.CARGO_TARGET_DIR }}/cargo-timings/ - retention-days: 14 - - unity-testsuite: - needs: [merge_queue_noop, lints] - # Skip if this is an external contribution. - # The license secrets will be empty, so the step would fail anyway. - if: ${{ needs.merge_queue_noop.outputs.skip != 'true' && (github.event_name != 'pull_request' || !github.event.pull_request.head.repo.fork) }} - permissions: - contents: read - checks: write - runs-on: spacetimedb-unity-runner - timeout-minutes: 30 - env: - CARGO_TARGET_DIR: ${{ github.workspace }}/target - RUST_BACKTRACE: full - UNITY_VERSION: 2022.3.32f1 - steps: - - name: Checkout repository - id: checkout-stdb - uses: actions/checkout@v4 - - # Keep this before generation/hydration so ignored build outputs do not affect hashFiles. - - name: Restore Unity Library - id: restore-unity-library - uses: actions/cache/restore@v4 - with: - path: demo/Blackholio/client-unity/Library - key: Unity-v2-${{ runner.os }}-${{ env.UNITY_VERSION }}-${{ hashFiles('demo/Blackholio/client-unity/**', 'sdks/csharp/**', 'crates/bindings-csharp/BSATN.Runtime/**', 'crates/bindings-csharp/Runtime/**', 'crates/bindings-csharp/Directory.Build.props', 'tools/regen/src/csharp.rs', 'global.json') }} - restore-keys: | - Unity-v2-${{ runner.os }}-${{ env.UNITY_VERSION }}- - - # Run cheap .NET tests first. If those fail, no need to run expensive Unity tests. - - - name: Setup dotnet - uses: actions/setup-dotnet@v3 - with: - global-json-file: global.json - - - name: Override NuGet packages - run: | - dotnet pack crates/bindings-csharp/BSATN.Runtime - dotnet pack crates/bindings-csharp/Runtime - - # Write out the nuget config file to `nuget.config`. This causes the spacetimedb-csharp-sdk repository - # to be aware of the local versions of the `bindings-csharp` packages in SpacetimeDB, and use them if - # available. Otherwise, `spacetimedb-csharp-sdk` will use the NuGet versions of the packages. - # This means that (if version numbers match) we will test the local versions of the C# packages, even - # if they're not pushed to NuGet. - # See https://learn.microsoft.com/en-us/nuget/reference/nuget-config-file for more info on the config file. - cd sdks/csharp - ./tools~/write-nuget-config.sh ../.. - - - name: Restore .NET solution - working-directory: sdks/csharp - run: dotnet restore --configfile NuGet.Config SpacetimeDB.ClientSDK.sln - - # Now, setup the Unity tests. - - name: Patch spacetimedb dependency in Cargo.toml - working-directory: demo/Blackholio/server-rust - run: | - sed -i "s|spacetimedb *=.*|spacetimedb = \{ path = \"../../../crates/bindings\" \}|" Cargo.toml - cat Cargo.toml - - - name: Install Rust toolchain - uses: dsherret/rust-toolchain-file@v1 - - name: Set default rust toolchain - run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) - - - *set-native-cache-keys - - *restore-jemalloc - - *configure-cached-jemalloc - - *restore-zstd - - *configure-cached-zstd - - *restore-rusty-v8 - - *restore-openssl - - *configure-cached-openssl - - - name: Install SpacetimeDB CLI from the local checkout - run: | - export CARGO_HOME="$HOME/.cargo" - echo "$CARGO_HOME/bin" >> "$GITHUB_PATH" - cargo install --force --path crates/cli --locked --message-format=short - cargo install --force --path crates/standalone --locked --message-format=short - # Add a handy alias using the old binary name, so that we don't have to rewrite all scripts (incl. in submodules). - ln -sf $CARGO_HOME/bin/spacetimedb-cli $CARGO_HOME/bin/spacetime - - - name: Generate client bindings - working-directory: demo/Blackholio/server-rust - run: bash ./generate.sh -y - - - name: Check for changes - run: | - tools/check-diff.sh demo/Blackholio/client-unity/Assets/Scripts/autogen || { - echo 'Error: Bindings are dirty. Please run `demo/Blackholio/server-rust/generate.sh`.' - exit 1 - } - - - name: Hydrate Unity SDK DLLs - run: cargo regen csharp dlls - - - name: Check Unity meta files - uses: DeNA/unity-meta-check@v3 - with: - enable_pr_comment: ${{ github.event_name == 'pull_request' }} - target_path: sdks/csharp - env: - GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" - - - name: Start SpacetimeDB - run: | - spacetime start & - disown - - - name: Publish unity-tests module to SpacetimeDB - working-directory: demo/Blackholio/server-rust - run: | - spacetime logout && spacetime login --server-issued-login local - bash ./publish.sh - - - name: Patch com.clockworklabs.spacetimedbsdk dependency in manifest.json - working-directory: demo/Blackholio/client-unity/Packages - run: | - yq e -i '.dependencies["com.clockworklabs.spacetimedbsdk"] = "file:../../../../sdks/csharp"' manifest.json - cat manifest.json - - - name: Run Unity tests - uses: game-ci/unity-test-runner@v4 - with: - unityVersion: ${{ env.UNITY_VERSION }} - projectPath: demo/Blackholio/client-unity # Path to the Unity project subdirectory - githubToken: ${{ secrets.GITHUB_TOKEN }} - testMode: playmode - useHostNetwork: true - artifactsPath: "" - env: - UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }} - UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }} - UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }} - - - name: Save Unity Library - if: ${{ github.ref == 'refs/heads/master' && steps.restore-unity-library.outputs.cache-hit != 'true' }} - uses: actions/cache/save@v4 - with: - path: demo/Blackholio/client-unity/Library - key: ${{ steps.restore-unity-library.outputs.cache-primary-key }} - - godot-testsuite: - needs: [merge_queue_noop, lints] - if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} - permissions: - contents: read - runs-on: spacetimedb-new-runner-2 - env: - CARGO_TARGET_DIR: ${{ github.workspace }}/target - UseLocalBsatnRuntime: true - steps: - - name: Checkout repository - id: checkout-stdb - uses: actions/checkout@v4 - - - name: Setup dotnet - uses: actions/setup-dotnet@v3 - with: - global-json-file: global.json - - - name: Override NuGet packages - run: | - dotnet pack -c Release crates/bindings-csharp/BSATN.Runtime - dotnet pack -c Release crates/bindings-csharp/Runtime - - # Write out the nuget config file to `nuget.config`. This causes the spacetimedb-csharp-sdk repository - # to be aware of the local versions of the `bindings-csharp` packages in SpacetimeDB, and use them if - # available. Otherwise, `spacetimedb-csharp-sdk` will use the NuGet versions of the packages. - # This means that (if version numbers match) we will test the local versions of the C# packages, even - # if they're not pushed to NuGet. - # See https://learn.microsoft.com/en-us/nuget/reference/nuget-config-file for more info on the config file. - cd sdks/csharp - ./tools~/write-nuget-config.sh ../.. - - - name: Restore .NET solution - working-directory: sdks/csharp - run: dotnet restore --configfile NuGet.Config SpacetimeDB.ClientSDK.sln - - # Now, setup the Godot tests. - - name: Patch spacetimedb dependency in Cargo.toml - working-directory: demo/Blackholio/server-rust - run: | - sed -i "s|spacetimedb *=.*|spacetimedb = \{ path = \"../../../crates/bindings\" \}|" Cargo.toml - cat Cargo.toml - - - name: Install Rust toolchain - uses: dsherret/rust-toolchain-file@v1 - - name: Set default rust toolchain - run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) - - - *set-native-cache-keys - - *restore-jemalloc - - *configure-cached-jemalloc - - *restore-zstd - - *configure-cached-zstd - - *restore-rusty-v8 - - *restore-openssl - - *configure-cached-openssl - - - name: Install SpacetimeDB CLI from the local checkout - run: | - export CARGO_HOME="$HOME/.cargo" - echo "$CARGO_HOME/bin" >> "$GITHUB_PATH" - cargo install --force --path crates/cli --locked --message-format=short - cargo install --force --path crates/standalone --locked --message-format=short - # Add a handy alias using the old binary name, so that we don't have to rewrite all scripts (incl. in submodules). - ln -sf $CARGO_HOME/bin/spacetimedb-cli $CARGO_HOME/bin/spacetime - - - name: Generate client bindings - working-directory: demo/Blackholio/server-rust - run: bash ./generate.sh -y - - - name: Check for changes - run: | - tools/check-diff.sh demo/Blackholio/client-godot/module_bindings || { - echo 'Error: Godot bindings are dirty. Please run `demo/Blackholio/server-rust/generate.sh`.' - exit 1 - } - - - name: Patch SpacetimeDB Godot SDK dependency - working-directory: demo/Blackholio/client-godot - run: | - dotnet remove package SpacetimeDB.ClientSDK.Godot - dotnet add reference ../../../sdks/csharp/SpacetimeDB.ClientSDK.Godot.csproj - cat blackholio.csproj - - - name: Setup Godot - uses: chickensoft-games/setup-godot@v2 - with: - version: 4.6.2 - use-dotnet: true - - - name: Restore Godot project - working-directory: demo/Blackholio/client-godot - run: dotnet restore --configfile ../../../NuGet.Config blackholio.csproj - - - name: Build Godot project - working-directory: demo/Blackholio/client-godot - run: godot --headless --verbose --build-solutions --quit - - - name: Start SpacetimeDB - run: | - spacetime start & - disown - - - name: Publish godot-tests module to SpacetimeDB - working-directory: demo/Blackholio/server-rust - run: | - spacetime login --server-issued-login local - bash ./publish.sh - - - name: Run Godot tests - working-directory: demo/Blackholio/client-godot - run: godot --headless --scene res://tests/GodotPlayModeTests.tscn - - csharp-testsuite: - needs: [merge_queue_noop, lints] - if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} - runs-on: spacetimedb-new-runner-2 - timeout-minutes: 30 - env: - CARGO_TARGET_DIR: ${{ github.workspace }}/target - RUST_BACKTRACE: full - steps: - - name: Checkout repository - id: checkout-stdb - uses: actions/checkout@v4 - - - name: Setup dotnet - uses: actions/setup-dotnet@v3 - with: - global-json-file: global.json - - - name: Install .NET workloads - run: | - dotnet workload config --update-mode manifests - dotnet workload update --from-previous-sdk - # Explicitly install wasi-experimental for .NET 8 SDK (needed for test_build_csharp_module) - # Create temp global.json to target .NET 8 SDK for workload install - echo '{"sdk":{"version":"8.0.100","rollForward":"latestFeature"}}' > global.json - dotnet workload install wasi-experimental - rm global.json - - - name: Override NuGet packages - run: | - dotnet pack crates/bindings-csharp/BSATN.Runtime - dotnet pack crates/bindings-csharp/Runtime - - # Write out the nuget config file to `nuget.config`. This causes the spacetimedb-csharp-sdk repository - # to be aware of the local versions of the `bindings-csharp` packages in SpacetimeDB, and use them if - # available. Otherwise, `spacetimedb-csharp-sdk` will use the NuGet versions of the packages. - # This means that (if version numbers match) we will test the local versions of the C# packages, even - # if they're not pushed to NuGet. - # See https://learn.microsoft.com/en-us/nuget/reference/nuget-config-file for more info on the config file. - cd sdks/csharp - ./tools~/write-nuget-config.sh ../.. - - - name: Restore .NET solution - working-directory: sdks/csharp - run: dotnet restore --configfile NuGet.Config SpacetimeDB.ClientSDK.sln - - - name: Run .NET tests - working-directory: sdks/csharp - run: dotnet test -warnaserror --no-restore SpacetimeDB.ClientSDK.csproj - - - name: Verify C# formatting - working-directory: sdks/csharp - run: dotnet format --no-restore --verify-no-changes SpacetimeDB.ClientSDK.sln - - - name: Install Rust toolchain - uses: dsherret/rust-toolchain-file@v1 - - name: Set default rust toolchain - run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) - - - *set-native-cache-keys - - *restore-jemalloc - - *configure-cached-jemalloc - - *restore-zstd - - *configure-cached-zstd - - *restore-rusty-v8-debug - - *restore-rusty-v8 - - *restore-openssl - - *configure-cached-openssl - - - name: Install SpacetimeDB CLI from the local checkout - run: | - export CARGO_HOME="$HOME/.cargo" - echo "$CARGO_HOME/bin" >> "$GITHUB_PATH" - cargo install --force --path crates/cli --locked --message-format=short - cargo install --force --path crates/standalone --features allow_loopback_http_for_tests --locked --message-format=short - # Add a handy alias using the old binary name, so that we don't have to rewrite all scripts (incl. in submodules). - ln -sf $CARGO_HOME/bin/spacetimedb-cli $CARGO_HOME/bin/spacetime - - - name: Check quickstart-chat bindings are up to date - run: | - for dotnet_version in 8 10; do - bash sdks/csharp/tools~/gen-quickstart.sh "$dotnet_version" - done - tools/check-diff.sh templates/chat-console-cs/module_bindings || { - echo 'Error: quickstart-chat bindings have changed. Please run `sdks/csharp/tools~/gen-quickstart.sh 10`.' - exit 1 - } - - # TODO: Re-enable this once csharp is using the v2 ws api. - # - name: Check client-api bindings are up to date - # working-directory: sdks/csharp - # run: | - # bash tools~/gen-client-api.sh - # "${GITHUB_WORKSPACE}"/tools/check-diff.sh src/SpacetimeDB/ClientApi || { - # echo 'Error: Client API bindings are dirty. Please run `sdks/csharp/tools~/gen-client-api.sh`.' - # exit 1 - # } - - - name: Start SpacetimeDB - run: | - spacetime start & - disown - - - name: Run regression tests - run: | - bash sdks/csharp/tools~/run-regression-tests.sh - # Restore global.json symlinks (we replaced them with files to work around .NET 10 SDK bug) - # server is 5 levels deep from root, republishing dirs are 6 levels deep - if [ -f sdks/csharp/examples~/regression-tests/server/global.json ] && [ ! -L sdks/csharp/examples~/regression-tests/server/global.json ]; then - echo "Restoring symlink at server/global.json" - rm -f sdks/csharp/examples~/regression-tests/server/global.json - ln -s ../../../../../global.json sdks/csharp/examples~/regression-tests/server/global.json - fi - for dir in sdks/csharp/examples~/regression-tests/republishing/server-initial \ - sdks/csharp/examples~/regression-tests/republishing/server-republish; do - if [ -f "$dir/global.json" ] && [ ! -L "$dir/global.json" ]; then - echo "Restoring symlink at $dir/global.json" - rm -f "$dir/global.json" - ln -s ../../../../../../global.json "$dir/global.json" - fi - done - tools/check-diff.sh sdks/csharp/examples~/regression-tests || { - echo 'Error: Bindings are dirty. Please run `sdks/csharp/tools~/gen-regression-tests.sh`.' - exit 1 - } - - global_json_policy: - needs: [merge_queue_noop] - if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} - name: Verify global.json files are symlinks - runs-on: ubuntu-latest - permissions: - contents: read - env: - RUST_BACKTRACE: full - steps: - - name: Find Git ref - env: - PR_NUMBER: ${{ github.event.inputs.pr_number }} - run: | - if [ -n "$PR_NUMBER" ]; then - GIT_REF="refs/pull/$PR_NUMBER/merge" - else - GIT_REF="${{ github.ref }}" - fi - echo "GIT_REF=${GIT_REF}" >>"$GITHUB_ENV" - - - name: Checkout sources - uses: actions/checkout@v4 - with: - ref: ${{ env.GIT_REF }} - - - uses: dsherret/rust-toolchain-file@v1 - - name: Set default rust toolchain - run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) - - - name: Check global.json policy - run: cargo ci global-json-policy - - - name: Upload timing reports - if: always() - uses: actions/upload-artifact@v4 - with: - name: cargo-timings-global-json-policy - path: ${{ github.workspace }}/target/cargo-timings/ - retention-days: 14 - - smoketests_mod_rs_complete: - needs: [merge_queue_noop] - if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} - name: Check smoketests/mod.rs is complete - runs-on: ubuntu-latest - permissions: - contents: read - env: - RUST_BACKTRACE: full - steps: - - name: Find Git ref - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - shell: bash - run: | - PR_NUMBER="${{ github.event.inputs.pr_number || null }}" - if test -n "${PR_NUMBER}"; then - GIT_REF="$( gh pr view --repo clockworklabs/SpacetimeDB $PR_NUMBER --json headRefName --jq .headRefName )" - else - GIT_REF="${{ github.ref }}" - fi - echo "GIT_REF=${GIT_REF}" >>"$GITHUB_ENV" - - name: Checkout sources - uses: actions/checkout@v4 - with: - ref: ${{ env.GIT_REF }} - - uses: dsherret/rust-toolchain-file@v1 - - name: Set default rust toolchain - run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) - - - name: Verify smoketest module lists and suite constraints - run: | - cargo run -p ci-smoketest-checks - - docs-build: - needs: [merge_queue_noop] - if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} - name: Docs build - runs-on: spacetimedb-new-runner-2 - env: - RUST_BACKTRACE: full - steps: - - name: Checkout repository - uses: actions/checkout@v3 - - - name: Set up Node.js - uses: actions/setup-node@v3 - with: - node-version: '22' - - - uses: ./.github/actions/setup-pnpm - with: - run_install: true - - - uses: dsherret/rust-toolchain-file@v1 - - name: Set default rust toolchain - run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) - - - name: Docusaurus build - run: cargo ci docs - - - name: Upload timing reports - if: always() - uses: actions/upload-artifact@v4 - with: - name: cargo-timings-docs-build - path: ${{ github.workspace }}/target/cargo-timings/ - retention-days: 14 - - typescript-test: - needs: [merge_queue_noop] - if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} - name: TypeScript - Tests - runs-on: spacetimedb-new-runner-2 - env: - CARGO_TARGET_DIR: ${{ github.workspace }}/target - RUST_BACKTRACE: full - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: 22 - - - uses: ./.github/actions/setup-pnpm - with: - run_install: true - - # - name: Extract SpacetimeDB branch name from file - # id: extract-branch - # run: | - # # Define the path to the branch file - # BRANCH_FILE=".github/spacetimedb-branch.txt" - - # # Default to master if file doesn't exist - # if [ ! -f "$BRANCH_FILE" ]; then - # echo "::notice::No SpacetimeDB branch file found, using 'master'" - # echo "branch=master" >> $GITHUB_OUTPUT - # exit 0 - # fi - - # # Read and trim whitespace from the file - # branch=$(cat "$BRANCH_FILE" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//') - - # # Fallback to master if empty - # if [ -z "$branch" ]; then - # echo "::warning::SpacetimeDB branch file is empty, using 'master'" - # branch="master" - # fi - - # echo "branch=$branch" >> $GITHUB_OUTPUT - # echo "Using SpacetimeDB branch from file: $branch" - - - name: Install Rust toolchain - uses: dsherret/rust-toolchain-file@v1 - - name: Set default rust toolchain - run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) - - - *set-native-cache-keys - - *restore-jemalloc - - *configure-cached-jemalloc - - *restore-zstd - - *configure-cached-zstd - - *restore-rusty-v8-debug - - *restore-openssl - - *configure-cached-openssl - - # - name: Install SpacetimeDB CLI from the local checkout - # run: | - # export CARGO_HOME="$HOME/.cargo" - # echo "$CARGO_HOME/bin" >> "$GITHUB_PATH" - # cargo install --force --path crates/cli --locked --message-format=short - # cargo install --force --path crates/standalone --locked --message-format=short - # # Add a handy alias using the old binary name, so that we don't have to rewrite all scripts (incl. in submodules). - # ln -sf $CARGO_HOME/bin/spacetimedb-cli $CARGO_HOME/bin/spacetime - # # Clear any existing information - # spacetime server clear -y - - - name: Run TypeScript tests - run: cargo ci typescript-test - - - name: Upload timing reports - if: always() - uses: actions/upload-artifact@v4 - with: - name: cargo-timings-typescript-test - path: ${{ github.workspace }}/target/cargo-timings/ - retention-days: 14 - - # - name: Run quickstart-chat tests - # working-directory: examples/quickstart-chat - # run: pnpm test - # - # # Run this step always, even if the previous steps fail - # - name: Print rows in the user table - # if: always() - # run: spacetime sql quickstart-chat "SELECT * FROM user" From f1d1808e51ae9015197dde12700af11505af3e78 Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Mon, 24 Aug 2026 11:01:42 -0700 Subject: [PATCH 02/50] [bfops/test-runner]: update --- .github/workflows/ci.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cf16b35d321..a68959ac473 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -57,6 +57,11 @@ jobs: name: Set default rust toolchain run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) + - name: print some debug info + run: | + pwd -P + find ~ -maxdepth 2 + - name: Build CLI and standalone shell: bash run: | From b121a71d22f6b1338ed7a4457a6a8cf12df853e8 Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Mon, 24 Aug 2026 11:12:53 -0700 Subject: [PATCH 03/50] [bfops/test-runner]: use external dir --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a68959ac473..6ef658c74b3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,7 +27,7 @@ jobs: runs-on: spacetimedb-new-runner-2-staging timeout-minutes: 15 env: - CARGO_TARGET_DIR: ${{ github.workspace }}/target + CARGO_TARGET_DIR: $HOME/actions-runner/target RUST_BACKTRACE: full ARTIFACT_SUFFIX: linux EXE_SUFFIX: "" @@ -60,7 +60,7 @@ jobs: - name: print some debug info run: | pwd -P - find ~ -maxdepth 2 + find ~ -maxdepth 3 - name: Build CLI and standalone shell: bash @@ -74,8 +74,8 @@ jobs: shell: bash run: | tar -czf build-support.tar.gz \ - "target/release/spacetimedb-cli${EXE_SUFFIX}" \ - "target/release/spacetimedb-standalone${EXE_SUFFIX}" + "${CARGO_TARGET_DIR}/release/spacetimedb-cli${EXE_SUFFIX}" \ + "${CARGO_TARGET_DIR}/release/spacetimedb-standalone${EXE_SUFFIX}" - name: Upload Cargo timing reports if: always() From e96ea6c506780be5a62ee4d01c9cccbc63836659 Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Mon, 24 Aug 2026 11:15:51 -0700 Subject: [PATCH 04/50] [bfops/test-runner]: debug info --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6ef658c74b3..b2d00747ec5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -65,7 +65,7 @@ jobs: - name: Build CLI and standalone shell: bash run: | - cargo build --timings --release \ + cargo build -vv --timings --release \ -p spacetimedb-cli \ -p spacetimedb-standalone \ --features spacetimedb-standalone/allow_loopback_http_for_tests From 34db4fc8dcc2f4f410c63115834620e0e740bc8e Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Mon, 24 Aug 2026 11:20:47 -0700 Subject: [PATCH 05/50] [bfops/test-runner]: other build step --- .github/workflows/ci.yml | 49 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b2d00747ec5..19698ca7e63 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -95,3 +95,52 @@ jobs: if-no-files-found: error overwrite: true retention-days: 14 + + smoketest_build_linux: + needs: [upload-build-artifacts-linux] + name: Build smoketests (Linux) + runs-on: spacetimedb-new-runner-2 + timeout-minutes: 15 + env: + CARGO_TARGET_DIR: $HOME/actions-runner/target + RUST_BACKTRACE: full + ARTIFACT_SUFFIX: linux + EXE_SUFFIX: "" + SMOKETEST_SUITE: standalone + steps: &smoketest-build-steps + - *find-git-ref + + - *checkout-sources + + - uses: dsherret/rust-toolchain-file@v1 + - *set-default-rust-toolchain + + - name: Install cargo-nextest + uses: taiki-e/install-action@nextest + + - name: Build smoketest dependencies and archive test binaries + shell: bash + run: | + cargo run -vv --timings --package ci -- smoketests --suite "${SMOKETEST_SUITE}" archive --archive-file smoketest-nextest.tar.zst + + shopt -s nullglob + precompiled_modules=(${CARGET_TARGET_DIR}/wasm32-unknown-unknown/release/smoketest_module_*.wasm) + if (( ${#precompiled_modules[@]} == 0 )); then + echo "No precompiled smoketest modules were produced." + exit 1 + fi + + tar -czf smoketest-support.tar.gz \ + "${CARGO_TARGET_DIR}/debug/ci-smoketests${EXE_SUFFIX}" \ + "${precompiled_modules[@]}" + + - name: Upload smoketest build + uses: actions/upload-artifact@v4 + with: + name: smoketest-build-${{ env.ARTIFACT_SUFFIX }} + path: | + smoketest-nextest.tar.zst + smoketest-support.tar.gz + if-no-files-found: error + overwrite: true + retention-days: 14 From 039300dde5a73e975012ae07a2375ae10285f047 Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Mon, 24 Aug 2026 11:54:08 -0700 Subject: [PATCH 06/50] [bfops/test-runner]: rm other CI --- .github/workflows/internal-tests.yml | 93 ---------------------------- 1 file changed, 93 deletions(-) delete mode 100644 .github/workflows/internal-tests.yml diff --git a/.github/workflows/internal-tests.yml b/.github/workflows/internal-tests.yml deleted file mode 100644 index e2301d3da96..00000000000 --- a/.github/workflows/internal-tests.yml +++ /dev/null @@ -1,93 +0,0 @@ -# `SPACETIMEDB_PRIVATE_TOKEN` needs Actions read/write, Contents read, and Pull -# requests read access to clockworklabs/SpacetimeDBPrivate. -name: Internal Tests - -on: - pull_request: - push: - branches: - - master - merge_group: - workflow_dispatch: - -run-name: Internal Tests [ref=${{ github.ref }}] - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -permissions: - contents: read - pull-requests: read - -jobs: - internal-tests: - name: Internal Tests - # Skip if not a PR or a push to master - # Skip if this is an external contribution. GitHub secrets will be empty, so the step would fail anyway. - if: ${{ (github.event_name == 'pull_request' || (github.event_name == 'push' && github.ref == 'refs/heads/master')) - && (github.event_name != 'pull_request' || !github.event.pull_request.head.repo.fork) }} - runs-on: ubuntu-latest - env: - TARGET_OWNER: clockworklabs - TARGET_REPO: SpacetimeDBPrivate - steps: - # Required for the path filter check below on non-PR commits (e.g. `master`) - - name: Checkout - uses: actions/checkout@v4 - - # Skip the private dispatch entirely when only `docs/` is touched. The job - # itself still completes successfully so required-status-check gating is - # satisfied without spending private-runner time on a docs-only change. - - name: Detect non-docs changes - id: filter - uses: dorny/paths-filter@v3 - with: - filters: | - non_docs: - - '!docs/**' - - - id: dispatch - name: Select or trigger tests - if: steps.filter.outputs.non_docs == 'true' - env: - CARGO_TARGET_DIR: ${{ runner.temp }}/internal-tests-cargo-target - GH_TOKEN: ${{ secrets.SPACETIMEDB_PRIVATE_TOKEN }} - PUBLIC_PR_NUMBER: ${{ github.event.pull_request.number }} - PUBLIC_SHA: ${{ github.event.pull_request.head.sha || github.sha }} - run: | - set -euo pipefail - args=(--public-sha "$PUBLIC_SHA") - if [[ -n "$PUBLIC_PR_NUMBER" ]]; then - args+=(--public-pr-number "$PUBLIC_PR_NUMBER") - fi - cargo run --quiet \ - --manifest-path tools/ci/Cargo.toml \ - -- other-workflows coordinate-internal-tests "${args[@]}" - - - name: Wait for Internal Tests to complete - if: steps.filter.outputs.non_docs == 'true' - env: - GH_TOKEN: ${{ secrets.SPACETIMEDB_PRIVATE_TOKEN }} - RUN_ID: ${{ steps.dispatch.outputs.run_id }} - run: | - set -euo pipefail - cargo ci other-workflows watch \ - --repo "$TARGET_OWNER/$TARGET_REPO" \ - --run-id "$RUN_ID" - - - name: Cancel invoked run if workflow cancelled - if: ${{ cancelled() && steps.dispatch.outputs.run_id && steps.dispatch.outputs.did_start == 'true' }} - uses: actions/github-script@v7 - with: - github-token: ${{ secrets.SPACETIMEDB_PRIVATE_TOKEN }} - script: | - const targetOwner = process.env.TARGET_OWNER; - const targetRepo = process.env.TARGET_REPO; - const runId = Number(`${{ steps.dispatch.outputs.run_id }}`); - if (!runId) return; - await github.rest.actions.cancelWorkflowRun({ - owner: targetOwner, - repo: targetRepo, - run_id: runId, - }); From 3cbcc076dca94ce4a9993e88b811067540bbbfc1 Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Mon, 24 Aug 2026 11:59:18 -0700 Subject: [PATCH 07/50] [bfops/test-runner]: more debug info --- .github/workflows/ci.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 19698ca7e63..e0fad771e0d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -57,10 +57,12 @@ jobs: name: Set default rust toolchain run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) - - name: print some debug info - run: | - pwd -P - find ~ -maxdepth 3 + - name: print dir + run: pwd -P + - name: find files + run: find ~ -maxdepth 3 + - name: look for openssl stuff + run: find ${CARGO_TARGET_DIR}/release/build/openssl-* -type f - name: Build CLI and standalone shell: bash From db26171a592561ca4753241dfa045eada7eabf81 Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Mon, 24 Aug 2026 12:38:38 -0700 Subject: [PATCH 08/50] [bfops/test-runner]: set target dir --- .github/workflows/ci.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e0fad771e0d..0352e5f7a3c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,11 +27,15 @@ jobs: runs-on: spacetimedb-new-runner-2-staging timeout-minutes: 15 env: - CARGO_TARGET_DIR: $HOME/actions-runner/target RUST_BACKTRACE: full ARTIFACT_SUFFIX: linux EXE_SUFFIX: "" steps: &upload-build-artifact-steps + - &set-cargo-target-dir + name: Set Cargo target directory + shell: bash + run: echo "CARGO_TARGET_DIR=${HOME}/actions-runner/target" >>"${GITHUB_ENV}" + - &find-git-ref name: Find Git ref env: @@ -104,12 +108,13 @@ jobs: runs-on: spacetimedb-new-runner-2 timeout-minutes: 15 env: - CARGO_TARGET_DIR: $HOME/actions-runner/target RUST_BACKTRACE: full ARTIFACT_SUFFIX: linux EXE_SUFFIX: "" SMOKETEST_SUITE: standalone steps: &smoketest-build-steps + - *set-cargo-target-dir + - *find-git-ref - *checkout-sources From aafe302d94700b5bdd6bf10713c19d4cc7865ffb Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Mon, 24 Aug 2026 13:56:44 -0700 Subject: [PATCH 09/50] [bfops/test-runner]: un-vv --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0352e5f7a3c..ecac0b8d6f5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -71,7 +71,7 @@ jobs: - name: Build CLI and standalone shell: bash run: | - cargo build -vv --timings --release \ + cargo build --timings --release \ -p spacetimedb-cli \ -p spacetimedb-standalone \ --features spacetimedb-standalone/allow_loopback_http_for_tests @@ -128,7 +128,7 @@ jobs: - name: Build smoketest dependencies and archive test binaries shell: bash run: | - cargo run -vv --timings --package ci -- smoketests --suite "${SMOKETEST_SUITE}" archive --archive-file smoketest-nextest.tar.zst + cargo run --timings --package ci -- smoketests --suite "${SMOKETEST_SUITE}" archive --archive-file smoketest-nextest.tar.zst shopt -s nullglob precompiled_modules=(${CARGET_TARGET_DIR}/wasm32-unknown-unknown/release/smoketest_module_*.wasm) From a9f4e953eee1bbcf904e813c5da57b9588d72521 Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Mon, 24 Aug 2026 14:12:39 -0700 Subject: [PATCH 10/50] [bfops/test-runner]: fix target dir --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ecac0b8d6f5..0c7607d78e9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,7 +34,7 @@ jobs: - &set-cargo-target-dir name: Set Cargo target directory shell: bash - run: echo "CARGO_TARGET_DIR=${HOME}/actions-runner/target" >>"${GITHUB_ENV}" + run: echo "CARGO_TARGET_DIR=${HOME}/actions-runner/_work/target" >>"${GITHUB_ENV}" - &find-git-ref name: Find Git ref @@ -66,12 +66,12 @@ jobs: - name: find files run: find ~ -maxdepth 3 - name: look for openssl stuff - run: find ${CARGO_TARGET_DIR}/release/build/openssl-* -type f + run: find ${CARGO_TARGET_DIR}/release/build/openssl-* -type f || true - name: Build CLI and standalone shell: bash run: | - cargo build --timings --release \ + cargo build -vv --timings --release \ -p spacetimedb-cli \ -p spacetimedb-standalone \ --features spacetimedb-standalone/allow_loopback_http_for_tests @@ -128,7 +128,7 @@ jobs: - name: Build smoketest dependencies and archive test binaries shell: bash run: | - cargo run --timings --package ci -- smoketests --suite "${SMOKETEST_SUITE}" archive --archive-file smoketest-nextest.tar.zst + cargo run -vv --timings --package ci -- smoketests --suite "${SMOKETEST_SUITE}" archive --archive-file smoketest-nextest.tar.zst shopt -s nullglob precompiled_modules=(${CARGET_TARGET_DIR}/wasm32-unknown-unknown/release/smoketest_module_*.wasm) From 22158bd0ebe06305309cdab4172dc8df7297d712 Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Mon, 24 Aug 2026 14:12:54 -0700 Subject: [PATCH 11/50] [bfops/test-runner]: un-vv --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0c7607d78e9..6158994c764 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -71,7 +71,7 @@ jobs: - name: Build CLI and standalone shell: bash run: | - cargo build -vv --timings --release \ + cargo build --timings --release \ -p spacetimedb-cli \ -p spacetimedb-standalone \ --features spacetimedb-standalone/allow_loopback_http_for_tests @@ -128,7 +128,7 @@ jobs: - name: Build smoketest dependencies and archive test binaries shell: bash run: | - cargo run -vv --timings --package ci -- smoketests --suite "${SMOKETEST_SUITE}" archive --archive-file smoketest-nextest.tar.zst + cargo run --timings --package ci -- smoketests --suite "${SMOKETEST_SUITE}" archive --archive-file smoketest-nextest.tar.zst shopt -s nullglob precompiled_modules=(${CARGET_TARGET_DIR}/wasm32-unknown-unknown/release/smoketest_module_*.wasm) From 1664b3fe79780d3951b9f8305aa1223d66a3064c Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Mon, 24 Aug 2026 14:19:37 -0700 Subject: [PATCH 12/50] [bfops/test-runner]: re-vv --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6158994c764..0c7607d78e9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -71,7 +71,7 @@ jobs: - name: Build CLI and standalone shell: bash run: | - cargo build --timings --release \ + cargo build -vv --timings --release \ -p spacetimedb-cli \ -p spacetimedb-standalone \ --features spacetimedb-standalone/allow_loopback_http_for_tests @@ -128,7 +128,7 @@ jobs: - name: Build smoketest dependencies and archive test binaries shell: bash run: | - cargo run --timings --package ci -- smoketests --suite "${SMOKETEST_SUITE}" archive --archive-file smoketest-nextest.tar.zst + cargo run -vv --timings --package ci -- smoketests --suite "${SMOKETEST_SUITE}" archive --archive-file smoketest-nextest.tar.zst shopt -s nullglob precompiled_modules=(${CARGET_TARGET_DIR}/wasm32-unknown-unknown/release/smoketest_module_*.wasm) From b028af2e7fca03fa2c9f7bc7d0e72bf6b2aa247d Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Mon, 24 Aug 2026 14:23:44 -0700 Subject: [PATCH 13/50] [bfops/test-runner]: redo --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0c7607d78e9..bdd7d266805 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -65,8 +65,8 @@ jobs: run: pwd -P - name: find files run: find ~ -maxdepth 3 - - name: look for openssl stuff - run: find ${CARGO_TARGET_DIR}/release/build/openssl-* -type f || true + - name: look for target dir + run: find ${CARGO_TARGET_DIR} - name: Build CLI and standalone shell: bash From 8ca8e3698ccd242623edffe25a925d9384189a4e Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Mon, 24 Aug 2026 14:33:30 -0700 Subject: [PATCH 14/50] [bfops/test-runner]: restore mtimes --- .github/workflows/ci.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bdd7d266805..652fa66e6cf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,6 +56,11 @@ jobs: with: ref: ${{ env.GIT_REF }} + - &restore-source-mtimes + name: Restore source mtimes from git history + shell: bash + run: git restore-mtime --quiet + - uses: dsherret/rust-toolchain-file@v1 - &set-default-rust-toolchain name: Set default rust toolchain @@ -119,6 +124,8 @@ jobs: - *checkout-sources + - *restore-source-mtimes + - uses: dsherret/rust-toolchain-file@v1 - *set-default-rust-toolchain From e347e08df2b83deacf4ef66e3a5ffccf555ecd8b Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Mon, 24 Aug 2026 14:39:59 -0700 Subject: [PATCH 15/50] [bfops/test-runner]: fetch so restore mtimes can work --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 652fa66e6cf..e2ca27f9fe9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -55,6 +55,7 @@ jobs: uses: actions/checkout@v4 with: ref: ${{ env.GIT_REF }} + fetch-depth: 0 - &restore-source-mtimes name: Restore source mtimes from git history From 4b27ede6a66ec02cbbcd0388415588cd33034e90 Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Mon, 24 Aug 2026 14:40:05 -0700 Subject: [PATCH 16/50] [bfops/test-runner]: comments --- .github/workflows/ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e2ca27f9fe9..f3413548c0e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -55,8 +55,12 @@ jobs: uses: actions/checkout@v4 with: ref: ${{ env.GIT_REF }} + # Full history lets git restore-mtime recover each file's actual + # last-change timestamp instead of using the shallow checkout's timestamp. fetch-depth: 0 + # Cargo checks source mtimes for freshness, so restore committed mtimes to + # avoid invalidating otherwise reusable artifacts in the prebuilt target cache. - &restore-source-mtimes name: Restore source mtimes from git history shell: bash From d2702cf02b6204b0f17a700f9713bd037d85c8c7 Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Mon, 24 Aug 2026 15:21:21 -0700 Subject: [PATCH 17/50] [bfops/test-runner]: empty From 49ccb40c39b7a2a317aa0e6bcf7ed52a277a5390 Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Mon, 24 Aug 2026 15:33:02 -0700 Subject: [PATCH 18/50] [bfops/test-runner]: empty From e5dfab316b193e5b7aa75023830d0bb895003fd8 Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Mon, 24 Aug 2026 15:51:13 -0700 Subject: [PATCH 19/50] [bfops/test-runner]: move GIT_HASH from lib -> codegen --- crates/{lib => codegen}/build.rs | 0 crates/codegen/src/util.rs | 3 ++- crates/lib/src/version.rs | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) rename crates/{lib => codegen}/build.rs (100%) diff --git a/crates/lib/build.rs b/crates/codegen/build.rs similarity index 100% rename from crates/lib/build.rs rename to crates/codegen/build.rs diff --git a/crates/codegen/src/util.rs b/crates/codegen/src/util.rs index a13a7ff2aba..5a62afdd06f 100644 --- a/crates/codegen/src/util.rs +++ b/crates/codegen/src/util.rs @@ -56,6 +56,7 @@ pub(super) fn print_lines(output: &mut Indenter, lines: &[&str]) { } pub const AUTO_GENERATED_PREFIX: &str = "// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB"; +const GIT_HASH: &str = env!("GIT_HASH"); const AUTO_GENERATED_FILE_COMMENT: &[&str] = &[ "// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE", @@ -72,7 +73,7 @@ pub(super) fn print_auto_generated_version_comment(output: &mut Indenter) { output, "// This was generated using spacetimedb cli version {} (commit {}).", version::spacetimedb_lib_version(), - version::GIT_HASH + GIT_HASH ); writeln!(output); } diff --git a/crates/lib/src/version.rs b/crates/lib/src/version.rs index c0fc2454c05..ba06079aeb6 100644 --- a/crates/lib/src/version.rs +++ b/crates/lib/src/version.rs @@ -1,5 +1,4 @@ const CLI_VERSION: &str = env!("CARGO_PKG_VERSION"); -pub const GIT_HASH: &str = env!("GIT_HASH"); pub fn spacetimedb_lib_version() -> &'static str { CLI_VERSION From 7b9a48d3fedd6d1fb27880e84482731d77f250bc Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Mon, 24 Aug 2026 16:21:50 -0700 Subject: [PATCH 20/50] [bfops/test-runner]: bump CI From 0e0fafc33faaf019ac61b2883f588f0424c9e168 Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Mon, 24 Aug 2026 16:29:06 -0700 Subject: [PATCH 21/50] [bfops/test-runner]: remove unused debug --- .github/workflows/ci.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f3413548c0e..3cf94c43053 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -73,10 +73,6 @@ jobs: - name: print dir run: pwd -P - - name: find files - run: find ~ -maxdepth 3 - - name: look for target dir - run: find ${CARGO_TARGET_DIR} - name: Build CLI and standalone shell: bash From d4b731dccde188656805fac57931ca4d2e0e7c08 Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Mon, 24 Aug 2026 18:34:54 -0700 Subject: [PATCH 22/50] [bfops/test-runner]: fix typo --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3cf94c43053..05a2a63543e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -139,7 +139,7 @@ jobs: cargo run -vv --timings --package ci -- smoketests --suite "${SMOKETEST_SUITE}" archive --archive-file smoketest-nextest.tar.zst shopt -s nullglob - precompiled_modules=(${CARGET_TARGET_DIR}/wasm32-unknown-unknown/release/smoketest_module_*.wasm) + precompiled_modules=(${CARGO_TARGET_DIR}/wasm32-unknown-unknown/release/smoketest_module_*.wasm) if (( ${#precompiled_modules[@]} == 0 )); then echo "No precompiled smoketest modules were produced." exit 1 From 951bc55e84c970d253e97a05beafe5a10b0a513d Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Mon, 24 Aug 2026 18:37:25 -0700 Subject: [PATCH 23/50] [bfops/test-runner]: add -vv --- tools/ci/commands/smoketests/src/main.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/ci/commands/smoketests/src/main.rs b/tools/ci/commands/smoketests/src/main.rs index 3dbf2087fe7..67909ca2de8 100644 --- a/tools/ci/commands/smoketests/src/main.rs +++ b/tools/ci/commands/smoketests/src/main.rs @@ -120,7 +120,7 @@ fn main() -> Result<()> { fn build_cli() -> Result<()> { let mut cmd = Command::new("cargo"); - cmd.args(["build", "--timings", "--release", "-p", "spacetimedb-cli"]); + cmd.args(["build", "-vv", "--timings", "--release", "-p", "spacetimedb-cli"]); run_binary_build(cmd, "Failed to build CLI") } @@ -128,6 +128,7 @@ fn build_standalone() -> Result<()> { let mut cmd = Command::new("cargo"); cmd.args([ "build", + "-vv", "--timings", "--release", "-p", @@ -176,6 +177,7 @@ fn build_precompiled_modules() -> Result<()> { let status = Command::new("cargo") .args([ "build", + "-vv", "--timings", "--workspace", "--release", From 927ba28c070aa4fa5deda7aceaa6cee3250d3b6b Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Mon, 24 Aug 2026 18:41:38 -0700 Subject: [PATCH 24/50] [bfops/test-runner]: fix runner --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 05a2a63543e..d8b96f088b0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -111,7 +111,7 @@ jobs: smoketest_build_linux: needs: [upload-build-artifacts-linux] name: Build smoketests (Linux) - runs-on: spacetimedb-new-runner-2 + runs-on: spacetimedb-new-runner-2-staging timeout-minutes: 15 env: RUST_BACKTRACE: full From 824811fec6e1c8dc7b03b9ca868a25c641bcdb99 Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Mon, 24 Aug 2026 19:19:28 -0700 Subject: [PATCH 25/50] [bfops/test-runner]: bump CI From ebd4f759ccb4d224c902965417db7c4ad94bf4aa Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Tue, 25 Aug 2026 10:41:19 -0700 Subject: [PATCH 26/50] [bfops/test-runner]: restore rest of CI --- .github/workflows/ci.yml | 1401 ++++++++++++++++++++++++++ .github/workflows/internal-tests.yml | 93 ++ 2 files changed, 1494 insertions(+) create mode 100644 .github/workflows/internal-tests.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d8b96f088b0..fe9236c5fc9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,7 +22,57 @@ permissions: pull-requests: read jobs: + merge_queue_noop: + name: Detect merge queue no-op + runs-on: ubuntu-latest + outputs: + skip: ${{ steps.compare.outputs.skip }} + steps: + - name: Checkout merge queue commit + uses: actions/checkout@v4 + + - name: Compare merge queue commit to PR head + id: compare + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + HEAD_REF: ${{ github.event.merge_group.head_ref }} + shell: bash + run: | + set -euo pipefail + + echo "skip=false" >>"$GITHUB_OUTPUT" + + if [[ "${GITHUB_EVENT_NAME}" != "merge_group" ]]; then + echo "Not a merge_group event; running CI normally." + exit 0 + fi + + if [[ ! "${HEAD_REF}" =~ /pr-([0-9]+)- ]]; then + echo "Could not parse PR number from merge group head ref: ${HEAD_REF}" + exit 0 + fi + + pr_number="${BASH_REMATCH[1]}" + pr_head_sha="$(gh api "repos/${GITHUB_REPOSITORY}/pulls/${pr_number}" --jq '.head.sha')" + pr_head_repo="$(gh api "repos/${GITHUB_REPOSITORY}/pulls/${pr_number}" --jq '.head.repo.full_name')" + + if [[ -z "${pr_head_sha}" || "${pr_head_sha}" == "null" || -z "${pr_head_repo}" || "${pr_head_repo}" == "null" ]]; then + echo "Could not resolve PR head SHA for PR #${pr_number}; running CI normally." + exit 0 + fi + + git fetch --no-tags --depth=1 "https://github.com/${pr_head_repo}.git" "${pr_head_sha}" + + if git diff --quiet "${pr_head_sha}" "${GITHUB_SHA}" --; then + echo "Merge queue commit ${GITHUB_SHA} has the same tree as PR #${pr_number} head ${pr_head_sha}; skipping duplicate CI." + echo "skip=true" >>"$GITHUB_OUTPUT" + else + echo "Merge queue commit ${GITHUB_SHA} differs from PR #${pr_number} head ${pr_head_sha}; running CI normally." + fi + upload-build-artifacts-linux: + needs: [merge_queue_noop, lints] + if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} name: Upload build artifacts (Linux) runs-on: spacetimedb-new-runner-2-staging timeout-minutes: 15 @@ -108,6 +158,19 @@ jobs: overwrite: true retention-days: 14 + upload-build-artifacts-windows: + needs: [merge_queue_noop, lints] + if: true + name: Upload build artifacts (Windows) + runs-on: spacetimedb-windows-runner + timeout-minutes: 15 + env: + RUST_BACKTRACE: full + ARTIFACT_SUFFIX: windows + EXE_SUFFIX: .exe + OPENSSL_RUST_USE_NASM: "1" + steps: *upload-build-artifact-steps + smoketest_build_linux: needs: [upload-build-artifacts-linux] name: Build smoketests (Linux) @@ -149,6 +212,16 @@ jobs: "${CARGO_TARGET_DIR}/debug/ci-smoketests${EXE_SUFFIX}" \ "${precompiled_modules[@]}" + - name: Upload Cargo timing reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: smoketest-build-cargo-timings-${{ env.ARTIFACT_SUFFIX }} + path: ${{ env.CARGO_TARGET_DIR }}/cargo-timings/ + if-no-files-found: warn + overwrite: true + retention-days: 14 + - name: Upload smoketest build uses: actions/upload-artifact@v4 with: @@ -159,3 +232,1331 @@ jobs: if-no-files-found: error overwrite: true retention-days: 14 + + smoketest_build_windows: + needs: [upload-build-artifacts-windows] + name: Build smoketests (Windows) + runs-on: spacetimedb-windows-runner + timeout-minutes: 15 + env: + CARGO_TARGET_DIR: ${{ github.workspace }}/target + RUST_BACKTRACE: full + ARTIFACT_SUFFIX: windows + EXE_SUFFIX: .exe + OPENSSL_RUST_USE_NASM: "1" + SMOKETEST_SUITE: all + steps: *smoketest-build-steps + + smoketest_partitions_linux: + needs: [smoketest_build_linux] + name: Smoketests (Linux ${{ matrix.partition }}/1) + strategy: + fail-fast: false + matrix: + partition: [1] + runs-on: spacetimedb-new-runner-2 + timeout-minutes: 30 + env: + CARGO_TARGET_DIR: ${{ github.workspace }}/target + RUST_BACKTRACE: full + SPACETIMEDB_CPP_DIR: ${{ github.workspace }}/crates/bindings-cpp + ARTIFACT_SUFFIX: linux + PARTITION_COUNT: 1 + steps: &smoketest-partition-steps + - *find-git-ref + + - *checkout-sources + + - uses: dsherret/rust-toolchain-file@v1 + - *set-default-rust-toolchain + + - uses: actions/setup-dotnet@v4 + with: + global-json-file: global.json + + # Node.js and pnpm are required for the TypeScript smoketests. + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: 18 + + - uses: ./.github/actions/setup-pnpm + + - name: Install TypeScript SDK dependencies + run: pnpm --filter spacetimedb install + + # Install emscripten for C++ module compilation tests. + - name: Install emscripten (Linux) + if: runner.os == 'Linux' + shell: bash + run: | + git clone https://github.com/emscripten-core/emsdk.git ~/emsdk + cd ~/emsdk + ./emsdk install 4.0.21 + ./emsdk activate 4.0.21 + + - name: Install emscripten (Windows) + if: runner.os == 'Windows' + shell: pwsh + run: | + git clone https://github.com/emscripten-core/emsdk.git $env:USERPROFILE\emsdk + cd $env:USERPROFILE\emsdk + .\emsdk install 4.0.21 + .\emsdk activate 4.0.21 + + - name: Install psql + if: runner.os == 'Windows' + shell: pwsh + run: | + # Fail properly if any individual command fails + $ErrorActionPreference = 'Stop' + $PSNativeCommandUseErrorActionPreference = $true + choco install psql -y --no-progress + # Check for existence, since `choco` doesn't seem to fail the step if it fails to install.. + # See https://github.com/clockworklabs/SpacetimeDB/pull/4399 for more background. + Get-Command psql + + - name: Update dotnet workloads + if: runner.os == 'Windows' + shell: pwsh + run: | + # Fail properly if any individual command fails + $ErrorActionPreference = 'Stop' + $PSNativeCommandUseErrorActionPreference = $true + + cd modules + # the sdk-manifests on windows-latest are messed up, so we need to update them + dotnet workload config --update-mode manifests + dotnet workload update --from-previous-sdk + # Explicitly install wasi-experimental for .NET 8 SDK (needed for test_build_csharp_module) + # Create temp global.json to target .NET 8 SDK for workload install + $sdk8Json = '{"sdk":{"version":"8.0.400","rollForward":"latestFeature"}}' + $sdk8Json | Out-File -FilePath global.json -Encoding utf8 + dotnet workload install wasi-experimental + Remove-Item global.json + + - name: Override NuGet packages + shell: bash + run: | + dotnet pack -c Release crates/bindings-csharp/BSATN.Runtime + dotnet pack -c Release crates/bindings-csharp/Runtime + cd sdks/csharp + ./tools~/write-nuget-config.sh ../.. + + - name: Install cargo-nextest + uses: taiki-e/install-action@nextest + + - name: Download build artifacts + uses: actions/download-artifact@v4 + with: + name: build-artifacts-${{ env.ARTIFACT_SUFFIX }} + path: build-artifacts + + - name: Extract build artifacts + shell: bash + run: | + tar -xzf build-artifacts/build-support.tar.gz + exe_suffix="" + if [[ "${RUNNER_OS}" == "Windows" ]]; then + exe_suffix=".exe" + fi + test -f "${CARGO_TARGET_DIR}/release/spacetimedb-cli${exe_suffix}" + test -f "${CARGO_TARGET_DIR}/release/spacetimedb-standalone${exe_suffix}" + + - name: Download smoketest build + uses: actions/download-artifact@v4 + with: + name: smoketest-build-${{ env.ARTIFACT_SUFFIX }} + + - name: Extract smoketest support files + shell: bash + run: tar -xzf smoketest-support.tar.gz + + # Serial execution avoids contention between the C# tests over generated bindings. + - name: Run smoketest partition (Linux) + if: runner.os == 'Linux' + shell: bash + run: | + if [ -f ~/emsdk/emsdk_env.sh ]; then + source ~/emsdk/emsdk_env.sh + fi + ./target/debug/ci-smoketests run-archive \ + --archive-file smoketest-nextest.tar.zst \ + -- \ + --partition hash:${{ matrix.partition }}/${{ env.PARTITION_COUNT }} + + # Due to Emscripten PATH issues this remains separate from the Linux command. + - name: Run smoketest partition (Windows) + if: runner.os == 'Windows' + shell: pwsh + run: | + if (Test-Path "$env:USERPROFILE\emsdk\emsdk_env.ps1") { + & "$env:USERPROFILE\emsdk\emsdk_env.ps1" | Out-Null + } + .\target\debug\ci-smoketests.exe run-archive ` + --archive-file smoketest-nextest.tar.zst ` + -- ` + --partition hash:${{ matrix.partition }}/${{ env.PARTITION_COUNT }} + + - name: Upload timing reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: cargo-timings-smoketests-${{ matrix.name }} + path: ${{ env.CARGO_TARGET_DIR }}/cargo-timings/ + retention-days: 14 + + smoketest_partitions_windows: + needs: [smoketest_build_windows] + name: Smoketests (Windows ${{ matrix.partition }}/4) + strategy: + fail-fast: false + matrix: + partition: [1, 2, 3, 4] + runs-on: spacetimedb-windows-runner + timeout-minutes: 30 + env: + CARGO_TARGET_DIR: ${{ github.workspace }}/target + RUST_BACKTRACE: full + SPACETIMEDB_CPP_DIR: ${{ github.workspace }}/crates/bindings-cpp + ARTIFACT_SUFFIX: windows + PARTITION_COUNT: 4 + steps: *smoketest-partition-steps + + # this is a no-op version of the above check with a trivially-passing body. + # we can't just let the check be entirely skipped because each matrix target is a required check, + # and skipping this check means that the matrix isn't "populated" so the required checks wouldn't be met. + smoketests_noop: + needs: [merge_queue_noop] + if: ${{ needs.merge_queue_noop.outputs.skip == 'true' }} + name: Smoketests (${{ matrix.name }}) + strategy: + matrix: + include: + - name: Linux 1/1 + - name: Windows 1/4 + - name: Windows 2/4 + - name: Windows 3/4 + - name: Windows 4/4 + runs-on: ubuntu-latest + steps: + - name: Skip duplicate merge queue smoketest + run: echo "Merge queue commit has the same tree as the PR head; smoketest already ran for the PR." + + test: + needs: [merge_queue_noop, lints] + if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} + name: Test Suite + runs-on: spacetimedb-new-runner-2 + + env: + CARGO_TARGET_DIR: ${{ github.workspace }}/target + RUST_BACKTRACE: full + steps: + - name: Find Git ref + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + PR_NUMBER="${{ github.event.inputs.pr_number || null }}" + if test -n "${PR_NUMBER}"; then + GIT_REF="$( gh pr view --repo clockworklabs/SpacetimeDB $PR_NUMBER --json headRefName --jq .headRefName )" + else + GIT_REF="${{ github.ref }}" + fi + echo "GIT_REF=${GIT_REF}" >>"$GITHUB_ENV" + + - name: Checkout sources + uses: actions/checkout@v4 + with: + ref: ${{ env.GIT_REF }} + + - uses: dsherret/rust-toolchain-file@v1 + - name: Set default rust toolchain + run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) + - *set-native-cache-keys + - &restore-jemalloc + name: Restore jemalloc + id: cache-jemalloc + if: runner.os == 'Linux' + uses: actions/cache/restore@v4 + with: *jemalloc-cache + - *configure-cached-jemalloc + - &restore-zstd + name: Restore Zstd + id: cache-zstd + if: runner.os == 'Linux' + uses: actions/cache/restore@v4 + with: *zstd-cache + - *configure-cached-zstd + - &restore-rusty-v8-debug + name: Restore rusty_v8 (debug) + uses: actions/cache/restore@v4 + with: &v8-debug-cache + path: ${{ env.CARGO_TARGET_DIR }}/debug/gn_out/obj + key: ${{ steps.native-cache-keys.outputs.v8-debug-key }} + - &restore-rusty-v8 + name: Restore rusty_v8 + uses: actions/cache/restore@v4 + with: *v8-release-cache + - *restore-openssl + - *configure-cached-openssl + + - uses: actions/setup-dotnet@v3 + with: + global-json-file: global.json + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: 22 + + - uses: ./.github/actions/setup-pnpm + with: + run_install: true + + # Install cmake and emscripten for C++ module compilation tests. + - name: Install cmake and emscripten + run: | + sudo apt-get update + sudo apt-get install -y cmake + git clone https://github.com/emscripten-core/emsdk.git ~/emsdk + cd ~/emsdk + ./emsdk install 4.0.21 + ./emsdk activate 4.0.21 + + - name: Install wasm-bindgen CLI + run: | + REQUIRED_WASM_BINDGEN_VERSION="$( + awk ' + $1 == "name" && $3 == "\"wasm-bindgen\"" { in_pkg = 1; next } + in_pkg && $1 == "version" { + gsub(/"/, "", $3); + print $3; + exit; + } + ' Cargo.lock + )" + if [ -z "${REQUIRED_WASM_BINDGEN_VERSION}" ]; then + echo "Failed to determine wasm-bindgen version from Cargo.lock" + exit 1 + fi + + INSTALLED_WASM_BINDGEN_VERSION="$(wasm-bindgen --version 2>/dev/null | awk '{print $2}' || true)" + if [ "${INSTALLED_WASM_BINDGEN_VERSION}" != "${REQUIRED_WASM_BINDGEN_VERSION}" ]; then + cargo install --locked --force wasm-bindgen-cli --version "${REQUIRED_WASM_BINDGEN_VERSION}" + fi + + wasm-bindgen --version + + # Source emsdk environment to make emcc (Emscripten compiler) available in PATH. + - name: Run tests + run: | + source ~/emsdk/emsdk_env.sh + cargo ci test + + - name: Upload timing reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: cargo-timings-test + path: ${{ env.CARGO_TARGET_DIR }}/cargo-timings/ + retention-days: 14 + + index_scan_bench: + needs: [merge_queue_noop, lints] + if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} + name: Index Scan Bench + runs-on: spacetimedb-benchmark-runner + concurrency: + group: ci-benchmark-runner + queue: max + timeout-minutes: 60 + env: + CARGO_TARGET_DIR: ${{ github.workspace }}/target + RUST_BACKTRACE: full + steps: + - name: Find Git ref + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + PR_NUMBER="${{ github.event.inputs.pr_number || null }}" + if test -n "${PR_NUMBER}"; then + GIT_REF="$( gh pr view --repo clockworklabs/SpacetimeDB $PR_NUMBER --json headRefName --jq .headRefName )" + else + GIT_REF="${{ github.ref }}" + fi + echo "GIT_REF=${GIT_REF}" >>"$GITHUB_ENV" + + - name: Checkout sources + uses: actions/checkout@v4 + with: + ref: ${{ env.GIT_REF }} + + - uses: dsherret/rust-toolchain-file@v1 + - name: Set default rust toolchain + run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) + + - *set-native-cache-keys + - *restore-jemalloc + - *configure-cached-jemalloc + - *restore-zstd + - *configure-cached-zstd + - *restore-rusty-v8 + - *restore-openssl + - *configure-cached-openssl + + - name: Run index scan benchmark regression check + run: cargo run --release -p spacetimedb-index-scan-gate + + lints: + needs: [merge_queue_noop] + if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} + name: Lints + runs-on: spacetimedb-new-runner-2 + env: + CARGO_TARGET_DIR: ${{ github.workspace }}/target + RUST_BACKTRACE: full + steps: + - name: Checkout sources + uses: actions/checkout@v3 + + - uses: dsherret/rust-toolchain-file@v1 + - name: Set default rust toolchain + run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) + - run: echo ::add-matcher::.github/workflows/rust_matcher.json + + - *set-native-cache-keys + - *restore-jemalloc + - *configure-cached-jemalloc + - *restore-zstd + - *configure-cached-zstd + - name: Cache rusty_v8 (debug) + uses: actions/cache@v4 + with: *v8-debug-cache + - *restore-openssl + - *configure-cached-openssl + + - uses: actions/setup-dotnet@v3 + with: + global-json-file: global.json + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: 22 + + - uses: ./.github/actions/setup-pnpm + with: + run_install: true + + - name: Run ci lint + run: cargo ci lint + + - name: Upload timing reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: cargo-timings-public-lints + path: ${{ env.CARGO_TARGET_DIR }}/cargo-timings/ + retention-days: 14 + + codeowners_check: + if: ${{ github.event_name == 'pull_request' }} + name: CODEOWNERS check + runs-on: spacetimedb-new-runner-2 + permissions: + contents: read + pull-requests: read + env: + CARGO_TARGET_DIR: ${{ github.workspace }}/target + RUST_BACKTRACE: full + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: dsherret/rust-toolchain-file@v1 + - name: Set default rust toolchain + run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) + + - name: Run CODEOWNERS check + run: | + cargo ci other-workflows codeowners-check \ + --base-ref "origin/${{ github.event.pull_request.base.ref }}" \ + --pr-number "${{ github.event.pull_request.number }}" + + - name: Upload timing reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: cargo-timings-codeowners-check + path: ${{ env.CARGO_TARGET_DIR }}/cargo-timings/ + retention-days: 14 + + wasm_bindings: + needs: [merge_queue_noop] + if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} + name: Build and test wasm bindings + runs-on: spacetimedb-new-runner-2 + env: + CARGO_TARGET_DIR: ${{ github.workspace }}/target + RUST_BACKTRACE: full + steps: + - uses: actions/checkout@v3 + + - uses: dsherret/rust-toolchain-file@v1 + - name: Set default rust toolchain + run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) + - run: echo ::add-matcher::.github/workflows/rust_matcher.json + + - *set-native-cache-keys + - *restore-jemalloc + - *configure-cached-jemalloc + - *restore-zstd + - *configure-cached-zstd + - *restore-openssl + - *configure-cached-openssl + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: 22 + + - uses: ./.github/actions/setup-pnpm + + - name: Run bindgen tests + run: cargo ci wasm-bindings + + - name: Upload timing reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: cargo-timings-wasm-bindings + path: ${{ env.CARGO_TARGET_DIR }}/cargo-timings/ + retention-days: 14 + + publish_checks: + needs: [merge_queue_noop] + if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} + name: Check that packages are publishable + runs-on: spacetimedb-new-runner-2 + permissions: read-all + env: + RUST_BACKTRACE: full + steps: + - uses: actions/checkout@v3 + - uses: dsherret/rust-toolchain-file@v1 + - name: Set default rust toolchain + run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) + - name: Run checks + run: cargo ci publish-checks + + - name: Upload timing reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: cargo-timings-publish-checks + path: ${{ github.workspace }}/target/cargo-timings/ + retention-days: 14 + + update: + needs: [merge_queue_noop] + if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} + name: Test spacetimedb-update flow (${{ matrix.target }}) + permissions: read-all + strategy: + matrix: + include: + - { target: x86_64-unknown-linux-gnu, runner: spacetimedb-new-runner-2 } + - { target: aarch64-apple-darwin, runner: macos-latest } + - { target: x86_64-pc-windows-msvc, runner: windows-latest } + runs-on: ${{ matrix.runner }} + env: + RUST_BACKTRACE: full + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Install Rust + uses: dsherret/rust-toolchain-file@v1 + - name: Set default rust toolchain + run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) + + - *set-native-cache-keys + - *restore-zstd + - *configure-cached-zstd + + - name: Install rust target + run: rustup target add ${{ matrix.target }} + + - name: Test spacetimedb-update + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: cargo ci update-flow --target=${{ matrix.target }} --github-token-auth + + - name: Upload timing reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: cargo-timings-update-flow-${{ matrix.target }} + path: ${{ github.workspace }}/target/cargo-timings/ + retention-days: 14 + + # this is a no-op version of the above check with a trivially-passing body. + # we can't just let the check be entirely skipped because each matrix target is a required check, + # and skipping this check means that the matrix isn't "populated" so the required checks wouldn't be met. + update_noop: + needs: [merge_queue_noop] + if: ${{ needs.merge_queue_noop.outputs.skip == 'true' }} + name: Test spacetimedb-update flow (${{ matrix.target }}) + permissions: read-all + strategy: + matrix: + include: + - { target: x86_64-unknown-linux-gnu } + - { target: aarch64-apple-darwin } + - { target: x86_64-pc-windows-msvc } + runs-on: ubuntu-latest + steps: + - name: Skip duplicate merge queue update test + run: echo "Merge queue commit has the same tree as the PR head; update-flow already ran for the PR." + + unreal_engine_tests: + name: Unreal Engine Tests + # This can't go on e.g. ubuntu-latest because that runner runs out of disk space. ChatGPT suggested that the general solution tends to be to use + # a custom runner. + runs-on: spacetimedb-new-runner-2 + # Disable the tests because they are very flaky at the moment. + # TODO: Remove this line and re-enable the `if` line just below here. + if: false + # Skip if this is an external contribution. GitHub secrets will be empty, so the step would fail anyway. + # if: ${{ github.event_name != 'pull_request' || !github.event.pull_request.head.repo.fork }} + container: + image: ghcr.io/epicgames/unreal-engine:dev-5.6 + credentials: + # Note(bfops): I don't think that `github.actor` needs to match the user that the token is for, because I'm using a token for my account and + # it seems to be totally happy. + # However, the token needs to be for a user that has access to the EpicGames org (see + # https://dev.epicgames.com/documentation/en-us/unreal-engine/downloading-source-code-in-unreal-engine?application_version=5.6) + username: ${{ github.actor }} + password: ${{ secrets.GHCR_TOKEN }} + # Run as root because otherwise we get permission denied for various directories inside the container. I tried doing dances to allow it to run + # without this (reassigning env vars and stuff), but was unable to get it to work and it felt like an uphill battle. + options: --user 0:0 + env: + RUST_BACKTRACE: full + steps: + # Uncomment this before merging so that it will run properly if run manually through the GH actions flow. It was playing weird with rolled back + # commits though. + # - name: Find Git ref + # env: + # GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # shell: bash + # run: | + # PR_NUMBER="${{ github.event.inputs.pr_number || null }}" + # if test -n "${PR_NUMBER}"; then + # GIT_REF="$( gh pr view --repo clockworklabs/SpacetimeDB $PR_NUMBER --json headRefName --jq .headRefName )" + # else + # GIT_REF="${{ github.ref }}" + # fi + # echo "GIT_REF=${GIT_REF}" >>"$GITHUB_ENV" + - name: Checkout sources + uses: actions/checkout@v4 + with: + ref: ${{ env.GIT_REF }} + - uses: dsherret/rust-toolchain-file@v1 + - name: Set default rust toolchain + run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) + - name: Run Unreal Engine tests + working-directory: sdks/unreal + env: + UE_ROOT_PATH: /home/ue4/UnrealEngine + run: | + + apt-get update + apt-get install -y acl curl ca-certificates + + REPO="$GITHUB_WORKSPACE" + # Let ue4 read/write the workspace & tool caches without changing ownership + for p in "$REPO" "${RUNNER_TEMP:-/__t}" "${RUNNER_TOOL_CACHE:-/__t}"; do + [ -d "$p" ] && setfacl -R -m u:ue4:rwX -m d:u:ue4:rwX "$p" || true + done + + # Rust tool caches live under the runner tool cache so they persist + export CARGO_HOME="${RUNNER_TOOL_CACHE:-/__t}/cargo" + export RUSTUP_HOME="${RUNNER_TOOL_CACHE:-/__t}/rustup" + mkdir -p "$CARGO_HOME" "$RUSTUP_HOME" + chown -R ue4:ue4 "$CARGO_HOME" "$RUSTUP_HOME" + + # Make sure the UE build script is executable (and parents traversable) + UE_DIR="${UE_ROOT_PATH:-/home/ue4/UnrealEngine}" + chmod a+rx "$UE_DIR" "$UE_DIR/Engine" "$UE_DIR/Engine/Build" "$UE_DIR/Engine/Build/BatchFiles/Linux" || true + chmod a+rx "$UE_DIR/Engine/Build/BatchFiles/Linux/Build.sh" || true + + # Run the build & tests as ue4 (who owns the UE tree) + sudo -E -H -u ue4 env \ + HOME=/home/ue4 \ + XDG_CONFIG_HOME=/home/ue4/.config \ + CARGO_HOME="$CARGO_HOME" \ + RUSTUP_HOME="$RUSTUP_HOME" \ + PATH="$CARGO_HOME/bin:$PATH" \ + bash -lc ' + set -euxo pipefail + # Install rustup for ue4 if needed (uses the shared caches) + if ! command -v cargo >/dev/null 2>&1; then + curl -sSf https://sh.rustup.rs | sh -s -- -y + fi + rustup show >/dev/null + git config --global --add safe.directory "$GITHUB_WORKSPACE" || true + + cd "$GITHUB_WORKSPACE/sdks/unreal" + cargo --version + cargo test -- --test-threads=1 + ' + + cli_docs: + needs: [merge_queue_noop] + if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} + name: Check CLI docs + permissions: read-all + runs-on: spacetimedb-new-runner-2 + env: + CARGO_TARGET_DIR: ${{ github.workspace }}/target + RUST_BACKTRACE: full + steps: + - name: Find Git ref + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + shell: bash + run: | + PR_NUMBER="${{ github.event.inputs.pr_number || null }}" + if test -n "${PR_NUMBER}"; then + GIT_REF="$( gh pr view --repo clockworklabs/SpacetimeDB $PR_NUMBER --json headRefName --jq .headRefName )" + else + GIT_REF="${{ github.ref }}" + fi + echo "GIT_REF=${GIT_REF}" >>"$GITHUB_ENV" + + - name: Checkout sources + uses: actions/checkout@v4 + with: + ref: ${{ env.GIT_REF }} + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: 22 + + - uses: ./.github/actions/setup-pnpm + with: + run_install: true + + - uses: dsherret/rust-toolchain-file@v1 + - name: Set default rust toolchain + run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) + + - *set-native-cache-keys + - *restore-jemalloc + - *configure-cached-jemalloc + - *restore-zstd + - *configure-cached-zstd + - *restore-openssl + - *configure-cached-openssl + + - name: Check for docs change + run: | + cargo ci cli-docs + + - name: Upload timing reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: cargo-timings-cli-docs + path: ${{ env.CARGO_TARGET_DIR }}/cargo-timings/ + retention-days: 14 + + unity-testsuite: + needs: [merge_queue_noop, lints] + # Skip if this is an external contribution. + # The license secrets will be empty, so the step would fail anyway. + if: ${{ needs.merge_queue_noop.outputs.skip != 'true' && (github.event_name != 'pull_request' || !github.event.pull_request.head.repo.fork) }} + permissions: + contents: read + checks: write + runs-on: spacetimedb-unity-runner + timeout-minutes: 30 + env: + CARGO_TARGET_DIR: ${{ github.workspace }}/target + RUST_BACKTRACE: full + UNITY_VERSION: 2022.3.32f1 + steps: + - name: Checkout repository + id: checkout-stdb + uses: actions/checkout@v4 + + # Keep this before generation/hydration so ignored build outputs do not affect hashFiles. + - name: Restore Unity Library + id: restore-unity-library + uses: actions/cache/restore@v4 + with: + path: demo/Blackholio/client-unity/Library + key: Unity-v2-${{ runner.os }}-${{ env.UNITY_VERSION }}-${{ hashFiles('demo/Blackholio/client-unity/**', 'sdks/csharp/**', 'crates/bindings-csharp/BSATN.Runtime/**', 'crates/bindings-csharp/Runtime/**', 'crates/bindings-csharp/Directory.Build.props', 'tools/regen/src/csharp.rs', 'global.json') }} + restore-keys: | + Unity-v2-${{ runner.os }}-${{ env.UNITY_VERSION }}- + + # Run cheap .NET tests first. If those fail, no need to run expensive Unity tests. + + - name: Setup dotnet + uses: actions/setup-dotnet@v3 + with: + global-json-file: global.json + + - name: Override NuGet packages + run: | + dotnet pack crates/bindings-csharp/BSATN.Runtime + dotnet pack crates/bindings-csharp/Runtime + + # Write out the nuget config file to `nuget.config`. This causes the spacetimedb-csharp-sdk repository + # to be aware of the local versions of the `bindings-csharp` packages in SpacetimeDB, and use them if + # available. Otherwise, `spacetimedb-csharp-sdk` will use the NuGet versions of the packages. + # This means that (if version numbers match) we will test the local versions of the C# packages, even + # if they're not pushed to NuGet. + # See https://learn.microsoft.com/en-us/nuget/reference/nuget-config-file for more info on the config file. + cd sdks/csharp + ./tools~/write-nuget-config.sh ../.. + + - name: Restore .NET solution + working-directory: sdks/csharp + run: dotnet restore --configfile NuGet.Config SpacetimeDB.ClientSDK.sln + + # Now, setup the Unity tests. + - name: Patch spacetimedb dependency in Cargo.toml + working-directory: demo/Blackholio/server-rust + run: | + sed -i "s|spacetimedb *=.*|spacetimedb = \{ path = \"../../../crates/bindings\" \}|" Cargo.toml + cat Cargo.toml + + - name: Install Rust toolchain + uses: dsherret/rust-toolchain-file@v1 + - name: Set default rust toolchain + run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) + + - *set-native-cache-keys + - *restore-jemalloc + - *configure-cached-jemalloc + - *restore-zstd + - *configure-cached-zstd + - *restore-rusty-v8 + - *restore-openssl + - *configure-cached-openssl + + - name: Install SpacetimeDB CLI from the local checkout + run: | + export CARGO_HOME="$HOME/.cargo" + echo "$CARGO_HOME/bin" >> "$GITHUB_PATH" + cargo install --force --path crates/cli --locked --message-format=short + cargo install --force --path crates/standalone --locked --message-format=short + # Add a handy alias using the old binary name, so that we don't have to rewrite all scripts (incl. in submodules). + ln -sf $CARGO_HOME/bin/spacetimedb-cli $CARGO_HOME/bin/spacetime + + - name: Generate client bindings + working-directory: demo/Blackholio/server-rust + run: bash ./generate.sh -y + + - name: Check for changes + run: | + tools/check-diff.sh demo/Blackholio/client-unity/Assets/Scripts/autogen || { + echo 'Error: Bindings are dirty. Please run `demo/Blackholio/server-rust/generate.sh`.' + exit 1 + } + + - name: Hydrate Unity SDK DLLs + run: cargo regen csharp dlls + + - name: Check Unity meta files + uses: DeNA/unity-meta-check@v3 + with: + enable_pr_comment: ${{ github.event_name == 'pull_request' }} + target_path: sdks/csharp + env: + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + + - name: Start SpacetimeDB + run: | + spacetime start & + disown + + - name: Publish unity-tests module to SpacetimeDB + working-directory: demo/Blackholio/server-rust + run: | + spacetime logout && spacetime login --server-issued-login local + bash ./publish.sh + + - name: Patch com.clockworklabs.spacetimedbsdk dependency in manifest.json + working-directory: demo/Blackholio/client-unity/Packages + run: | + yq e -i '.dependencies["com.clockworklabs.spacetimedbsdk"] = "file:../../../../sdks/csharp"' manifest.json + cat manifest.json + + - name: Run Unity tests + uses: game-ci/unity-test-runner@v4 + with: + unityVersion: ${{ env.UNITY_VERSION }} + projectPath: demo/Blackholio/client-unity # Path to the Unity project subdirectory + githubToken: ${{ secrets.GITHUB_TOKEN }} + testMode: playmode + useHostNetwork: true + artifactsPath: "" + env: + UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }} + UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }} + UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }} + + - name: Save Unity Library + if: ${{ github.ref == 'refs/heads/master' && steps.restore-unity-library.outputs.cache-hit != 'true' }} + uses: actions/cache/save@v4 + with: + path: demo/Blackholio/client-unity/Library + key: ${{ steps.restore-unity-library.outputs.cache-primary-key }} + + godot-testsuite: + needs: [merge_queue_noop, lints] + if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} + permissions: + contents: read + runs-on: spacetimedb-new-runner-2 + env: + CARGO_TARGET_DIR: ${{ github.workspace }}/target + UseLocalBsatnRuntime: true + steps: + - name: Checkout repository + id: checkout-stdb + uses: actions/checkout@v4 + + - name: Setup dotnet + uses: actions/setup-dotnet@v3 + with: + global-json-file: global.json + + - name: Override NuGet packages + run: | + dotnet pack -c Release crates/bindings-csharp/BSATN.Runtime + dotnet pack -c Release crates/bindings-csharp/Runtime + + # Write out the nuget config file to `nuget.config`. This causes the spacetimedb-csharp-sdk repository + # to be aware of the local versions of the `bindings-csharp` packages in SpacetimeDB, and use them if + # available. Otherwise, `spacetimedb-csharp-sdk` will use the NuGet versions of the packages. + # This means that (if version numbers match) we will test the local versions of the C# packages, even + # if they're not pushed to NuGet. + # See https://learn.microsoft.com/en-us/nuget/reference/nuget-config-file for more info on the config file. + cd sdks/csharp + ./tools~/write-nuget-config.sh ../.. + + - name: Restore .NET solution + working-directory: sdks/csharp + run: dotnet restore --configfile NuGet.Config SpacetimeDB.ClientSDK.sln + + # Now, setup the Godot tests. + - name: Patch spacetimedb dependency in Cargo.toml + working-directory: demo/Blackholio/server-rust + run: | + sed -i "s|spacetimedb *=.*|spacetimedb = \{ path = \"../../../crates/bindings\" \}|" Cargo.toml + cat Cargo.toml + + - name: Install Rust toolchain + uses: dsherret/rust-toolchain-file@v1 + - name: Set default rust toolchain + run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) + + - *set-native-cache-keys + - *restore-jemalloc + - *configure-cached-jemalloc + - *restore-zstd + - *configure-cached-zstd + - *restore-rusty-v8 + - *restore-openssl + - *configure-cached-openssl + + - name: Install SpacetimeDB CLI from the local checkout + run: | + export CARGO_HOME="$HOME/.cargo" + echo "$CARGO_HOME/bin" >> "$GITHUB_PATH" + cargo install --force --path crates/cli --locked --message-format=short + cargo install --force --path crates/standalone --locked --message-format=short + # Add a handy alias using the old binary name, so that we don't have to rewrite all scripts (incl. in submodules). + ln -sf $CARGO_HOME/bin/spacetimedb-cli $CARGO_HOME/bin/spacetime + + - name: Generate client bindings + working-directory: demo/Blackholio/server-rust + run: bash ./generate.sh -y + + - name: Check for changes + run: | + tools/check-diff.sh demo/Blackholio/client-godot/module_bindings || { + echo 'Error: Godot bindings are dirty. Please run `demo/Blackholio/server-rust/generate.sh`.' + exit 1 + } + + - name: Patch SpacetimeDB Godot SDK dependency + working-directory: demo/Blackholio/client-godot + run: | + dotnet remove package SpacetimeDB.ClientSDK.Godot + dotnet add reference ../../../sdks/csharp/SpacetimeDB.ClientSDK.Godot.csproj + cat blackholio.csproj + + - name: Setup Godot + uses: chickensoft-games/setup-godot@v2 + with: + version: 4.6.2 + use-dotnet: true + + - name: Restore Godot project + working-directory: demo/Blackholio/client-godot + run: dotnet restore --configfile ../../../NuGet.Config blackholio.csproj + + - name: Build Godot project + working-directory: demo/Blackholio/client-godot + run: godot --headless --verbose --build-solutions --quit + + - name: Start SpacetimeDB + run: | + spacetime start & + disown + + - name: Publish godot-tests module to SpacetimeDB + working-directory: demo/Blackholio/server-rust + run: | + spacetime login --server-issued-login local + bash ./publish.sh + + - name: Run Godot tests + working-directory: demo/Blackholio/client-godot + run: godot --headless --scene res://tests/GodotPlayModeTests.tscn + + csharp-testsuite: + needs: [merge_queue_noop, lints] + if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} + runs-on: spacetimedb-new-runner-2 + timeout-minutes: 30 + env: + CARGO_TARGET_DIR: ${{ github.workspace }}/target + RUST_BACKTRACE: full + steps: + - name: Checkout repository + id: checkout-stdb + uses: actions/checkout@v4 + + - name: Setup dotnet + uses: actions/setup-dotnet@v3 + with: + global-json-file: global.json + + - name: Install .NET workloads + run: | + dotnet workload config --update-mode manifests + dotnet workload update --from-previous-sdk + # Explicitly install wasi-experimental for .NET 8 SDK (needed for test_build_csharp_module) + # Create temp global.json to target .NET 8 SDK for workload install + echo '{"sdk":{"version":"8.0.100","rollForward":"latestFeature"}}' > global.json + dotnet workload install wasi-experimental + rm global.json + + - name: Override NuGet packages + run: | + dotnet pack crates/bindings-csharp/BSATN.Runtime + dotnet pack crates/bindings-csharp/Runtime + + # Write out the nuget config file to `nuget.config`. This causes the spacetimedb-csharp-sdk repository + # to be aware of the local versions of the `bindings-csharp` packages in SpacetimeDB, and use them if + # available. Otherwise, `spacetimedb-csharp-sdk` will use the NuGet versions of the packages. + # This means that (if version numbers match) we will test the local versions of the C# packages, even + # if they're not pushed to NuGet. + # See https://learn.microsoft.com/en-us/nuget/reference/nuget-config-file for more info on the config file. + cd sdks/csharp + ./tools~/write-nuget-config.sh ../.. + + - name: Restore .NET solution + working-directory: sdks/csharp + run: dotnet restore --configfile NuGet.Config SpacetimeDB.ClientSDK.sln + + - name: Run .NET tests + working-directory: sdks/csharp + run: dotnet test -warnaserror --no-restore SpacetimeDB.ClientSDK.csproj + + - name: Verify C# formatting + working-directory: sdks/csharp + run: dotnet format --no-restore --verify-no-changes SpacetimeDB.ClientSDK.sln + + - name: Install Rust toolchain + uses: dsherret/rust-toolchain-file@v1 + - name: Set default rust toolchain + run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) + + - *set-native-cache-keys + - *restore-jemalloc + - *configure-cached-jemalloc + - *restore-zstd + - *configure-cached-zstd + - *restore-rusty-v8-debug + - *restore-rusty-v8 + - *restore-openssl + - *configure-cached-openssl + + - name: Install SpacetimeDB CLI from the local checkout + run: | + export CARGO_HOME="$HOME/.cargo" + echo "$CARGO_HOME/bin" >> "$GITHUB_PATH" + cargo install --force --path crates/cli --locked --message-format=short + cargo install --force --path crates/standalone --features allow_loopback_http_for_tests --locked --message-format=short + # Add a handy alias using the old binary name, so that we don't have to rewrite all scripts (incl. in submodules). + ln -sf $CARGO_HOME/bin/spacetimedb-cli $CARGO_HOME/bin/spacetime + + - name: Check quickstart-chat bindings are up to date + run: | + for dotnet_version in 8 10; do + bash sdks/csharp/tools~/gen-quickstart.sh "$dotnet_version" + done + tools/check-diff.sh templates/chat-console-cs/module_bindings || { + echo 'Error: quickstart-chat bindings have changed. Please run `sdks/csharp/tools~/gen-quickstart.sh 10`.' + exit 1 + } + + # TODO: Re-enable this once csharp is using the v2 ws api. + # - name: Check client-api bindings are up to date + # working-directory: sdks/csharp + # run: | + # bash tools~/gen-client-api.sh + # "${GITHUB_WORKSPACE}"/tools/check-diff.sh src/SpacetimeDB/ClientApi || { + # echo 'Error: Client API bindings are dirty. Please run `sdks/csharp/tools~/gen-client-api.sh`.' + # exit 1 + # } + + - name: Start SpacetimeDB + run: | + spacetime start & + disown + + - name: Run regression tests + run: | + bash sdks/csharp/tools~/run-regression-tests.sh + # Restore global.json symlinks (we replaced them with files to work around .NET 10 SDK bug) + # server is 5 levels deep from root, republishing dirs are 6 levels deep + if [ -f sdks/csharp/examples~/regression-tests/server/global.json ] && [ ! -L sdks/csharp/examples~/regression-tests/server/global.json ]; then + echo "Restoring symlink at server/global.json" + rm -f sdks/csharp/examples~/regression-tests/server/global.json + ln -s ../../../../../global.json sdks/csharp/examples~/regression-tests/server/global.json + fi + for dir in sdks/csharp/examples~/regression-tests/republishing/server-initial \ + sdks/csharp/examples~/regression-tests/republishing/server-republish; do + if [ -f "$dir/global.json" ] && [ ! -L "$dir/global.json" ]; then + echo "Restoring symlink at $dir/global.json" + rm -f "$dir/global.json" + ln -s ../../../../../../global.json "$dir/global.json" + fi + done + tools/check-diff.sh sdks/csharp/examples~/regression-tests || { + echo 'Error: Bindings are dirty. Please run `sdks/csharp/tools~/gen-regression-tests.sh`.' + exit 1 + } + + global_json_policy: + needs: [merge_queue_noop] + if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} + name: Verify global.json files are symlinks + runs-on: ubuntu-latest + permissions: + contents: read + env: + RUST_BACKTRACE: full + steps: + - name: Find Git ref + env: + PR_NUMBER: ${{ github.event.inputs.pr_number }} + run: | + if [ -n "$PR_NUMBER" ]; then + GIT_REF="refs/pull/$PR_NUMBER/merge" + else + GIT_REF="${{ github.ref }}" + fi + echo "GIT_REF=${GIT_REF}" >>"$GITHUB_ENV" + + - name: Checkout sources + uses: actions/checkout@v4 + with: + ref: ${{ env.GIT_REF }} + + - uses: dsherret/rust-toolchain-file@v1 + - name: Set default rust toolchain + run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) + + - name: Check global.json policy + run: cargo ci global-json-policy + + - name: Upload timing reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: cargo-timings-global-json-policy + path: ${{ github.workspace }}/target/cargo-timings/ + retention-days: 14 + + smoketests_mod_rs_complete: + needs: [merge_queue_noop] + if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} + name: Check smoketests/mod.rs is complete + runs-on: ubuntu-latest + permissions: + contents: read + env: + RUST_BACKTRACE: full + steps: + - name: Find Git ref + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + shell: bash + run: | + PR_NUMBER="${{ github.event.inputs.pr_number || null }}" + if test -n "${PR_NUMBER}"; then + GIT_REF="$( gh pr view --repo clockworklabs/SpacetimeDB $PR_NUMBER --json headRefName --jq .headRefName )" + else + GIT_REF="${{ github.ref }}" + fi + echo "GIT_REF=${GIT_REF}" >>"$GITHUB_ENV" + - name: Checkout sources + uses: actions/checkout@v4 + with: + ref: ${{ env.GIT_REF }} + - uses: dsherret/rust-toolchain-file@v1 + - name: Set default rust toolchain + run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) + + - name: Verify smoketest module lists and suite constraints + run: | + cargo run -p ci-smoketest-checks + + docs-build: + needs: [merge_queue_noop] + if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} + name: Docs build + runs-on: spacetimedb-new-runner-2 + env: + RUST_BACKTRACE: full + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: '22' + + - uses: ./.github/actions/setup-pnpm + with: + run_install: true + + - uses: dsherret/rust-toolchain-file@v1 + - name: Set default rust toolchain + run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) + + - name: Docusaurus build + run: cargo ci docs + + - name: Upload timing reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: cargo-timings-docs-build + path: ${{ github.workspace }}/target/cargo-timings/ + retention-days: 14 + + typescript-test: + needs: [merge_queue_noop] + if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} + name: TypeScript - Tests + runs-on: spacetimedb-new-runner-2 + env: + CARGO_TARGET_DIR: ${{ github.workspace }}/target + RUST_BACKTRACE: full + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: 22 + + - uses: ./.github/actions/setup-pnpm + with: + run_install: true + + # - name: Extract SpacetimeDB branch name from file + # id: extract-branch + # run: | + # # Define the path to the branch file + # BRANCH_FILE=".github/spacetimedb-branch.txt" + + # # Default to master if file doesn't exist + # if [ ! -f "$BRANCH_FILE" ]; then + # echo "::notice::No SpacetimeDB branch file found, using 'master'" + # echo "branch=master" >> $GITHUB_OUTPUT + # exit 0 + # fi + + # # Read and trim whitespace from the file + # branch=$(cat "$BRANCH_FILE" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//') + + # # Fallback to master if empty + # if [ -z "$branch" ]; then + # echo "::warning::SpacetimeDB branch file is empty, using 'master'" + # branch="master" + # fi + + # echo "branch=$branch" >> $GITHUB_OUTPUT + # echo "Using SpacetimeDB branch from file: $branch" + + - name: Install Rust toolchain + uses: dsherret/rust-toolchain-file@v1 + - name: Set default rust toolchain + run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) + + - *set-native-cache-keys + - *restore-jemalloc + - *configure-cached-jemalloc + - *restore-zstd + - *configure-cached-zstd + - *restore-rusty-v8-debug + - *restore-openssl + - *configure-cached-openssl + + # - name: Install SpacetimeDB CLI from the local checkout + # run: | + # export CARGO_HOME="$HOME/.cargo" + # echo "$CARGO_HOME/bin" >> "$GITHUB_PATH" + # cargo install --force --path crates/cli --locked --message-format=short + # cargo install --force --path crates/standalone --locked --message-format=short + # # Add a handy alias using the old binary name, so that we don't have to rewrite all scripts (incl. in submodules). + # ln -sf $CARGO_HOME/bin/spacetimedb-cli $CARGO_HOME/bin/spacetime + # # Clear any existing information + # spacetime server clear -y + + - name: Run TypeScript tests + run: cargo ci typescript-test + + - name: Upload timing reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: cargo-timings-typescript-test + path: ${{ github.workspace }}/target/cargo-timings/ + retention-days: 14 + + # - name: Run quickstart-chat tests + # working-directory: examples/quickstart-chat + # run: pnpm test + # + # # Run this step always, even if the previous steps fail + # - name: Print rows in the user table + # if: always() + # run: spacetime sql quickstart-chat "SELECT * FROM user" diff --git a/.github/workflows/internal-tests.yml b/.github/workflows/internal-tests.yml new file mode 100644 index 00000000000..e2301d3da96 --- /dev/null +++ b/.github/workflows/internal-tests.yml @@ -0,0 +1,93 @@ +# `SPACETIMEDB_PRIVATE_TOKEN` needs Actions read/write, Contents read, and Pull +# requests read access to clockworklabs/SpacetimeDBPrivate. +name: Internal Tests + +on: + pull_request: + push: + branches: + - master + merge_group: + workflow_dispatch: + +run-name: Internal Tests [ref=${{ github.ref }}] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + pull-requests: read + +jobs: + internal-tests: + name: Internal Tests + # Skip if not a PR or a push to master + # Skip if this is an external contribution. GitHub secrets will be empty, so the step would fail anyway. + if: ${{ (github.event_name == 'pull_request' || (github.event_name == 'push' && github.ref == 'refs/heads/master')) + && (github.event_name != 'pull_request' || !github.event.pull_request.head.repo.fork) }} + runs-on: ubuntu-latest + env: + TARGET_OWNER: clockworklabs + TARGET_REPO: SpacetimeDBPrivate + steps: + # Required for the path filter check below on non-PR commits (e.g. `master`) + - name: Checkout + uses: actions/checkout@v4 + + # Skip the private dispatch entirely when only `docs/` is touched. The job + # itself still completes successfully so required-status-check gating is + # satisfied without spending private-runner time on a docs-only change. + - name: Detect non-docs changes + id: filter + uses: dorny/paths-filter@v3 + with: + filters: | + non_docs: + - '!docs/**' + + - id: dispatch + name: Select or trigger tests + if: steps.filter.outputs.non_docs == 'true' + env: + CARGO_TARGET_DIR: ${{ runner.temp }}/internal-tests-cargo-target + GH_TOKEN: ${{ secrets.SPACETIMEDB_PRIVATE_TOKEN }} + PUBLIC_PR_NUMBER: ${{ github.event.pull_request.number }} + PUBLIC_SHA: ${{ github.event.pull_request.head.sha || github.sha }} + run: | + set -euo pipefail + args=(--public-sha "$PUBLIC_SHA") + if [[ -n "$PUBLIC_PR_NUMBER" ]]; then + args+=(--public-pr-number "$PUBLIC_PR_NUMBER") + fi + cargo run --quiet \ + --manifest-path tools/ci/Cargo.toml \ + -- other-workflows coordinate-internal-tests "${args[@]}" + + - name: Wait for Internal Tests to complete + if: steps.filter.outputs.non_docs == 'true' + env: + GH_TOKEN: ${{ secrets.SPACETIMEDB_PRIVATE_TOKEN }} + RUN_ID: ${{ steps.dispatch.outputs.run_id }} + run: | + set -euo pipefail + cargo ci other-workflows watch \ + --repo "$TARGET_OWNER/$TARGET_REPO" \ + --run-id "$RUN_ID" + + - name: Cancel invoked run if workflow cancelled + if: ${{ cancelled() && steps.dispatch.outputs.run_id && steps.dispatch.outputs.did_start == 'true' }} + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.SPACETIMEDB_PRIVATE_TOKEN }} + script: | + const targetOwner = process.env.TARGET_OWNER; + const targetRepo = process.env.TARGET_REPO; + const runId = Number(`${{ steps.dispatch.outputs.run_id }}`); + if (!runId) return; + await github.rest.actions.cancelWorkflowRun({ + owner: targetOwner, + repo: targetRepo, + run_id: runId, + }); From 1fd833ff140dd3593c1eb5c177e7a7efa27230c4 Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Tue, 25 Aug 2026 10:41:46 -0700 Subject: [PATCH 27/50] [bfops/test-runner]: remove some CI --- .github/workflows/ci.yml | 2 +- .github/workflows/internal-tests.yml | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fe9236c5fc9..a9458bb7868 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -160,7 +160,7 @@ jobs: upload-build-artifacts-windows: needs: [merge_queue_noop, lints] - if: true + if: false name: Upload build artifacts (Windows) runs-on: spacetimedb-windows-runner timeout-minutes: 15 diff --git a/.github/workflows/internal-tests.yml b/.github/workflows/internal-tests.yml index e2301d3da96..57198e22011 100644 --- a/.github/workflows/internal-tests.yml +++ b/.github/workflows/internal-tests.yml @@ -25,8 +25,7 @@ jobs: name: Internal Tests # Skip if not a PR or a push to master # Skip if this is an external contribution. GitHub secrets will be empty, so the step would fail anyway. - if: ${{ (github.event_name == 'pull_request' || (github.event_name == 'push' && github.ref == 'refs/heads/master')) - && (github.event_name != 'pull_request' || !github.event.pull_request.head.repo.fork) }} + if: false runs-on: ubuntu-latest env: TARGET_OWNER: clockworklabs From 011b07a2ce257919861400dfdd45b5ccb20c3504 Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Tue, 25 Aug 2026 10:53:27 -0700 Subject: [PATCH 28/50] [bfops/test-runner]: fixing other CI --- .github/workflows/ci.yml | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a9458bb7868..910bc293524 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -254,7 +254,7 @@ jobs: fail-fast: false matrix: partition: [1] - runs-on: spacetimedb-new-runner-2 + runs-on: spacetimedb-new-runner-2-staging timeout-minutes: 30 env: CARGO_TARGET_DIR: ${{ github.workspace }}/target @@ -380,7 +380,7 @@ jobs: if [ -f ~/emsdk/emsdk_env.sh ]; then source ~/emsdk/emsdk_env.sh fi - ./target/debug/ci-smoketests run-archive \ + cargo ci smoketests run-archive \ --archive-file smoketest-nextest.tar.zst \ -- \ --partition hash:${{ matrix.partition }}/${{ env.PARTITION_COUNT }} @@ -393,7 +393,7 @@ jobs: if (Test-Path "$env:USERPROFILE\emsdk\emsdk_env.ps1") { & "$env:USERPROFILE\emsdk\emsdk_env.ps1" | Out-Null } - .\target\debug\ci-smoketests.exe run-archive ` + cargo ci smoketests run-archive ` --archive-file smoketest-nextest.tar.zst ` -- ` --partition hash:${{ matrix.partition }}/${{ env.PARTITION_COUNT }} @@ -447,7 +447,7 @@ jobs: needs: [merge_queue_noop, lints] if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} name: Test Suite - runs-on: spacetimedb-new-runner-2 + runs-on: spacetimedb-new-runner-2-staging env: CARGO_TARGET_DIR: ${{ github.workspace }}/target @@ -612,7 +612,7 @@ jobs: needs: [merge_queue_noop] if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} name: Lints - runs-on: spacetimedb-new-runner-2 + runs-on: spacetimedb-new-runner-2-staging env: CARGO_TARGET_DIR: ${{ github.workspace }}/target RUST_BACKTRACE: full @@ -663,7 +663,7 @@ jobs: codeowners_check: if: ${{ github.event_name == 'pull_request' }} name: CODEOWNERS check - runs-on: spacetimedb-new-runner-2 + runs-on: spacetimedb-new-runner-2-staging permissions: contents: read pull-requests: read @@ -698,7 +698,7 @@ jobs: needs: [merge_queue_noop] if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} name: Build and test wasm bindings - runs-on: spacetimedb-new-runner-2 + runs-on: spacetimedb-new-runner-2-staging env: CARGO_TARGET_DIR: ${{ github.workspace }}/target RUST_BACKTRACE: full @@ -740,7 +740,7 @@ jobs: needs: [merge_queue_noop] if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} name: Check that packages are publishable - runs-on: spacetimedb-new-runner-2 + runs-on: spacetimedb-new-runner-2-staging permissions: read-all env: RUST_BACKTRACE: full @@ -826,7 +826,7 @@ jobs: name: Unreal Engine Tests # This can't go on e.g. ubuntu-latest because that runner runs out of disk space. ChatGPT suggested that the general solution tends to be to use # a custom runner. - runs-on: spacetimedb-new-runner-2 + runs-on: spacetimedb-new-runner-2-staging # Disable the tests because they are very flaky at the moment. # TODO: Remove this line and re-enable the `if` line just below here. if: false @@ -920,7 +920,7 @@ jobs: if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} name: Check CLI docs permissions: read-all - runs-on: spacetimedb-new-runner-2 + runs-on: spacetimedb-new-runner-2-staging env: CARGO_TARGET_DIR: ${{ github.workspace }}/target RUST_BACKTRACE: full @@ -1125,7 +1125,7 @@ jobs: if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} permissions: contents: read - runs-on: spacetimedb-new-runner-2 + runs-on: spacetimedb-new-runner-2-staging env: CARGO_TARGET_DIR: ${{ github.workspace }}/target UseLocalBsatnRuntime: true @@ -1237,7 +1237,7 @@ jobs: csharp-testsuite: needs: [merge_queue_noop, lints] if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} - runs-on: spacetimedb-new-runner-2 + runs-on: spacetimedb-new-runner-2-staging timeout-minutes: 30 env: CARGO_TARGET_DIR: ${{ github.workspace }}/target @@ -1432,14 +1432,13 @@ jobs: run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) - name: Verify smoketest module lists and suite constraints - run: | - cargo run -p ci-smoketest-checks + run: cargo ci smoketests check-mod-list docs-build: needs: [merge_queue_noop] if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} name: Docs build - runs-on: spacetimedb-new-runner-2 + runs-on: spacetimedb-new-runner-2-staging env: RUST_BACKTRACE: full steps: @@ -1474,7 +1473,7 @@ jobs: needs: [merge_queue_noop] if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} name: TypeScript - Tests - runs-on: spacetimedb-new-runner-2 + runs-on: spacetimedb-new-runner-2-staging env: CARGO_TARGET_DIR: ${{ github.workspace }}/target RUST_BACKTRACE: full From 9ecc27765c213f02a2074852dd82484084f27065 Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Tue, 25 Aug 2026 11:04:56 -0700 Subject: [PATCH 29/50] [bfops/test-runner]: apply same changes to other CI --- .github/workflows/ci.yml | 198 +++++++++++++++------------------------ 1 file changed, 77 insertions(+), 121 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 910bc293524..e1da824ace4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -84,7 +84,13 @@ jobs: - &set-cargo-target-dir name: Set Cargo target directory shell: bash - run: echo "CARGO_TARGET_DIR=${HOME}/actions-runner/_work/target" >>"${GITHUB_ENV}" + run: | + if [[ "${RUNNER_OS}" == "Linux" ]]; then + cargo_target_dir="${HOME}/actions-runner/_work/target" + else + cargo_target_dir="${GITHUB_WORKSPACE}/target" + fi + echo "CARGO_TARGET_DIR=${cargo_target_dir}" >>"${GITHUB_ENV}" - &find-git-ref name: Find Git ref @@ -257,16 +263,19 @@ jobs: runs-on: spacetimedb-new-runner-2-staging timeout-minutes: 30 env: - CARGO_TARGET_DIR: ${{ github.workspace }}/target RUST_BACKTRACE: full SPACETIMEDB_CPP_DIR: ${{ github.workspace }}/crates/bindings-cpp ARTIFACT_SUFFIX: linux PARTITION_COUNT: 1 steps: &smoketest-partition-steps + - *set-cargo-target-dir + - *find-git-ref - *checkout-sources + - *restore-source-mtimes + - uses: dsherret/rust-toolchain-file@v1 - *set-default-rust-toolchain @@ -450,9 +459,10 @@ jobs: runs-on: spacetimedb-new-runner-2-staging env: - CARGO_TARGET_DIR: ${{ github.workspace }}/target RUST_BACKTRACE: full steps: + - *set-cargo-target-dir + - name: Find Git ref env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -469,38 +479,13 @@ jobs: uses: actions/checkout@v4 with: ref: ${{ env.GIT_REF }} + fetch-depth: 0 + + - *restore-source-mtimes - uses: dsherret/rust-toolchain-file@v1 - name: Set default rust toolchain run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) - - *set-native-cache-keys - - &restore-jemalloc - name: Restore jemalloc - id: cache-jemalloc - if: runner.os == 'Linux' - uses: actions/cache/restore@v4 - with: *jemalloc-cache - - *configure-cached-jemalloc - - &restore-zstd - name: Restore Zstd - id: cache-zstd - if: runner.os == 'Linux' - uses: actions/cache/restore@v4 - with: *zstd-cache - - *configure-cached-zstd - - &restore-rusty-v8-debug - name: Restore rusty_v8 (debug) - uses: actions/cache/restore@v4 - with: &v8-debug-cache - path: ${{ env.CARGO_TARGET_DIR }}/debug/gn_out/obj - key: ${{ steps.native-cache-keys.outputs.v8-debug-key }} - - &restore-rusty-v8 - name: Restore rusty_v8 - uses: actions/cache/restore@v4 - with: *v8-release-cache - - *restore-openssl - - *configure-cached-openssl - - uses: actions/setup-dotnet@v3 with: global-json-file: global.json @@ -596,15 +581,6 @@ jobs: - name: Set default rust toolchain run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) - - *set-native-cache-keys - - *restore-jemalloc - - *configure-cached-jemalloc - - *restore-zstd - - *configure-cached-zstd - - *restore-rusty-v8 - - *restore-openssl - - *configure-cached-openssl - - name: Run index scan benchmark regression check run: cargo run --release -p spacetimedb-index-scan-gate @@ -614,28 +590,22 @@ jobs: name: Lints runs-on: spacetimedb-new-runner-2-staging env: - CARGO_TARGET_DIR: ${{ github.workspace }}/target RUST_BACKTRACE: full steps: + - *set-cargo-target-dir + - name: Checkout sources uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - *restore-source-mtimes - uses: dsherret/rust-toolchain-file@v1 - name: Set default rust toolchain run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) - run: echo ::add-matcher::.github/workflows/rust_matcher.json - - *set-native-cache-keys - - *restore-jemalloc - - *configure-cached-jemalloc - - *restore-zstd - - *configure-cached-zstd - - name: Cache rusty_v8 (debug) - uses: actions/cache@v4 - with: *v8-debug-cache - - *restore-openssl - - *configure-cached-openssl - - uses: actions/setup-dotnet@v3 with: global-json-file: global.json @@ -668,14 +638,17 @@ jobs: contents: read pull-requests: read env: - CARGO_TARGET_DIR: ${{ github.workspace }}/target RUST_BACKTRACE: full GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: + - *set-cargo-target-dir + - uses: actions/checkout@v4 with: fetch-depth: 0 + - *restore-source-mtimes + - uses: dsherret/rust-toolchain-file@v1 - name: Set default rust toolchain run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) @@ -700,24 +673,21 @@ jobs: name: Build and test wasm bindings runs-on: spacetimedb-new-runner-2-staging env: - CARGO_TARGET_DIR: ${{ github.workspace }}/target RUST_BACKTRACE: full steps: + - *set-cargo-target-dir + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - *restore-source-mtimes - uses: dsherret/rust-toolchain-file@v1 - name: Set default rust toolchain run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) - run: echo ::add-matcher::.github/workflows/rust_matcher.json - - *set-native-cache-keys - - *restore-jemalloc - - *configure-cached-jemalloc - - *restore-zstd - - *configure-cached-zstd - - *restore-openssl - - *configure-cached-openssl - - name: Set up Node.js uses: actions/setup-node@v4 with: @@ -745,7 +715,14 @@ jobs: env: RUST_BACKTRACE: full steps: + - *set-cargo-target-dir + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - *restore-source-mtimes + - uses: dsherret/rust-toolchain-file@v1 - name: Set default rust toolchain run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) @@ -757,7 +734,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: cargo-timings-publish-checks - path: ${{ github.workspace }}/target/cargo-timings/ + path: ${{ env.CARGO_TARGET_DIR }}/cargo-timings/ retention-days: 14 update: @@ -775,18 +752,17 @@ jobs: env: RUST_BACKTRACE: full steps: - - name: Checkout - uses: actions/checkout@v3 + - *set-cargo-target-dir + + - *find-git-ref + - *checkout-sources + - *restore-source-mtimes - name: Install Rust uses: dsherret/rust-toolchain-file@v1 - name: Set default rust toolchain run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) - - *set-native-cache-keys - - *restore-zstd - - *configure-cached-zstd - - name: Install rust target run: rustup target add ${{ matrix.target }} @@ -800,7 +776,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: cargo-timings-update-flow-${{ matrix.target }} - path: ${{ github.workspace }}/target/cargo-timings/ + path: ${{ env.CARGO_TARGET_DIR }}/cargo-timings/ retention-days: 14 # this is a no-op version of the above check with a trivially-passing body. @@ -922,9 +898,10 @@ jobs: permissions: read-all runs-on: spacetimedb-new-runner-2-staging env: - CARGO_TARGET_DIR: ${{ github.workspace }}/target RUST_BACKTRACE: full steps: + - *set-cargo-target-dir + - name: Find Git ref env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -942,6 +919,9 @@ jobs: uses: actions/checkout@v4 with: ref: ${{ env.GIT_REF }} + fetch-depth: 0 + + - *restore-source-mtimes - name: Set up Node.js uses: actions/setup-node@v4 @@ -956,14 +936,6 @@ jobs: - name: Set default rust toolchain run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) - - *set-native-cache-keys - - *restore-jemalloc - - *configure-cached-jemalloc - - *restore-zstd - - *configure-cached-zstd - - *restore-openssl - - *configure-cached-openssl - - name: Check for docs change run: | cargo ci cli-docs @@ -1042,15 +1014,6 @@ jobs: - name: Set default rust toolchain run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) - - *set-native-cache-keys - - *restore-jemalloc - - *configure-cached-jemalloc - - *restore-zstd - - *configure-cached-zstd - - *restore-rusty-v8 - - *restore-openssl - - *configure-cached-openssl - - name: Install SpacetimeDB CLI from the local checkout run: | export CARGO_HOME="$HOME/.cargo" @@ -1127,12 +1090,17 @@ jobs: contents: read runs-on: spacetimedb-new-runner-2-staging env: - CARGO_TARGET_DIR: ${{ github.workspace }}/target UseLocalBsatnRuntime: true steps: + - *set-cargo-target-dir + - name: Checkout repository id: checkout-stdb uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - *restore-source-mtimes - name: Setup dotnet uses: actions/setup-dotnet@v3 @@ -1169,15 +1137,6 @@ jobs: - name: Set default rust toolchain run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) - - *set-native-cache-keys - - *restore-jemalloc - - *configure-cached-jemalloc - - *restore-zstd - - *configure-cached-zstd - - *restore-rusty-v8 - - *restore-openssl - - *configure-cached-openssl - - name: Install SpacetimeDB CLI from the local checkout run: | export CARGO_HOME="$HOME/.cargo" @@ -1240,12 +1199,17 @@ jobs: runs-on: spacetimedb-new-runner-2-staging timeout-minutes: 30 env: - CARGO_TARGET_DIR: ${{ github.workspace }}/target RUST_BACKTRACE: full steps: + - *set-cargo-target-dir + - name: Checkout repository id: checkout-stdb uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - *restore-source-mtimes - name: Setup dotnet uses: actions/setup-dotnet@v3 @@ -1293,16 +1257,6 @@ jobs: - name: Set default rust toolchain run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) - - *set-native-cache-keys - - *restore-jemalloc - - *configure-cached-jemalloc - - *restore-zstd - - *configure-cached-zstd - - *restore-rusty-v8-debug - - *restore-rusty-v8 - - *restore-openssl - - *configure-cached-openssl - - name: Install SpacetimeDB CLI from the local checkout run: | export CARGO_HOME="$HOME/.cargo" @@ -1442,8 +1396,14 @@ jobs: env: RUST_BACKTRACE: full steps: + - *set-cargo-target-dir + - name: Checkout repository uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - *restore-source-mtimes - name: Set up Node.js uses: actions/setup-node@v3 @@ -1466,7 +1426,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: cargo-timings-docs-build - path: ${{ github.workspace }}/target/cargo-timings/ + path: ${{ env.CARGO_TARGET_DIR }}/cargo-timings/ retention-days: 14 typescript-test: @@ -1475,11 +1435,16 @@ jobs: name: TypeScript - Tests runs-on: spacetimedb-new-runner-2-staging env: - CARGO_TARGET_DIR: ${{ github.workspace }}/target RUST_BACKTRACE: full steps: + - *set-cargo-target-dir + - name: Checkout repository uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - *restore-source-mtimes - name: Set up Node.js uses: actions/setup-node@v4 @@ -1520,15 +1485,6 @@ jobs: - name: Set default rust toolchain run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) - - *set-native-cache-keys - - *restore-jemalloc - - *configure-cached-jemalloc - - *restore-zstd - - *configure-cached-zstd - - *restore-rusty-v8-debug - - *restore-openssl - - *configure-cached-openssl - # - name: Install SpacetimeDB CLI from the local checkout # run: | # export CARGO_HOME="$HOME/.cargo" @@ -1548,7 +1504,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: cargo-timings-typescript-test - path: ${{ github.workspace }}/target/cargo-timings/ + path: ${{ env.CARGO_TARGET_DIR }}/cargo-timings/ retention-days: 14 # - name: Run quickstart-chat tests From de9d45d9deb42ed24de9917829b1236d1bd7a36b Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Tue, 25 Aug 2026 11:07:14 -0700 Subject: [PATCH 30/50] [bfops/test-runner]: -vv --- tools/ci/commands/test/src/main.rs | 2 ++ tools/ci/commands/update-flow/src/main.rs | 4 ++-- tools/ci/commands/wasm-bindings/src/main.rs | 2 +- tools/ci/src/main.rs | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/tools/ci/commands/test/src/main.rs b/tools/ci/commands/test/src/main.rs index 373a30ef49a..2b5e08299a7 100644 --- a/tools/ci/commands/test/src/main.rs +++ b/tools/ci/commands/test/src/main.rs @@ -56,6 +56,7 @@ fn main() -> Result<()> { cmd!( "cargo", "build", + "-vv", "--release", "-p", "spacetimedb-cli", @@ -113,6 +114,7 @@ fn main() -> Result<()> { cmd!( "cargo", "run", + "-vv", "-p", "spacetimedb-codegen", "--example", diff --git a/tools/ci/commands/update-flow/src/main.rs b/tools/ci/commands/update-flow/src/main.rs index 273e5f26efc..d861b3ce20f 100644 --- a/tools/ci/commands/update-flow/src/main.rs +++ b/tools/ci/commands/update-flow/src/main.rs @@ -40,7 +40,7 @@ fn main() -> Result<()> { cmd( "cargo", - ["build", "-p", "spacetimedb-update"] + ["build", "-vv", "-p", "spacetimedb-update"] .into_iter() .chain(common_args.clone()), ) @@ -53,7 +53,7 @@ fn main() -> Result<()> { let root_arg = format!("--root-dir={}", root_dir_string); cmd( "cargo", - ["run", "-p", "spacetimedb-update"] + ["run", "-vv", "-p", "spacetimedb-update"] .into_iter() .chain(common_args.clone()) .chain(["--", "self-install", &root_arg, "--yes"].into_iter()), diff --git a/tools/ci/commands/wasm-bindings/src/main.rs b/tools/ci/commands/wasm-bindings/src/main.rs index aa1946d11ac..53f4ee6ea4d 100644 --- a/tools/ci/commands/wasm-bindings/src/main.rs +++ b/tools/ci/commands/wasm-bindings/src/main.rs @@ -24,7 +24,7 @@ fn main() -> Result<()> { pnpm(["build"]).dir("crates/bindings-typescript").run()?; cmd!("cargo", "test", "-p", "spacetimedb-codegen").run()?; // Pre-build the CLI so that it _doesn't_ get `cargo update`d, since that may break the build. - cmd!("cargo", "build", "-p", "spacetimedb-cli").run()?; + cmd!("cargo", "build", "-vv", "-p", "spacetimedb-cli").run()?; // Make sure the `Cargo.lock` file reflects the latest available versions. // This is what users would end up with on a fresh module, so we want to // catch any compile errors arising from a different transitive closure diff --git a/tools/ci/src/main.rs b/tools/ci/src/main.rs index bb0878277d9..9870e2f6e97 100644 --- a/tools/ci/src/main.rs +++ b/tools/ci/src/main.rs @@ -112,7 +112,7 @@ fn is_skipped(command: &Command, skips: &[String]) -> bool { } fn run_package(package: &str, args: &[String]) -> Result<()> { - let mut cargo_args = vec!["run", "--timings", "--package", package, "--"]; + let mut cargo_args = vec!["run", "-vv", "--timings", "--package", package, "--"]; cargo_args.extend(args.iter().map(String::as_str)); cmd("cargo", cargo_args).run()?; Ok(()) From cd9a0295adb6966709335aeb63d9eef395d3b25e Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Tue, 25 Aug 2026 11:08:22 -0700 Subject: [PATCH 31/50] [bfops/test-runner]: fix --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e1da824ace4..f85f4f021da 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -119,6 +119,7 @@ jobs: # avoid invalidating otherwise reusable artifacts in the prebuilt target cache. - &restore-source-mtimes name: Restore source mtimes from git history + if: runner.os == 'Linux' shell: bash run: git restore-mtime --quiet From a458a30925f440bbb7b185a2b3d69a200e432d90 Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Tue, 25 Aug 2026 11:10:15 -0700 Subject: [PATCH 32/50] [bfops/test-runner]: switch runner --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f85f4f021da..388b10c9af1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1319,7 +1319,7 @@ jobs: needs: [merge_queue_noop] if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} name: Verify global.json files are symlinks - runs-on: ubuntu-latest + runs-on: spacetimedb-new-runner-2-staging permissions: contents: read env: From 0f2f377a3ea41f272354b764557866e1e6c5577a Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Tue, 25 Aug 2026 11:16:45 -0700 Subject: [PATCH 33/50] [bfops/test-runner]: -vv --- .cargo/config.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index 7b7b2eb4e1f..faf5acbd091 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -3,7 +3,7 @@ rustflags = ["--cfg", "tokio_unstable"] [alias] llm = "run --package xtask-llm-benchmark --bin llm_benchmark --" -ci = "run -p ci --" +ci = "run -vv -p ci --" regen = "run -p regen --" smoketest = "ci smoketests --" smoketests = "smoketest" From 06d18ceb81bf2951e0c516860f25f33876d2b61f Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Tue, 25 Aug 2026 11:16:50 -0700 Subject: [PATCH 34/50] [bfops/test-runner]: switch runner --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 388b10c9af1..a8ec4733000 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1360,7 +1360,7 @@ jobs: needs: [merge_queue_noop] if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} name: Check smoketests/mod.rs is complete - runs-on: ubuntu-latest + runs-on: spacetimedb-new-runner-2-staging permissions: contents: read env: From 2667a17ebd12cfc48e30a073b869b5e1577d934b Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Tue, 25 Aug 2026 11:17:31 -0700 Subject: [PATCH 35/50] [bfops/test-runner]: don't run benchmark --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a8ec4733000..73f84f8c2d5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -550,7 +550,7 @@ jobs: index_scan_bench: needs: [merge_queue_noop, lints] - if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} + if: false name: Index Scan Bench runs-on: spacetimedb-benchmark-runner concurrency: From 43eedb1b1ede877c1c3c2e545763ae229dee5834 Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Tue, 25 Aug 2026 11:18:19 -0700 Subject: [PATCH 36/50] [bfops/test-runner]: skip unity runner --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 73f84f8c2d5..ab44fd3f31b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -953,7 +953,7 @@ jobs: needs: [merge_queue_noop, lints] # Skip if this is an external contribution. # The license secrets will be empty, so the step would fail anyway. - if: ${{ needs.merge_queue_noop.outputs.skip != 'true' && (github.event_name != 'pull_request' || !github.event.pull_request.head.repo.fork) }} + if: false permissions: contents: read checks: write From 721e3981947cc31ad5056259574e00146af3e31d Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Tue, 25 Aug 2026 11:19:41 -0700 Subject: [PATCH 37/50] [bfops/test-runner]: -vv --- crates/bindings-typescript/test-app/package.json | 2 +- crates/bindings-typescript/test-react-router-app/package.json | 2 +- crates/bindings-typescript/test-solid-router/package.json | 2 +- templates/angular-ts/package.json | 2 +- templates/astro-ts/package.json | 2 +- templates/chat-react-ts/package.json | 2 +- templates/hangman-react-ts/package.json | 2 +- templates/money-exchange-react-ts/package.json | 2 +- templates/nextjs-ts/package.json | 2 +- templates/nuxt-ts/package.json | 2 +- templates/react-ts/package.json | 2 +- templates/remix-ts/package.json | 2 +- templates/solid-ts/package.json | 2 +- templates/svelte-ts/package.json | 2 +- templates/vue-ts/package.json | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) diff --git a/crates/bindings-typescript/test-app/package.json b/crates/bindings-typescript/test-app/package.json index 8ba058dad9d..7c431dd7a54 100644 --- a/crates/bindings-typescript/test-app/package.json +++ b/crates/bindings-typescript/test-app/package.json @@ -12,7 +12,7 @@ "format": "prettier . --write --ignore-path ../../../.prettierignore", "lint": "eslint . && prettier . --check --ignore-path ../../../.prettierignore", "preview": "vite preview", - "generate": "cargo run -p gen-bindings -- --replacement ../../../src/index && prettier --write src/module_bindings", + "generate": "cargo run -vv -p gen-bindings -- --replacement ../../../src/index && prettier --write src/module_bindings", "spacetime:generate": "spacetime generate --lang typescript --out-dir src/module_bindings --project-path server", "spacetime:start": "spacetime start", "spacetime:publish:local": "spacetime publish game --project-path server --server local", diff --git a/crates/bindings-typescript/test-react-router-app/package.json b/crates/bindings-typescript/test-react-router-app/package.json index db0f2d504d2..4b165faa9c2 100644 --- a/crates/bindings-typescript/test-react-router-app/package.json +++ b/crates/bindings-typescript/test-react-router-app/package.json @@ -12,7 +12,7 @@ "format": "prettier . --write --ignore-path ../../../.prettierignore", "lint": "eslint . && prettier . --check --ignore-path ../../../.prettierignore", "preview": "vite preview", - "generate": "cargo run -p gen-bindings -- --replacement ../../../src/index && prettier --write src/module_bindings", + "generate": "cargo run -vv -p gen-bindings -- --replacement ../../../src/index && prettier --write src/module_bindings", "spacetime:generate": "spacetime generate --lang typescript --out-dir src/module_bindings --module-path server", "spacetime:start": "spacetime start", "spacetime:publish:local": "spacetime publish game --module-path server --server local", diff --git a/crates/bindings-typescript/test-solid-router/package.json b/crates/bindings-typescript/test-solid-router/package.json index f5dc7bb5842..01a0af04b3a 100644 --- a/crates/bindings-typescript/test-solid-router/package.json +++ b/crates/bindings-typescript/test-solid-router/package.json @@ -9,7 +9,7 @@ "dev": "vite", "build": "vite build", "serve": "vite preview", - "generate": "cargo run -p gen-bindings -- --replacement ../../../src/index && prettier --write src/module_bindings", + "generate": "cargo run -vv -p gen-bindings -- --replacement ../../../src/index && prettier --write src/module_bindings", "spacetime:generate": "spacetime generate --lang typescript --out-dir src/module_bindings --module-path server", "spacetime:start": "spacetime start", "spacetime:publish:local": "spacetime publish game --module-path server --server local", diff --git a/templates/angular-ts/package.json b/templates/angular-ts/package.json index b0cd069cf89..ccda26c5120 100644 --- a/templates/angular-ts/package.json +++ b/templates/angular-ts/package.json @@ -6,7 +6,7 @@ "scripts": { "dev": "node scripts/dev.mjs", "build": "ng build", - "generate": "cargo run -p gen-bindings -- --out-dir src/module_bindings --module-path spacetimedb && prettier --write src/module_bindings", + "generate": "cargo run -vv -p gen-bindings -- --out-dir src/module_bindings --module-path spacetimedb && prettier --write src/module_bindings", "spacetime:generate": "spacetime generate --lang typescript --out-dir src/module_bindings --module-path spacetimedb", "spacetime:publish:local": "spacetime publish --module-path spacetimedb --server local", "spacetime:publish": "spacetime publish --module-path spacetimedb --server maincloud" diff --git a/templates/astro-ts/package.json b/templates/astro-ts/package.json index 1e194115bb8..0888e22265a 100644 --- a/templates/astro-ts/package.json +++ b/templates/astro-ts/package.json @@ -9,7 +9,7 @@ "preview": "astro preview", "start": "node ./dist/server/entry.mjs", "astro": "astro", - "generate": "pnpm --dir spacetimedb install && cargo run -p gen-bindings -- --out-dir src/module_bindings --module-path spacetimedb && prettier --write src/module_bindings", + "generate": "pnpm --dir spacetimedb install && cargo run -vv -p gen-bindings -- --out-dir src/module_bindings --module-path spacetimedb && prettier --write src/module_bindings", "spacetime:generate": "spacetime generate --lang typescript --out-dir src/module_bindings --module-path spacetimedb", "spacetime:publish:local": "spacetime publish --module-path spacetimedb --server local", "spacetime:publish": "spacetime publish --module-path spacetimedb --server maincloud" diff --git a/templates/chat-react-ts/package.json b/templates/chat-react-ts/package.json index a5a081caed2..b4177a49475 100644 --- a/templates/chat-react-ts/package.json +++ b/templates/chat-react-ts/package.json @@ -10,7 +10,7 @@ "lint": "eslint . && prettier . --check --ignore-path ../../.prettierignore", "preview": "vite preview", "test": "vitest run", - "generate": "cargo run -p gen-bindings -- --out-dir src/module_bindings --module-path spacetimedb && prettier --write src/module_bindings", + "generate": "cargo run -vv -p gen-bindings -- --out-dir src/module_bindings --module-path spacetimedb && prettier --write src/module_bindings", "spacetime:generate": "spacetime generate --lang typescript --out-dir src/module_bindings --module-path spacetimedb", "spacetime:publish:local": "spacetime publish --module-path server --server local", "spacetime:publish": "spacetime publish --module-path server --server maincloud" diff --git a/templates/hangman-react-ts/package.json b/templates/hangman-react-ts/package.json index 4076ae402cf..ccb5f1c5ad0 100644 --- a/templates/hangman-react-ts/package.json +++ b/templates/hangman-react-ts/package.json @@ -9,7 +9,7 @@ "format": "prettier . --write --ignore-path ../../.prettierignore", "lint": "eslint . && prettier . --check --ignore-path ../../.prettierignore", "preview": "vite preview", - "generate": "cargo run -p gen-bindings -- --out-dir src/module_bindings --module-path spacetimedb && prettier --write src/module_bindings", + "generate": "cargo run -vv -p gen-bindings -- --out-dir src/module_bindings --module-path spacetimedb && prettier --write src/module_bindings", "spacetime:generate": "spacetime generate --lang typescript --out-dir src/module_bindings --module-path spacetimedb", "spacetime:publish:local": "spacetime publish --module-path spacetimedb --server local", "spacetime:publish": "spacetime publish --module-path spacetimedb --server maincloud" diff --git a/templates/money-exchange-react-ts/package.json b/templates/money-exchange-react-ts/package.json index c42682d1744..86e199644b9 100644 --- a/templates/money-exchange-react-ts/package.json +++ b/templates/money-exchange-react-ts/package.json @@ -10,7 +10,7 @@ "lint": "eslint . && prettier . --check --ignore-path ../../.prettierignore", "preview": "vite preview", "test": "vitest run", - "generate": "cargo run -p gen-bindings -- --out-dir src/module_bindings --module-path spacetimedb && prettier --write src/module_bindings", + "generate": "cargo run -vv -p gen-bindings -- --out-dir src/module_bindings --module-path spacetimedb && prettier --write src/module_bindings", "spacetime:generate": "spacetime generate --lang typescript --out-dir src/module_bindings --module-path spacetimedb", "spacetime:publish:local": "spacetime publish --module-path spacetimedb --server local", "spacetime:publish": "spacetime publish --module-path spacetimedb --server maincloud" diff --git a/templates/nextjs-ts/package.json b/templates/nextjs-ts/package.json index 9ec40873f49..92ee1799d47 100644 --- a/templates/nextjs-ts/package.json +++ b/templates/nextjs-ts/package.json @@ -8,7 +8,7 @@ "build": "next build", "start": "next start", "lint": "next lint", - "generate": "pnpm --dir spacetimedb install && cargo run -p gen-bindings -- --out-dir src/module_bindings --module-path spacetimedb && prettier --write src/module_bindings", + "generate": "pnpm --dir spacetimedb install && cargo run -vv -p gen-bindings -- --out-dir src/module_bindings --module-path spacetimedb && prettier --write src/module_bindings", "spacetime:generate": "spacetime generate --lang typescript --out-dir src/module_bindings --module-path spacetimedb", "spacetime:publish:local": "spacetime publish --module-path spacetimedb --server local", "spacetime:publish": "spacetime publish --module-path spacetimedb --server maincloud" diff --git a/templates/nuxt-ts/package.json b/templates/nuxt-ts/package.json index 5c220f3bcc8..6034481ec97 100644 --- a/templates/nuxt-ts/package.json +++ b/templates/nuxt-ts/package.json @@ -7,7 +7,7 @@ "dev": "nuxt dev", "build": "nuxt build", "preview": "nuxt preview", - "generate": "pnpm --dir spacetimedb install && cargo run -p gen-bindings -- --out-dir module_bindings --module-path spacetimedb && prettier --write module_bindings", + "generate": "pnpm --dir spacetimedb install && cargo run -vv -p gen-bindings -- --out-dir module_bindings --module-path spacetimedb && prettier --write module_bindings", "spacetime:generate": "spacetime generate --lang typescript --out-dir module_bindings --module-path spacetimedb", "spacetime:publish:local": "spacetime publish --module-path spacetimedb --server local", "spacetime:publish": "spacetime publish --module-path spacetimedb --server maincloud" diff --git a/templates/react-ts/package.json b/templates/react-ts/package.json index 00765c9e27a..b847cda21ac 100644 --- a/templates/react-ts/package.json +++ b/templates/react-ts/package.json @@ -7,7 +7,7 @@ "dev": "vite", "build": "tsc -b && vite build", "preview": "vite preview", - "generate": "cargo run -p gen-bindings -- --out-dir src/module_bindings --module-path spacetimedb && prettier --write src/module_bindings", + "generate": "cargo run -vv -p gen-bindings -- --out-dir src/module_bindings --module-path spacetimedb && prettier --write src/module_bindings", "spacetime:generate": "spacetime generate --lang typescript --out-dir src/module_bindings --module-path spacetimedb", "spacetime:publish:local": "spacetime publish --module-path server --server local", "spacetime:publish": "spacetime publish --module-path server --server maincloud" diff --git a/templates/remix-ts/package.json b/templates/remix-ts/package.json index 155dd879d04..4d9f0ee1f0d 100644 --- a/templates/remix-ts/package.json +++ b/templates/remix-ts/package.json @@ -7,7 +7,7 @@ "dev": "npx remix vite:dev", "build": "npx remix vite:build", "start": "npx remix-serve ./build/server/index.js", - "generate": "pnpm --dir spacetimedb install && cargo run -p gen-bindings -- --out-dir src/module_bindings --module-path spacetimedb && prettier --write src/module_bindings", + "generate": "pnpm --dir spacetimedb install && cargo run -vv -p gen-bindings -- --out-dir src/module_bindings --module-path spacetimedb && prettier --write src/module_bindings", "spacetime:generate": "spacetime generate --lang typescript --out-dir src/module_bindings --module-path spacetimedb", "spacetime:publish:local": "spacetime publish --module-path spacetimedb --server local", "spacetime:publish": "spacetime publish --module-path spacetimedb --server maincloud" diff --git a/templates/solid-ts/package.json b/templates/solid-ts/package.json index ed5cf238373..973486cce1c 100644 --- a/templates/solid-ts/package.json +++ b/templates/solid-ts/package.json @@ -7,7 +7,7 @@ "dev": "vite", "build": "vite build", "preview": "vite preview", - "generate": "pnpm --dir spacetimedb install && cargo run -p gen-bindings -- --out-dir src/module_bindings --module-path spacetimedb && prettier --write src/module_bindings", + "generate": "pnpm --dir spacetimedb install && cargo run -vv -p gen-bindings -- --out-dir src/module_bindings --module-path spacetimedb && prettier --write src/module_bindings", "spacetime:generate": "spacetime generate --lang typescript --out-dir src/module_bindings --module-path spacetimedb", "spacetime:publish:local": "spacetime publish --module-path spacetimedb --server local", "spacetime:publish": "spacetime publish --module-path spacetimedb --server maincloud" diff --git a/templates/svelte-ts/package.json b/templates/svelte-ts/package.json index fb909102b0e..9e0a32f9b07 100644 --- a/templates/svelte-ts/package.json +++ b/templates/svelte-ts/package.json @@ -7,7 +7,7 @@ "dev": "vite", "build": "vite build", "preview": "vite preview", - "generate": "pnpm --dir spacetimedb install && cargo run -p gen-bindings -- --out-dir src/module_bindings --module-path spacetimedb && prettier --write src/module_bindings", + "generate": "pnpm --dir spacetimedb install && cargo run -vv -p gen-bindings -- --out-dir src/module_bindings --module-path spacetimedb && prettier --write src/module_bindings", "spacetime:generate": "spacetime generate --lang typescript --out-dir src/module_bindings --module-path spacetimedb", "spacetime:publish:local": "spacetime publish --module-path spacetimedb --server local", "spacetime:publish": "spacetime publish --module-path spacetimedb --server maincloud" diff --git a/templates/vue-ts/package.json b/templates/vue-ts/package.json index 8a41c1f0ef3..5621895c30b 100644 --- a/templates/vue-ts/package.json +++ b/templates/vue-ts/package.json @@ -7,7 +7,7 @@ "dev": "vite", "build": "vue-tsc -b && vite build", "preview": "vite preview", - "generate": "pnpm --dir spacetimedb install && cargo run -p gen-bindings -- --out-dir src/module_bindings --module-path spacetimedb && prettier --write src/module_bindings", + "generate": "pnpm --dir spacetimedb install && cargo run -vv -p gen-bindings -- --out-dir src/module_bindings --module-path spacetimedb && prettier --write src/module_bindings", "spacetime:generate": "spacetime generate --lang typescript --out-dir src/module_bindings --module-path spacetimedb", "spacetime:publish:local": "spacetime publish --module-path spacetimedb --server local", "spacetime:publish": "spacetime publish --module-path spacetimedb --server maincloud" From 429b8159c23dc0d6a5c5406ce22635e27f33c53e Mon Sep 17 00:00:00 2001 From: joshua-spacetime Date: Sun, 23 Aug 2026 14:23:04 -0700 Subject: [PATCH 38/50] Remove cli and standalone builds from most CI jobs Download shared artifacts instead. --- .github/workflows/ci.yml | 78 ++++++++++------------ sdks/csharp/tools~/gen-quickstart.sh | 6 +- sdks/csharp/tools~/gen-regression-tests.sh | 10 +-- sdks/csharp/tools~/run-regression-tests.sh | 18 ++--- sdks/csharp/tools~/spacetime-command.sh | 11 +++ tools/ci/commands/test/src/main.rs | 63 ++++++++++++----- 6 files changed, 116 insertions(+), 70 deletions(-) create mode 100644 sdks/csharp/tools~/spacetime-command.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b56dd41aa0c..60575d93c82 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -314,7 +314,6 @@ jobs: SMOKETEST_SUITE: standalone steps: &smoketest-build-steps - *find-git-ref - - *checkout-sources - uses: dsherret/rust-toolchain-file@v1 @@ -400,7 +399,6 @@ jobs: PARTITION_COUNT: 1 steps: &smoketest-partition-steps - *find-git-ref - - *checkout-sources - uses: dsherret/rust-toolchain-file@v1 @@ -472,13 +470,15 @@ jobs: - name: Install cargo-nextest uses: taiki-e/install-action@nextest - - name: Download build artifacts + - &download-build-artifacts + name: Download build artifacts uses: actions/download-artifact@v4 with: name: build-artifacts-${{ env.ARTIFACT_SUFFIX }} path: build-artifacts - - name: Extract build artifacts + - &extract-build-artifacts + name: Extract build artifacts shell: bash run: | tar -xzf build-artifacts/build-support.tar.gz @@ -570,7 +570,7 @@ jobs: run: echo "Merge queue commit has the same tree as the PR head; smoketest already ran for the PR." test: - needs: [merge_queue_noop, lints] + needs: [merge_queue_noop, lints, upload-build-artifacts-linux] if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} name: Test Suite runs-on: spacetimedb-new-runner-2 @@ -578,6 +578,7 @@ jobs: env: CARGO_TARGET_DIR: ${{ github.workspace }}/target RUST_BACKTRACE: full + ARTIFACT_SUFFIX: linux steps: - name: Find Git ref env: @@ -627,6 +628,9 @@ jobs: - *restore-openssl - *configure-cached-openssl + - *download-build-artifacts + - *extract-build-artifacts + - uses: actions/setup-dotnet@v3 with: global-json-file: global.json @@ -678,7 +682,7 @@ jobs: - name: Run tests run: | source ~/emsdk/emsdk_env.sh - cargo ci test + cargo ci test --prebuilt-runtime - name: Upload timing reports if: always() @@ -1103,7 +1107,7 @@ jobs: retention-days: 14 unity-testsuite: - needs: [merge_queue_noop, lints] + needs: [merge_queue_noop, lints, upload-build-artifacts-linux] # Skip if this is an external contribution. # The license secrets will be empty, so the step would fail anyway. if: ${{ needs.merge_queue_noop.outputs.skip != 'true' && (github.event_name != 'pull_request' || !github.event.pull_request.head.repo.fork) }} @@ -1115,11 +1119,11 @@ jobs: env: CARGO_TARGET_DIR: ${{ github.workspace }}/target RUST_BACKTRACE: full + ARTIFACT_SUFFIX: linux UNITY_VERSION: 2022.3.32f1 steps: - - name: Checkout repository - id: checkout-stdb - uses: actions/checkout@v4 + - *find-git-ref + - *checkout-sources # Keep this before generation/hydration so ignored build outputs do not affect hashFiles. - name: Restore Unity Library @@ -1177,14 +1181,15 @@ jobs: - *restore-openssl - *configure-cached-openssl - - name: Install SpacetimeDB CLI from the local checkout + - *download-build-artifacts + - *extract-build-artifacts + + - &expose-spacetime-cli + name: Expose SpacetimeDB CLI on PATH + shell: bash run: | - export CARGO_HOME="$HOME/.cargo" - echo "$CARGO_HOME/bin" >> "$GITHUB_PATH" - cargo install --force --path crates/cli --locked --message-format=short - cargo install --force --path crates/standalone --locked --message-format=short - # Add a handy alias using the old binary name, so that we don't have to rewrite all scripts (incl. in submodules). - ln -sf $CARGO_HOME/bin/spacetimedb-cli $CARGO_HOME/bin/spacetime + ln -sf spacetimedb-cli target/release/spacetime + echo "$GITHUB_WORKSPACE/target/release" >> "$GITHUB_PATH" - name: Generate client bindings working-directory: demo/Blackholio/server-rust @@ -1247,18 +1252,18 @@ jobs: key: ${{ steps.restore-unity-library.outputs.cache-primary-key }} godot-testsuite: - needs: [merge_queue_noop, lints] + needs: [merge_queue_noop, lints, upload-build-artifacts-linux] if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} permissions: contents: read runs-on: spacetimedb-new-runner-2 env: CARGO_TARGET_DIR: ${{ github.workspace }}/target + ARTIFACT_SUFFIX: linux UseLocalBsatnRuntime: true steps: - - name: Checkout repository - id: checkout-stdb - uses: actions/checkout@v4 + - *find-git-ref + - *checkout-sources - name: Setup dotnet uses: actions/setup-dotnet@v3 @@ -1304,14 +1309,9 @@ jobs: - *restore-openssl - *configure-cached-openssl - - name: Install SpacetimeDB CLI from the local checkout - run: | - export CARGO_HOME="$HOME/.cargo" - echo "$CARGO_HOME/bin" >> "$GITHUB_PATH" - cargo install --force --path crates/cli --locked --message-format=short - cargo install --force --path crates/standalone --locked --message-format=short - # Add a handy alias using the old binary name, so that we don't have to rewrite all scripts (incl. in submodules). - ln -sf $CARGO_HOME/bin/spacetimedb-cli $CARGO_HOME/bin/spacetime + - *download-build-artifacts + - *extract-build-artifacts + - *expose-spacetime-cli - name: Generate client bindings working-directory: demo/Blackholio/server-rust @@ -1361,17 +1361,18 @@ jobs: run: godot --headless --scene res://tests/GodotPlayModeTests.tscn csharp-testsuite: - needs: [merge_queue_noop, lints] + needs: [merge_queue_noop, lints, upload-build-artifacts-linux] if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} runs-on: spacetimedb-new-runner-2 timeout-minutes: 30 env: CARGO_TARGET_DIR: ${{ github.workspace }}/target RUST_BACKTRACE: full + ARTIFACT_SUFFIX: linux + SPACETIME_BIN: ${{ github.workspace }}/target/release/spacetimedb-cli steps: - - name: Checkout repository - id: checkout-stdb - uses: actions/checkout@v4 + - *find-git-ref + - *checkout-sources - name: Setup dotnet uses: actions/setup-dotnet@v3 @@ -1429,14 +1430,9 @@ jobs: - *restore-openssl - *configure-cached-openssl - - name: Install SpacetimeDB CLI from the local checkout - run: | - export CARGO_HOME="$HOME/.cargo" - echo "$CARGO_HOME/bin" >> "$GITHUB_PATH" - cargo install --force --path crates/cli --locked --message-format=short - cargo install --force --path crates/standalone --features allow_loopback_http_for_tests --locked --message-format=short - # Add a handy alias using the old binary name, so that we don't have to rewrite all scripts (incl. in submodules). - ln -sf $CARGO_HOME/bin/spacetimedb-cli $CARGO_HOME/bin/spacetime + - *download-build-artifacts + - *extract-build-artifacts + - *expose-spacetime-cli - name: Check quickstart-chat bindings are up to date run: | diff --git a/sdks/csharp/tools~/gen-quickstart.sh b/sdks/csharp/tools~/gen-quickstart.sh index e683271bf53..10743c3f3ee 100755 --- a/sdks/csharp/tools~/gen-quickstart.sh +++ b/sdks/csharp/tools~/gen-quickstart.sh @@ -7,6 +7,8 @@ SDK_PATH="$(realpath "$SDK_PATH")" STDB_PATH="$SDK_PATH/../.." DOTNET_VERSION="${1:-}" +source "$SDK_PATH/tools~/spacetime-command.sh" + GLOBAL_JSON_BACKUPS=() backup_global_json_once() { @@ -66,5 +68,5 @@ if [ -n "$DOTNET_VERSION" ]; then BUILD_OPTIONS+=("--build-options=--dotnet-version $DOTNET_VERSION") fi -cargo build --manifest-path "$STDB_PATH/crates/standalone/Cargo.toml" -cargo run --manifest-path "$STDB_PATH/crates/cli/Cargo.toml" -- generate -y -l csharp -o "$STDB_PATH/templates/chat-console-cs/module_bindings" --module-path "$STDB_PATH/templates/chat-console-cs/spacetimedb" "${BUILD_OPTIONS[@]}" +prepare_spacetime "$STDB_PATH" +"${SPACETIME[@]}" generate -y -l csharp -o "$STDB_PATH/templates/chat-console-cs/module_bindings" --module-path "$STDB_PATH/templates/chat-console-cs/spacetimedb" "${BUILD_OPTIONS[@]}" diff --git a/sdks/csharp/tools~/gen-regression-tests.sh b/sdks/csharp/tools~/gen-regression-tests.sh index 54852ff03fb..3a8c7ee8299 100755 --- a/sdks/csharp/tools~/gen-regression-tests.sh +++ b/sdks/csharp/tools~/gen-regression-tests.sh @@ -7,6 +7,8 @@ SDK_PATH="$(realpath "$SDK_PATH")" STDB_PATH="$SDK_PATH/../.." DOTNET_VERSION="${1:-}" +source "$SDK_PATH/tools~/spacetime-command.sh" + GLOBAL_JSON_BACKUPS=() expected_global_json_symlink_target() { @@ -81,7 +83,7 @@ if [ -n "$DOTNET_VERSION" ]; then BUILD_OPTIONS+=("--build-options=--dotnet-version $DOTNET_VERSION") fi -cargo build --manifest-path "$STDB_PATH/crates/standalone/Cargo.toml" -cargo run --manifest-path "$STDB_PATH/crates/cli/Cargo.toml" -- generate -y -l csharp -o "$SDK_PATH/examples~/regression-tests/client/module_bindings" --module-path "$SDK_PATH/examples~/regression-tests/server" "${BUILD_OPTIONS[@]}" -cargo run --manifest-path "$STDB_PATH/crates/cli/Cargo.toml" -- generate -y -l csharp -o "$SDK_PATH/examples~/regression-tests/republishing/client/module_bindings" --module-path "$SDK_PATH/examples~/regression-tests/republishing/server-republish" "${BUILD_OPTIONS[@]}" -cargo run --manifest-path "$STDB_PATH/crates/cli/Cargo.toml" -- generate -y -l csharp -o "$SDK_PATH/examples~/regression-tests/procedure-client/module_bindings" --module-path "$STDB_PATH/modules/sdk-test-procedure" "${BUILD_OPTIONS[@]}" +prepare_spacetime "$STDB_PATH" +"${SPACETIME[@]}" generate -y -l csharp -o "$SDK_PATH/examples~/regression-tests/client/module_bindings" --module-path "$SDK_PATH/examples~/regression-tests/server" "${BUILD_OPTIONS[@]}" +"${SPACETIME[@]}" generate -y -l csharp -o "$SDK_PATH/examples~/regression-tests/republishing/client/module_bindings" --module-path "$SDK_PATH/examples~/regression-tests/republishing/server-republish" "${BUILD_OPTIONS[@]}" +"${SPACETIME[@]}" generate -y -l csharp -o "$SDK_PATH/examples~/regression-tests/procedure-client/module_bindings" --module-path "$STDB_PATH/modules/sdk-test-procedure" "${BUILD_OPTIONS[@]}" diff --git a/sdks/csharp/tools~/run-regression-tests.sh b/sdks/csharp/tools~/run-regression-tests.sh index fb3aca90f4d..c55865dbd32 100644 --- a/sdks/csharp/tools~/run-regression-tests.sh +++ b/sdks/csharp/tools~/run-regression-tests.sh @@ -9,6 +9,8 @@ SDK_PATH="$(realpath "$SDK_PATH")" STDB_PATH="$SDK_PATH/../.." SPACETIMEDB_SERVER_URL="${SPACETIMEDB_SERVER_URL:-local}" +source "$SDK_PATH/tools~/spacetime-command.sh" + DOTNET_VERSIONS=("$@") if [ ${#DOTNET_VERSIONS[@]} -eq 0 ]; then DOTNET_VERSIONS=(8 10) @@ -99,8 +101,8 @@ run_client() { trap restore_global_jsons EXIT -# Build and run SpacetimeDB server -cargo build --manifest-path "$STDB_PATH/crates/standalone/Cargo.toml" +# Ensure the CLI and standalone used by the regression tests are available. +prepare_spacetime "$STDB_PATH" for dotnet_version in "${DOTNET_VERSIONS[@]}"; do echo "Running C# regression tests with .NET $dotnet_version" @@ -111,13 +113,13 @@ for dotnet_version in "${DOTNET_VERSIONS[@]}"; do "$SDK_PATH/tools~/gen-regression-tests.sh" "$dotnet_version" # Publish module for btree test - cargo run --manifest-path "$STDB_PATH/crates/cli/Cargo.toml" -- publish --dotnet-version "$dotnet_version" -c -y --server "$SPACETIMEDB_SERVER_URL" -p "$SDK_PATH/examples~/regression-tests/server" btree-repro + "${SPACETIME[@]}" publish --dotnet-version "$dotnet_version" -c -y --server "$SPACETIMEDB_SERVER_URL" -p "$SDK_PATH/examples~/regression-tests/server" btree-repro # Publish module for republishing module test - cargo run --manifest-path "$STDB_PATH/crates/cli/Cargo.toml" -- publish --dotnet-version "$dotnet_version" -c -y --server "$SPACETIMEDB_SERVER_URL" -p "$SDK_PATH/examples~/regression-tests/republishing/server-initial" republish-test - cargo run --manifest-path "$STDB_PATH/crates/cli/Cargo.toml" call --server "$SPACETIMEDB_SERVER_URL" republish-test insert 1 - cargo run --manifest-path "$STDB_PATH/crates/cli/Cargo.toml" -- publish --dotnet-version "$dotnet_version" --server "$SPACETIMEDB_SERVER_URL" -p "$SDK_PATH/examples~/regression-tests/republishing/server-republish" --break-clients republish-test - cargo run --manifest-path "$STDB_PATH/crates/cli/Cargo.toml" call --server "$SPACETIMEDB_SERVER_URL" republish-test insert 2 + "${SPACETIME[@]}" publish --dotnet-version "$dotnet_version" -c -y --server "$SPACETIMEDB_SERVER_URL" -p "$SDK_PATH/examples~/regression-tests/republishing/server-initial" republish-test + "${SPACETIME[@]}" call --server "$SPACETIMEDB_SERVER_URL" republish-test insert 1 + "${SPACETIME[@]}" publish --dotnet-version "$dotnet_version" --server "$SPACETIMEDB_SERVER_URL" -p "$SDK_PATH/examples~/regression-tests/republishing/server-republish" --break-clients republish-test + "${SPACETIME[@]}" call --server "$SPACETIMEDB_SERVER_URL" republish-test insert 2 echo "Cleanup obj~ folders generated in $SDK_PATH/examples~/regression-tests/procedure-client" # There is a bug in the code generator that creates obj~ folders in the output directory using a Rust project. @@ -125,7 +127,7 @@ for dotnet_version in "${DOTNET_VERSIONS[@]}"; do rm -rf "$SDK_PATH/examples~/regression-tests/procedure-client/module_bindings"/*/obj~ # Publish module for procedure tests - cargo run --manifest-path "$STDB_PATH/crates/cli/Cargo.toml" -- publish --dotnet-version "$dotnet_version" -c -y --server "$SPACETIMEDB_SERVER_URL" -p "$STDB_PATH/modules/sdk-test-procedure" procedure-tests + "${SPACETIME[@]}" publish --dotnet-version "$dotnet_version" -c -y --server "$SPACETIMEDB_SERVER_URL" -p "$STDB_PATH/modules/sdk-test-procedure" procedure-tests # Run clients against the modules published with this .NET version. run_client "$SDK_PATH/examples~/regression-tests/client" "$dotnet_version" diff --git a/sdks/csharp/tools~/spacetime-command.sh b/sdks/csharp/tools~/spacetime-command.sh new file mode 100644 index 00000000000..1cbc6949f90 --- /dev/null +++ b/sdks/csharp/tools~/spacetime-command.sh @@ -0,0 +1,11 @@ +# CI provides a prebuilt CLI; direct local invocations keep using Cargo. +prepare_spacetime() { + local stdb_path="$1" + + if [[ -n "${SPACETIME_BIN:-}" ]]; then + SPACETIME=("$SPACETIME_BIN") + else + cargo build --manifest-path "$stdb_path/crates/standalone/Cargo.toml" + SPACETIME=(cargo run --manifest-path "$stdb_path/crates/cli/Cargo.toml" --) + fi +} diff --git a/tools/ci/commands/test/src/main.rs b/tools/ci/commands/test/src/main.rs index 373a30ef49a..3b759cc2ec1 100644 --- a/tools/ci/commands/test/src/main.rs +++ b/tools/ci/commands/test/src/main.rs @@ -1,8 +1,9 @@ #![allow(clippy::disallowed_macros)] -use anyhow::Result; +use anyhow::{ensure, Result}; use ci_common::pnpm; use clap::Parser; use duct::cmd; +use std::{env, path::PathBuf}; /// Runs tests /// @@ -10,10 +11,40 @@ use duct::cmd; /// This does not include Unreal tests. /// This expects to run in a clean git state. #[derive(Parser)] -struct Cli {} +struct Cli { + /// Use release CLI and standalone binaries already present in the Cargo target directory. + #[arg(long)] + prebuilt_runtime: bool, +} + +fn runtime_binary_path(binary_name: &str) -> PathBuf { + let target_dir = env::var_os("CARGO_TARGET_DIR") + .map(PathBuf::from) + .unwrap_or_else(|| ci_common::repo_root().join("target")); + target_dir + .join("release") + .join(binary_name) + .with_extension(env::consts::EXE_EXTENSION) +} + +fn verify_prebuilt_runtime() -> Result<()> { + for binary_name in ["spacetimedb-cli", "spacetimedb-standalone"] { + let binary_path = runtime_binary_path(binary_name); + ensure!( + binary_path.is_file(), + "--prebuilt-runtime requires {binary_name} at {}", + binary_path.display() + ); + } + Ok(()) +} fn main() -> Result<()> { - Cli::parse(); + let cli = Cli::parse(); + + if cli.prebuilt_runtime { + verify_prebuilt_runtime()?; + } pnpm(["build"]).dir("crates/bindings-typescript").run()?; @@ -53,18 +84,20 @@ fn main() -> Result<()> { .run()?; // The SDK test harness uses the same child-process server guard as smoketests, // which expects release CLI/standalone binaries to already exist. - cmd!( - "cargo", - "build", - "--release", - "-p", - "spacetimedb-cli", - "-p", - "spacetimedb-standalone", - "--features", - "spacetimedb-standalone/allow_loopback_http_for_tests", - ) - .run()?; + if !cli.prebuilt_runtime { + cmd!( + "cargo", + "build", + "--release", + "-p", + "spacetimedb-cli", + "-p", + "spacetimedb-standalone", + "--features", + "spacetimedb-standalone/allow_loopback_http_for_tests", + ) + .run()?; + } // SDK procedure tests intentionally make localhost HTTP requests. cmd!( "cargo", From 1e3ab0b3437a4ac60c8c66db422b96faa87fbd49 Mon Sep 17 00:00:00 2001 From: joshua-spacetime Date: Tue, 25 Aug 2026 11:33:24 -0700 Subject: [PATCH 39/50] Pull out cli and standalone from typescript tests --- .github/workflows/ci.yml | 46 ++--------- Cargo.lock | 8 ++ Cargo.toml | 1 + modules/benchmarks-ts/package.json | 6 +- modules/module-test-ts/package.json | 6 +- .../sdk-test-case-conversion-ts/package.json | 6 +- .../package.json | 6 +- .../package.json | 6 +- modules/sdk-test-procedure-ts/package.json | 6 +- modules/sdk-test-ts/package.json | 6 +- modules/sdk-test-view-pk-ts/package.json | 6 +- sdks/csharp/tools~/gen-quickstart.sh | 5 +- sdks/csharp/tools~/gen-regression-tests.sh | 9 +-- sdks/csharp/tools~/run-regression-tests.sh | 17 ++-- sdks/csharp/tools~/spacetime-command.sh | 11 --- .../chat-react-ts/spacetimedb/package.json | 6 +- tools/ci/commands/run-spacetime/Cargo.toml | 11 +++ tools/ci/commands/run-spacetime/src/main.rs | 78 +++++++++++++++++++ tools/ci/commands/test/src/main.rs | 27 +------ tools/ci/commands/typescript-test/src/main.rs | 63 +++++++++++---- tools/ci/common/src/lib.rs | 33 +++++++- tools/ci/src/main.rs | 13 ++++ tools/gen-bindings/src/main.rs | 19 ++--- 23 files changed, 246 insertions(+), 149 deletions(-) delete mode 100644 sdks/csharp/tools~/spacetime-command.sh create mode 100644 tools/ci/commands/run-spacetime/Cargo.toml create mode 100644 tools/ci/commands/run-spacetime/src/main.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 60575d93c82..ba9420b20ce 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1593,16 +1593,17 @@ jobs: retention-days: 14 typescript-test: - needs: [merge_queue_noop] + needs: [merge_queue_noop, upload-build-artifacts-linux] if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} name: TypeScript - Tests runs-on: spacetimedb-new-runner-2 env: CARGO_TARGET_DIR: ${{ github.workspace }}/target RUST_BACKTRACE: full + ARTIFACT_SUFFIX: linux steps: - - name: Checkout repository - uses: actions/checkout@v4 + - *find-git-ref + - *checkout-sources - name: Set up Node.js uses: actions/setup-node@v4 @@ -1613,31 +1614,6 @@ jobs: with: run_install: true - # - name: Extract SpacetimeDB branch name from file - # id: extract-branch - # run: | - # # Define the path to the branch file - # BRANCH_FILE=".github/spacetimedb-branch.txt" - - # # Default to master if file doesn't exist - # if [ ! -f "$BRANCH_FILE" ]; then - # echo "::notice::No SpacetimeDB branch file found, using 'master'" - # echo "branch=master" >> $GITHUB_OUTPUT - # exit 0 - # fi - - # # Read and trim whitespace from the file - # branch=$(cat "$BRANCH_FILE" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//') - - # # Fallback to master if empty - # if [ -z "$branch" ]; then - # echo "::warning::SpacetimeDB branch file is empty, using 'master'" - # branch="master" - # fi - - # echo "branch=$branch" >> $GITHUB_OUTPUT - # echo "Using SpacetimeDB branch from file: $branch" - - name: Install Rust toolchain uses: dsherret/rust-toolchain-file@v1 - name: Set default rust toolchain @@ -1652,19 +1628,11 @@ jobs: - *restore-openssl - *configure-cached-openssl - # - name: Install SpacetimeDB CLI from the local checkout - # run: | - # export CARGO_HOME="$HOME/.cargo" - # echo "$CARGO_HOME/bin" >> "$GITHUB_PATH" - # cargo install --force --path crates/cli --locked --message-format=short - # cargo install --force --path crates/standalone --locked --message-format=short - # # Add a handy alias using the old binary name, so that we don't have to rewrite all scripts (incl. in submodules). - # ln -sf $CARGO_HOME/bin/spacetimedb-cli $CARGO_HOME/bin/spacetime - # # Clear any existing information - # spacetime server clear -y + - *download-build-artifacts + - *extract-build-artifacts - name: Run TypeScript tests - run: cargo ci typescript-test + run: cargo ci typescript-test --prebuilt-runtime - name: Upload timing reports if: always() diff --git a/Cargo.lock b/Cargo.lock index 22cd022fb09..fc5253adb9f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -970,6 +970,14 @@ dependencies = [ "duct", ] +[[package]] +name = "ci-run-spacetime" +version = "0.1.0" +dependencies = [ + "anyhow", + "duct", +] + [[package]] name = "ci-smoketest-checks" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 44858f71b9c..18d5c5a324e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -78,6 +78,7 @@ members = [ "tools/ci/commands/cli-docs", "tools/ci/commands/global-json-policy", "tools/ci/commands/publish-checks", + "tools/ci/commands/run-spacetime", "tools/ci/commands/typescript-test", "tools/ci/commands/version-upgrade-check", "tools/ci/commands/docs", diff --git a/modules/benchmarks-ts/package.json b/modules/benchmarks-ts/package.json index 27c251622dc..839846845c8 100644 --- a/modules/benchmarks-ts/package.json +++ b/modules/benchmarks-ts/package.json @@ -4,9 +4,9 @@ "description": "", "main": "index.js", "scripts": { - "build": "cargo build -p spacetimedb-standalone && cargo run -p spacetimedb-cli -- build", - "generate-ts": "cargo build -p spacetimedb-standalone && cargo run -p spacetimedb-cli -- generate --lang typescript --out-dir ts-codegen", - "publish": "cargo run -p spacetimedb-cli -- publish" + "build": "cargo ci run-spacetime build", + "generate-ts": "cargo ci run-spacetime generate --lang typescript --out-dir ts-codegen", + "publish": "cargo ci run-spacetime publish" }, "keywords": [], "author": "", diff --git a/modules/module-test-ts/package.json b/modules/module-test-ts/package.json index 4e964319a75..f961418a3a8 100644 --- a/modules/module-test-ts/package.json +++ b/modules/module-test-ts/package.json @@ -3,9 +3,9 @@ "license": "ISC", "type": "module", "scripts": { - "build": "cargo build -p spacetimedb-standalone && cargo run -p spacetimedb-cli -- build", - "generate-ts": "cargo build -p spacetimedb-standalone && cargo run -p spacetimedb-cli -- generate --lang typescript --out-dir ts-codegen", - "publish": "cargo run -p spacetimedb-cli -- publish" + "build": "cargo ci run-spacetime build", + "generate-ts": "cargo ci run-spacetime generate --lang typescript --out-dir ts-codegen", + "publish": "cargo ci run-spacetime publish" }, "dependencies": { "spacetimedb": "workspace:^" diff --git a/modules/sdk-test-case-conversion-ts/package.json b/modules/sdk-test-case-conversion-ts/package.json index 326c97ec7fc..58872ce2cdc 100644 --- a/modules/sdk-test-case-conversion-ts/package.json +++ b/modules/sdk-test-case-conversion-ts/package.json @@ -4,9 +4,9 @@ "description": "", "main": "index.js", "scripts": { - "build": "cargo build -p spacetimedb-standalone && cargo run -p spacetimedb-cli -- build", - "generate-ts": "cargo build -p spacetimedb-standalone && cargo run -p spacetimedb-cli -- generate --lang typescript --out-dir ts-codegen", - "publish": "cargo run -p spacetimedb-cli -- publish" + "build": "cargo ci run-spacetime build", + "generate-ts": "cargo ci run-spacetime generate --lang typescript --out-dir ts-codegen", + "publish": "cargo ci run-spacetime publish" }, "keywords": [], "author": "", diff --git a/modules/sdk-test-connect-disconnect-ts/package.json b/modules/sdk-test-connect-disconnect-ts/package.json index cd7b60b0e47..604fefb5c63 100644 --- a/modules/sdk-test-connect-disconnect-ts/package.json +++ b/modules/sdk-test-connect-disconnect-ts/package.json @@ -4,9 +4,9 @@ "description": "", "main": "index.js", "scripts": { - "build": "cargo build -p spacetimedb-standalone && cargo run -p spacetimedb-cli -- build", - "generate-ts": "cargo build -p spacetimedb-standalone && cargo run -p spacetimedb-cli -- generate --lang typescript --out-dir ts-codegen", - "publish": "cargo run -p spacetimedb-cli -- publish" + "build": "cargo ci run-spacetime build", + "generate-ts": "cargo ci run-spacetime generate --lang typescript --out-dir ts-codegen", + "publish": "cargo ci run-spacetime publish" }, "keywords": [], "author": "", diff --git a/modules/sdk-test-procedural-view-pk-ts/package.json b/modules/sdk-test-procedural-view-pk-ts/package.json index ed3cefd9de5..fe8bfe1e4bf 100644 --- a/modules/sdk-test-procedural-view-pk-ts/package.json +++ b/modules/sdk-test-procedural-view-pk-ts/package.json @@ -4,9 +4,9 @@ "license": "ISC", "type": "module", "scripts": { - "build": "cargo build -p spacetimedb-standalone && cargo run -p spacetimedb-cli -- build", - "generate-ts": "cargo build -p spacetimedb-standalone && cargo run -p spacetimedb-cli -- generate --lang typescript --out-dir ts-codegen", - "publish": "cargo run -p spacetimedb-cli -- publish" + "build": "cargo ci run-spacetime build", + "generate-ts": "cargo ci run-spacetime generate --lang typescript --out-dir ts-codegen", + "publish": "cargo ci run-spacetime publish" }, "dependencies": { "spacetimedb": "workspace:^" diff --git a/modules/sdk-test-procedure-ts/package.json b/modules/sdk-test-procedure-ts/package.json index c8b4bc4ba89..42f060786c0 100644 --- a/modules/sdk-test-procedure-ts/package.json +++ b/modules/sdk-test-procedure-ts/package.json @@ -3,9 +3,9 @@ "license": "ISC", "type": "module", "scripts": { - "build": "cargo build -p spacetimedb-standalone && cargo run -p spacetimedb-cli -- build", - "generate-ts": "cargo build -p spacetimedb-standalone && cargo run -p spacetimedb-cli -- generate --lang typescript --out-dir ts-codegen", - "publish": "cargo run -p spacetimedb-cli -- publish" + "build": "cargo ci run-spacetime build", + "generate-ts": "cargo ci run-spacetime generate --lang typescript --out-dir ts-codegen", + "publish": "cargo ci run-spacetime publish" }, "dependencies": { "spacetimedb": "workspace:^" diff --git a/modules/sdk-test-ts/package.json b/modules/sdk-test-ts/package.json index 4e964319a75..f961418a3a8 100644 --- a/modules/sdk-test-ts/package.json +++ b/modules/sdk-test-ts/package.json @@ -3,9 +3,9 @@ "license": "ISC", "type": "module", "scripts": { - "build": "cargo build -p spacetimedb-standalone && cargo run -p spacetimedb-cli -- build", - "generate-ts": "cargo build -p spacetimedb-standalone && cargo run -p spacetimedb-cli -- generate --lang typescript --out-dir ts-codegen", - "publish": "cargo run -p spacetimedb-cli -- publish" + "build": "cargo ci run-spacetime build", + "generate-ts": "cargo ci run-spacetime generate --lang typescript --out-dir ts-codegen", + "publish": "cargo ci run-spacetime publish" }, "dependencies": { "spacetimedb": "workspace:^" diff --git a/modules/sdk-test-view-pk-ts/package.json b/modules/sdk-test-view-pk-ts/package.json index a03509611e5..51b91759342 100644 --- a/modules/sdk-test-view-pk-ts/package.json +++ b/modules/sdk-test-view-pk-ts/package.json @@ -4,9 +4,9 @@ "license": "ISC", "type": "module", "scripts": { - "build": "cargo build -p spacetimedb-standalone && cargo run -p spacetimedb-cli -- build", - "generate-ts": "cargo build -p spacetimedb-standalone && cargo run -p spacetimedb-cli -- generate --lang typescript --out-dir ts-codegen", - "publish": "cargo run -p spacetimedb-cli -- publish" + "build": "cargo ci run-spacetime build", + "generate-ts": "cargo ci run-spacetime generate --lang typescript --out-dir ts-codegen", + "publish": "cargo ci run-spacetime publish" }, "dependencies": { "spacetimedb": "workspace:^" diff --git a/sdks/csharp/tools~/gen-quickstart.sh b/sdks/csharp/tools~/gen-quickstart.sh index 10743c3f3ee..4c2a3c05fa7 100755 --- a/sdks/csharp/tools~/gen-quickstart.sh +++ b/sdks/csharp/tools~/gen-quickstart.sh @@ -7,7 +7,7 @@ SDK_PATH="$(realpath "$SDK_PATH")" STDB_PATH="$SDK_PATH/../.." DOTNET_VERSION="${1:-}" -source "$SDK_PATH/tools~/spacetime-command.sh" +cd "$STDB_PATH" GLOBAL_JSON_BACKUPS=() @@ -68,5 +68,4 @@ if [ -n "$DOTNET_VERSION" ]; then BUILD_OPTIONS+=("--build-options=--dotnet-version $DOTNET_VERSION") fi -prepare_spacetime "$STDB_PATH" -"${SPACETIME[@]}" generate -y -l csharp -o "$STDB_PATH/templates/chat-console-cs/module_bindings" --module-path "$STDB_PATH/templates/chat-console-cs/spacetimedb" "${BUILD_OPTIONS[@]}" +cargo ci run-spacetime generate -y -l csharp -o "$STDB_PATH/templates/chat-console-cs/module_bindings" --module-path "$STDB_PATH/templates/chat-console-cs/spacetimedb" "${BUILD_OPTIONS[@]}" diff --git a/sdks/csharp/tools~/gen-regression-tests.sh b/sdks/csharp/tools~/gen-regression-tests.sh index 3a8c7ee8299..b0c4e7f4ad3 100755 --- a/sdks/csharp/tools~/gen-regression-tests.sh +++ b/sdks/csharp/tools~/gen-regression-tests.sh @@ -7,7 +7,7 @@ SDK_PATH="$(realpath "$SDK_PATH")" STDB_PATH="$SDK_PATH/../.." DOTNET_VERSION="${1:-}" -source "$SDK_PATH/tools~/spacetime-command.sh" +cd "$STDB_PATH" GLOBAL_JSON_BACKUPS=() @@ -83,7 +83,6 @@ if [ -n "$DOTNET_VERSION" ]; then BUILD_OPTIONS+=("--build-options=--dotnet-version $DOTNET_VERSION") fi -prepare_spacetime "$STDB_PATH" -"${SPACETIME[@]}" generate -y -l csharp -o "$SDK_PATH/examples~/regression-tests/client/module_bindings" --module-path "$SDK_PATH/examples~/regression-tests/server" "${BUILD_OPTIONS[@]}" -"${SPACETIME[@]}" generate -y -l csharp -o "$SDK_PATH/examples~/regression-tests/republishing/client/module_bindings" --module-path "$SDK_PATH/examples~/regression-tests/republishing/server-republish" "${BUILD_OPTIONS[@]}" -"${SPACETIME[@]}" generate -y -l csharp -o "$SDK_PATH/examples~/regression-tests/procedure-client/module_bindings" --module-path "$STDB_PATH/modules/sdk-test-procedure" "${BUILD_OPTIONS[@]}" +cargo ci run-spacetime generate -y -l csharp -o "$SDK_PATH/examples~/regression-tests/client/module_bindings" --module-path "$SDK_PATH/examples~/regression-tests/server" "${BUILD_OPTIONS[@]}" +cargo ci run-spacetime generate -y -l csharp -o "$SDK_PATH/examples~/regression-tests/republishing/client/module_bindings" --module-path "$SDK_PATH/examples~/regression-tests/republishing/server-republish" "${BUILD_OPTIONS[@]}" +cargo ci run-spacetime generate -y -l csharp -o "$SDK_PATH/examples~/regression-tests/procedure-client/module_bindings" --module-path "$STDB_PATH/modules/sdk-test-procedure" "${BUILD_OPTIONS[@]}" diff --git a/sdks/csharp/tools~/run-regression-tests.sh b/sdks/csharp/tools~/run-regression-tests.sh index c55865dbd32..ea5cb58a779 100644 --- a/sdks/csharp/tools~/run-regression-tests.sh +++ b/sdks/csharp/tools~/run-regression-tests.sh @@ -9,7 +9,7 @@ SDK_PATH="$(realpath "$SDK_PATH")" STDB_PATH="$SDK_PATH/../.." SPACETIMEDB_SERVER_URL="${SPACETIMEDB_SERVER_URL:-local}" -source "$SDK_PATH/tools~/spacetime-command.sh" +cd "$STDB_PATH" DOTNET_VERSIONS=("$@") if [ ${#DOTNET_VERSIONS[@]} -eq 0 ]; then @@ -101,9 +101,6 @@ run_client() { trap restore_global_jsons EXIT -# Ensure the CLI and standalone used by the regression tests are available. -prepare_spacetime "$STDB_PATH" - for dotnet_version in "${DOTNET_VERSIONS[@]}"; do echo "Running C# regression tests with .NET $dotnet_version" @@ -113,13 +110,13 @@ for dotnet_version in "${DOTNET_VERSIONS[@]}"; do "$SDK_PATH/tools~/gen-regression-tests.sh" "$dotnet_version" # Publish module for btree test - "${SPACETIME[@]}" publish --dotnet-version "$dotnet_version" -c -y --server "$SPACETIMEDB_SERVER_URL" -p "$SDK_PATH/examples~/regression-tests/server" btree-repro + cargo ci run-spacetime publish --dotnet-version "$dotnet_version" -c -y --server "$SPACETIMEDB_SERVER_URL" -p "$SDK_PATH/examples~/regression-tests/server" btree-repro # Publish module for republishing module test - "${SPACETIME[@]}" publish --dotnet-version "$dotnet_version" -c -y --server "$SPACETIMEDB_SERVER_URL" -p "$SDK_PATH/examples~/regression-tests/republishing/server-initial" republish-test - "${SPACETIME[@]}" call --server "$SPACETIMEDB_SERVER_URL" republish-test insert 1 - "${SPACETIME[@]}" publish --dotnet-version "$dotnet_version" --server "$SPACETIMEDB_SERVER_URL" -p "$SDK_PATH/examples~/regression-tests/republishing/server-republish" --break-clients republish-test - "${SPACETIME[@]}" call --server "$SPACETIMEDB_SERVER_URL" republish-test insert 2 + cargo ci run-spacetime publish --dotnet-version "$dotnet_version" -c -y --server "$SPACETIMEDB_SERVER_URL" -p "$SDK_PATH/examples~/regression-tests/republishing/server-initial" republish-test + cargo ci run-spacetime call --server "$SPACETIMEDB_SERVER_URL" republish-test insert 1 + cargo ci run-spacetime publish --dotnet-version "$dotnet_version" --server "$SPACETIMEDB_SERVER_URL" -p "$SDK_PATH/examples~/regression-tests/republishing/server-republish" --break-clients republish-test + cargo ci run-spacetime call --server "$SPACETIMEDB_SERVER_URL" republish-test insert 2 echo "Cleanup obj~ folders generated in $SDK_PATH/examples~/regression-tests/procedure-client" # There is a bug in the code generator that creates obj~ folders in the output directory using a Rust project. @@ -127,7 +124,7 @@ for dotnet_version in "${DOTNET_VERSIONS[@]}"; do rm -rf "$SDK_PATH/examples~/regression-tests/procedure-client/module_bindings"/*/obj~ # Publish module for procedure tests - "${SPACETIME[@]}" publish --dotnet-version "$dotnet_version" -c -y --server "$SPACETIMEDB_SERVER_URL" -p "$STDB_PATH/modules/sdk-test-procedure" procedure-tests + cargo ci run-spacetime publish --dotnet-version "$dotnet_version" -c -y --server "$SPACETIMEDB_SERVER_URL" -p "$STDB_PATH/modules/sdk-test-procedure" procedure-tests # Run clients against the modules published with this .NET version. run_client "$SDK_PATH/examples~/regression-tests/client" "$dotnet_version" diff --git a/sdks/csharp/tools~/spacetime-command.sh b/sdks/csharp/tools~/spacetime-command.sh deleted file mode 100644 index 1cbc6949f90..00000000000 --- a/sdks/csharp/tools~/spacetime-command.sh +++ /dev/null @@ -1,11 +0,0 @@ -# CI provides a prebuilt CLI; direct local invocations keep using Cargo. -prepare_spacetime() { - local stdb_path="$1" - - if [[ -n "${SPACETIME_BIN:-}" ]]; then - SPACETIME=("$SPACETIME_BIN") - else - cargo build --manifest-path "$stdb_path/crates/standalone/Cargo.toml" - SPACETIME=(cargo run --manifest-path "$stdb_path/crates/cli/Cargo.toml" --) - fi -} diff --git a/templates/chat-react-ts/spacetimedb/package.json b/templates/chat-react-ts/spacetimedb/package.json index c8a3cdbdaa4..84620dae731 100644 --- a/templates/chat-react-ts/spacetimedb/package.json +++ b/templates/chat-react-ts/spacetimedb/package.json @@ -3,9 +3,9 @@ "license": "ISC", "type": "module", "scripts": { - "build": "cargo build -p spacetimedb-standalone && cargo run -p spacetimedb-cli -- build", - "generate-ts": "cargo build -p spacetimedb-standalone && cargo run -p spacetimedb-cli -- generate --lang typescript --out-dir ts-codegen", - "publish": "cargo run -p spacetimedb-cli -- publish" + "build": "cargo ci run-spacetime build", + "generate-ts": "cargo ci run-spacetime generate --lang typescript --out-dir ts-codegen", + "publish": "cargo ci run-spacetime publish" }, "dependencies": { "spacetimedb": "workspace:^" diff --git a/tools/ci/commands/run-spacetime/Cargo.toml b/tools/ci/commands/run-spacetime/Cargo.toml new file mode 100644 index 00000000000..3ec38ddf291 --- /dev/null +++ b/tools/ci/commands/run-spacetime/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "ci-run-spacetime" +version = "0.1.0" +edition.workspace = true + +[dependencies] +anyhow.workspace = true +duct.workspace = true + +[lints] +workspace = true diff --git a/tools/ci/commands/run-spacetime/src/main.rs b/tools/ci/commands/run-spacetime/src/main.rs new file mode 100644 index 00000000000..f7820e664ee --- /dev/null +++ b/tools/ci/commands/run-spacetime/src/main.rs @@ -0,0 +1,78 @@ +#![allow(clippy::disallowed_macros)] + +use anyhow::{bail, ensure, Result}; +use duct::cmd; +use std::{ + env, + ffi::OsString, + path::{Path, PathBuf}, +}; + +const CLI_NAME: &str = "spacetimedb-cli"; +const STANDALONE_NAME: &str = "spacetimedb-standalone"; + +fn executable_name(name: &str) -> OsString { + if env::consts::EXE_EXTENSION.is_empty() { + name.into() + } else { + format!("{name}.{}", env::consts::EXE_EXTENSION).into() + } +} + +fn validate_runtime(cli: &Path) -> Result<()> { + ensure!( + cli.is_file(), + "SpacetimeDB CLI binary does not exist at {}", + cli.display() + ); + + let standalone = cli.with_file_name(executable_name(STANDALONE_NAME)); + ensure!( + standalone.is_file(), + "SpacetimeDB standalone binary does not exist beside the CLI at {}", + standalone.display() + ); + + Ok(()) +} + +fn repo_root() -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .ancestors() + .nth(4) + .expect("run-spacetime package should be nested beneath the workspace root") + .to_owned() +} + +fn local_cli() -> Result { + cmd!("cargo", "build", "-p", CLI_NAME, "-p", STANDALONE_NAME).run()?; + + let target_dir = env::var_os("CARGO_TARGET_DIR") + .map(PathBuf::from) + .unwrap_or_else(|| repo_root().join("target")); + Ok(target_dir.join("debug").join(executable_name(CLI_NAME))) +} + +fn main() -> Result<()> { + let args = env::args_os().skip(1).collect::>(); + if args.is_empty() { + bail!("Usage: cargo ci run-spacetime [args...]"); + } + + let cli = match env::var_os("SPACETIME_BIN") { + Some(path) => { + let path = PathBuf::from(path); + ensure!( + path.is_absolute(), + "SPACETIME_BIN must be an absolute path, got {}", + path.display() + ); + path + } + None => local_cli()?, + }; + + validate_runtime(&cli)?; + cmd(cli, args).run()?; + Ok(()) +} diff --git a/tools/ci/commands/test/src/main.rs b/tools/ci/commands/test/src/main.rs index 3b759cc2ec1..c6db37a4f64 100644 --- a/tools/ci/commands/test/src/main.rs +++ b/tools/ci/commands/test/src/main.rs @@ -1,9 +1,8 @@ #![allow(clippy::disallowed_macros)] -use anyhow::{ensure, Result}; +use anyhow::Result; use ci_common::pnpm; use clap::Parser; use duct::cmd; -use std::{env, path::PathBuf}; /// Runs tests /// @@ -17,33 +16,11 @@ struct Cli { prebuilt_runtime: bool, } -fn runtime_binary_path(binary_name: &str) -> PathBuf { - let target_dir = env::var_os("CARGO_TARGET_DIR") - .map(PathBuf::from) - .unwrap_or_else(|| ci_common::repo_root().join("target")); - target_dir - .join("release") - .join(binary_name) - .with_extension(env::consts::EXE_EXTENSION) -} - -fn verify_prebuilt_runtime() -> Result<()> { - for binary_name in ["spacetimedb-cli", "spacetimedb-standalone"] { - let binary_path = runtime_binary_path(binary_name); - ensure!( - binary_path.is_file(), - "--prebuilt-runtime requires {binary_name} at {}", - binary_path.display() - ); - } - Ok(()) -} - fn main() -> Result<()> { let cli = Cli::parse(); if cli.prebuilt_runtime { - verify_prebuilt_runtime()?; + ci_common::require_prebuilt_runtime()?; } pnpm(["build"]).dir("crates/bindings-typescript").run()?; diff --git a/tools/ci/commands/typescript-test/src/main.rs b/tools/ci/commands/typescript-test/src/main.rs index f18a3b82bfb..3cdcef23bf2 100644 --- a/tools/ci/commands/typescript-test/src/main.rs +++ b/tools/ci/commands/typescript-test/src/main.rs @@ -2,19 +2,46 @@ use anyhow::{bail, Result}; use ci_common::pnpm; use clap::Parser; -use duct::cmd; +use duct::Expression; /// Runs TypeScript workspace tests and template build checks. #[derive(Parser)] -struct Cli {} +struct Cli { + /// Use release CLI and standalone binaries already present in the Cargo target directory. + #[arg(long)] + prebuilt_runtime: bool, +} + +fn with_runtime(command: Expression, runtime: Option<&ci_common::PrebuiltRuntime>) -> Expression { + match runtime { + Some(runtime) => command.env("SPACETIME_BIN", &runtime.cli), + None => command, + } +} fn main() -> Result<()> { - Cli::parse(); + let cli = Cli::parse(); + let prebuilt_runtime = cli + .prebuilt_runtime + .then(ci_common::require_prebuilt_runtime) + .transpose()?; - pnpm(["build"]).dir("crates/bindings-typescript").run()?; - pnpm(["test"]).dir("crates/bindings-typescript").run()?; - pnpm(["generate"]).dir("templates/chat-react-ts").run()?; - let diff_status = cmd!( + with_runtime( + pnpm(["build"]).dir("crates/bindings-typescript"), + prebuilt_runtime.as_ref(), + ) + .run()?; + with_runtime( + pnpm(["test"]).dir("crates/bindings-typescript"), + prebuilt_runtime.as_ref(), + ) + .run()?; + with_runtime( + pnpm(["generate"]).dir("templates/chat-react-ts"), + prebuilt_runtime.as_ref(), + ) + .run()?; + let diff_status = duct::cmd!( "bash", "tools/check-diff.sh", "templates/chat-react-ts/src/module_bindings" @@ -23,12 +50,20 @@ fn main() -> Result<()> { if !diff_status.status.success() { bail!("Bindings are dirty. Please generate bindings again and commit them to this branch."); } - pnpm(["build"]).dir("templates/chat-react-ts").run()?; - pnpm(["-r", "--filter", "./**", "run", "build"]) - .dir("templates") - .run()?; - pnpm(["-r", "--filter", "./**", "run", "build"]) - .dir("crates/bindings-typescript") - .run()?; + with_runtime( + pnpm(["build"]).dir("templates/chat-react-ts"), + prebuilt_runtime.as_ref(), + ) + .run()?; + with_runtime( + pnpm(["-r", "--filter", "./**", "run", "build"]).dir("templates"), + prebuilt_runtime.as_ref(), + ) + .run()?; + with_runtime( + pnpm(["-r", "--filter", "./**", "run", "build"]).dir("crates/bindings-typescript"), + prebuilt_runtime.as_ref(), + ) + .run()?; Ok(()) } diff --git a/tools/ci/common/src/lib.rs b/tools/ci/common/src/lib.rs index 4dfafe8e03b..c8b293f5c9d 100644 --- a/tools/ci/common/src/lib.rs +++ b/tools/ci/common/src/lib.rs @@ -1,9 +1,15 @@ -use anyhow::{bail, Result}; +use anyhow::{bail, ensure, Result}; use duct::{cmd, Expression}; +use std::env; use std::ffi::OsStr; use std::path::Path; use std::path::PathBuf; +pub struct PrebuiltRuntime { + pub cli: PathBuf, + pub standalone: PathBuf, +} + pub fn ensure_repo_root() -> Result<()> { if !Path::new("Cargo.toml").exists() { bail!("You must execute this command from the SpacetimeDB repository root (where Cargo.toml is located)"); @@ -20,6 +26,31 @@ pub fn repo_root() -> PathBuf { .to_path_buf() } +pub fn require_prebuilt_runtime() -> Result { + let target_dir = env::var_os("CARGO_TARGET_DIR") + .map(PathBuf::from) + .unwrap_or_else(|| repo_root().join("target")); + let release_dir = target_dir.join("release"); + let binary_path = |name: &str| release_dir.join(name).with_extension(env::consts::EXE_EXTENSION); + let runtime = PrebuiltRuntime { + cli: binary_path("spacetimedb-cli"), + standalone: binary_path("spacetimedb-standalone"), + }; + + for (name, path) in [ + ("spacetimedb-cli", &runtime.cli), + ("spacetimedb-standalone", &runtime.standalone), + ] { + ensure!( + path.is_file(), + "--prebuilt-runtime requires {name} at {}", + path.display() + ); + } + + Ok(runtime) +} + pub fn pnpm(args: I) -> Expression where I: IntoIterator, diff --git a/tools/ci/src/main.rs b/tools/ci/src/main.rs index bb0878277d9..32890a44985 100644 --- a/tools/ci/src/main.rs +++ b/tools/ci/src/main.rs @@ -82,6 +82,13 @@ const COMMANDS: &[Command] = &[ }, ]; +// Utilities are available as explicit subcommands, but are not run by a bare +// `cargo ci` invocation. +const UTILITY_COMMANDS: &[Command] = &[Command { + path: &["run-spacetime"], + package: "ci-run-spacetime", +}]; + fn print_help() { println!("Usage: cargo ci [--skip ...]"); println!(" cargo ci [ARGS]..."); @@ -90,11 +97,17 @@ fn print_help() { for command in COMMANDS { println!(" {}", command.path.join(" ")); } + println!(); + println!("Utilities:"); + for command in UTILITY_COMMANDS { + println!(" {}", command.path.join(" ")); + } } fn command_for(args: &[String]) -> Option<(&'static Command, usize)> { COMMANDS .iter() + .chain(UTILITY_COMMANDS) .filter_map(|command| { args.get(..command.path.len()) .is_some_and(|head| head.iter().map(String::as_str).eq(command.path.iter().copied())) diff --git a/tools/gen-bindings/src/main.rs b/tools/gen-bindings/src/main.rs index 88fe7c7cc51..8cdb5f15a03 100644 --- a/tools/gen-bindings/src/main.rs +++ b/tools/gen-bindings/src/main.rs @@ -46,26 +46,17 @@ fn run_inherit(cmd: impl AsRef, args: &[&str], cwd: Option<&Path>) -> Res fn main() -> Result<()> { let args = Cli::parse(); - let workspace_dir = Path::new(env!("CARGO_MANIFEST_DIR")) - .parent() - .unwrap() - .parent() - .unwrap(); - - // 1) Build prerequisite - run_inherit("cargo", &["build"], Some(workspace_dir))?; - - // 2) Ensure output directory exists + // 1) Ensure output directory exists if !Path::new(&args.out_dir).exists() { fs::create_dir_all(&args.out_dir).context("create output directory")?; } - // 3) Generate TS client from project + // 2) Generate TS client from project run_inherit( - workspace_dir - .join("target/debug/spacetimedb-cli") - .with_extension(std::env::consts::EXE_EXTENSION), + "cargo", &[ + "ci", + "run-spacetime", "generate", "-y", "--lang", From 91e1812442df116475381ca3978d9e14cf63633b Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Tue, 25 Aug 2026 12:11:29 -0700 Subject: [PATCH 40/50] [bfops/test-runner]: skip ones we've fixed --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ab44fd3f31b..7c310a89e4b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -72,7 +72,7 @@ jobs: upload-build-artifacts-linux: needs: [merge_queue_noop, lints] - if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} + if: false name: Upload build artifacts (Linux) runs-on: spacetimedb-new-runner-2-staging timeout-minutes: 15 From 733512a813aedcc83b6a41363fccf9ba96c9b285 Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Tue, 25 Aug 2026 12:34:53 -0700 Subject: [PATCH 41/50] [bfops/test-runner]: -vv --- .github/workflows/ci.yml | 18 +++++++++--------- tools/ci/commands/lint/src/main.rs | 9 +++++++-- tools/ci/commands/test/src/main.rs | 5 +++++ tools/ci/commands/wasm-bindings/src/main.rs | 4 ++-- 4 files changed, 23 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7c310a89e4b..dd02480e879 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -529,7 +529,7 @@ jobs: INSTALLED_WASM_BINDGEN_VERSION="$(wasm-bindgen --version 2>/dev/null | awk '{print $2}' || true)" if [ "${INSTALLED_WASM_BINDGEN_VERSION}" != "${REQUIRED_WASM_BINDGEN_VERSION}" ]; then - cargo install --locked --force wasm-bindgen-cli --version "${REQUIRED_WASM_BINDGEN_VERSION}" + cargo install -vv --locked --force wasm-bindgen-cli --version "${REQUIRED_WASM_BINDGEN_VERSION}" fi wasm-bindgen --version @@ -583,7 +583,7 @@ jobs: run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) - name: Run index scan benchmark regression check - run: cargo run --release -p spacetimedb-index-scan-gate + run: cargo run -vv --release -p spacetimedb-index-scan-gate lints: needs: [merge_queue_noop] @@ -889,7 +889,7 @@ jobs: cd "$GITHUB_WORKSPACE/sdks/unreal" cargo --version - cargo test -- --test-threads=1 + cargo test -vv -- --test-threads=1 ' cli_docs: @@ -1019,8 +1019,8 @@ jobs: run: | export CARGO_HOME="$HOME/.cargo" echo "$CARGO_HOME/bin" >> "$GITHUB_PATH" - cargo install --force --path crates/cli --locked --message-format=short - cargo install --force --path crates/standalone --locked --message-format=short + cargo install -vv --force --path crates/cli --locked --message-format=short + cargo install -vv --force --path crates/standalone --locked --message-format=short # Add a handy alias using the old binary name, so that we don't have to rewrite all scripts (incl. in submodules). ln -sf $CARGO_HOME/bin/spacetimedb-cli $CARGO_HOME/bin/spacetime @@ -1142,8 +1142,8 @@ jobs: run: | export CARGO_HOME="$HOME/.cargo" echo "$CARGO_HOME/bin" >> "$GITHUB_PATH" - cargo install --force --path crates/cli --locked --message-format=short - cargo install --force --path crates/standalone --locked --message-format=short + cargo install -vv --force --path crates/cli --locked --message-format=short + cargo install -vv --force --path crates/standalone --locked --message-format=short # Add a handy alias using the old binary name, so that we don't have to rewrite all scripts (incl. in submodules). ln -sf $CARGO_HOME/bin/spacetimedb-cli $CARGO_HOME/bin/spacetime @@ -1262,8 +1262,8 @@ jobs: run: | export CARGO_HOME="$HOME/.cargo" echo "$CARGO_HOME/bin" >> "$GITHUB_PATH" - cargo install --force --path crates/cli --locked --message-format=short - cargo install --force --path crates/standalone --features allow_loopback_http_for_tests --locked --message-format=short + cargo install -vv --force --path crates/cli --locked --message-format=short + cargo install -vv --force --path crates/standalone --features allow_loopback_http_for_tests --locked --message-format=short # Add a handy alias using the old binary name, so that we don't have to rewrite all scripts (incl. in submodules). ln -sf $CARGO_HOME/bin/spacetimedb-cli $CARGO_HOME/bin/spacetime diff --git a/tools/ci/commands/lint/src/main.rs b/tools/ci/commands/lint/src/main.rs index 956d4f44ce4..b09f236b03c 100644 --- a/tools/ci/commands/lint/src/main.rs +++ b/tools/ci/commands/lint/src/main.rs @@ -308,6 +308,7 @@ fn main() -> Result<()> { cmd!( "cargo", "clippy", + "-vv", "--timings", "--all", "--tests", @@ -320,6 +321,7 @@ fn main() -> Result<()> { cmd!( "cargo", "clippy", + "-vv", "--timings", "--no-default-features", "--features=browser", @@ -336,7 +338,10 @@ fn main() -> Result<()> { .dir("crates/bindings-csharp") .run()?; pnpm(["lint"]).run()?; - cmd!("cargo", "test", "--doc", "--target", "wasm32-unknown-unknown") + cmd!("cargo", "test", "-vv", "--doc", "--target", "wasm32-unknown-unknown") + .dir("crates/bindings") + .run()?; + cmd!("cargo", "test", "-vv", "--doc") .dir("crates/bindings") .run()?; cmd!("cargo", "test", "--doc").dir("crates/bindings").run()?; @@ -345,7 +350,7 @@ fn main() -> Result<()> { // We won't pass `--no-deps`, though, // since we want everything reachable through it to also work. // This includes `sats` and `lib`. - cmd!("cargo", "doc") + cmd!("cargo", "doc", "-vv") .dir("crates/bindings") // Make `cargo doc` exit with error on warnings, most notably broken links .env("RUSTDOCFLAGS", "--deny warnings") diff --git a/tools/ci/commands/test/src/main.rs b/tools/ci/commands/test/src/main.rs index 2b5e08299a7..04aa20c7a42 100644 --- a/tools/ci/commands/test/src/main.rs +++ b/tools/ci/commands/test/src/main.rs @@ -24,6 +24,7 @@ fn main() -> Result<()> { cmd!( "cargo", "test", + "-vv", "--all", "--exclude", "spacetimedb-smoketests", @@ -43,6 +44,7 @@ fn main() -> Result<()> { cmd!( "cargo", "test", + "-vv", "-p", "spacetimedb", "--features", @@ -70,6 +72,7 @@ fn main() -> Result<()> { cmd!( "cargo", "test", + "-vv", "-p", "spacetimedb-sdk", "--features", @@ -84,6 +87,7 @@ fn main() -> Result<()> { cmd!( "cargo", "test", + "-vv", "-p", "spacetimedb-sdk", "--features", @@ -102,6 +106,7 @@ fn main() -> Result<()> { cmd!( "cargo", "test", + "-vv", "-p", "spacetimedb-durability", "--features", diff --git a/tools/ci/commands/wasm-bindings/src/main.rs b/tools/ci/commands/wasm-bindings/src/main.rs index 53f4ee6ea4d..afbd9d681e3 100644 --- a/tools/ci/commands/wasm-bindings/src/main.rs +++ b/tools/ci/commands/wasm-bindings/src/main.rs @@ -22,7 +22,7 @@ fn main() -> Result<()> { ]) .run()?; pnpm(["build"]).dir("crates/bindings-typescript").run()?; - cmd!("cargo", "test", "-p", "spacetimedb-codegen").run()?; + cmd!("cargo", "test", "-vv", "-p", "spacetimedb-codegen").run()?; // Pre-build the CLI so that it _doesn't_ get `cargo update`d, since that may break the build. cmd!("cargo", "build", "-vv", "-p", "spacetimedb-cli").run()?; // Make sure the `Cargo.lock` file reflects the latest available versions. @@ -31,7 +31,7 @@ fn main() -> Result<()> { // of dependencies than what is in the workspace lock file. // // For context see also: https://github.com/clockworklabs/SpacetimeDB/pull/2714 - cmd!("cargo", "update").run()?; + cmd!("cargo", "update", "-vv").run()?; let cli_path = ci_common::repo_root() .join("target/debug/spacetimedb-cli") .with_extension(std::env::consts::EXE_EXTENSION); From 0dd6cff7271dea3c26032b0524e4c95e4596288c Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Tue, 25 Aug 2026 12:35:20 -0700 Subject: [PATCH 42/50] [bfops/test-runner]: fix dup --- tools/ci/commands/lint/src/main.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tools/ci/commands/lint/src/main.rs b/tools/ci/commands/lint/src/main.rs index b09f236b03c..10bb7c61125 100644 --- a/tools/ci/commands/lint/src/main.rs +++ b/tools/ci/commands/lint/src/main.rs @@ -341,10 +341,7 @@ fn main() -> Result<()> { cmd!("cargo", "test", "-vv", "--doc", "--target", "wasm32-unknown-unknown") .dir("crates/bindings") .run()?; - cmd!("cargo", "test", "-vv", "--doc") - .dir("crates/bindings") - .run()?; - cmd!("cargo", "test", "--doc").dir("crates/bindings").run()?; + cmd!("cargo", "test", "-vv", "--doc").dir("crates/bindings").run()?; // `bindings` is the only crate we care strongly about documenting, // since we link to its docs.rs from our website. // We won't pass `--no-deps`, though, From fbd61ca4226c7efde694cede0872bd5d31361434 Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Tue, 25 Aug 2026 12:54:24 -0700 Subject: [PATCH 43/50] [bfops/test-runner]: use target_dir properly --- tools/ci/commands/wasm-bindings/src/main.rs | 14 ++++++++++++-- tools/gen-bindings/src/main.rs | 14 +++++++++++--- tools/generate-client-api/src/main.rs | 14 +++++++++++--- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/tools/ci/commands/wasm-bindings/src/main.rs b/tools/ci/commands/wasm-bindings/src/main.rs index afbd9d681e3..1e1c4f25d14 100644 --- a/tools/ci/commands/wasm-bindings/src/main.rs +++ b/tools/ci/commands/wasm-bindings/src/main.rs @@ -3,6 +3,7 @@ use anyhow::Result; use ci_common::pnpm; use clap::Parser; use duct::cmd; +use std::path::PathBuf; /// Tests Wasm bindings /// @@ -10,6 +11,15 @@ use duct::cmd; #[derive(Parser)] struct Cli {} +fn cargo_target_dir() -> PathBuf { + let repo_root = ci_common::repo_root(); + match std::env::var_os("CARGO_TARGET_DIR").map(PathBuf::from) { + Some(path) if path.is_absolute() => path, + Some(path) => repo_root.join(path), + None => repo_root.join("target"), + } +} + fn main() -> Result<()> { Cli::parse(); @@ -32,8 +42,8 @@ fn main() -> Result<()> { // // For context see also: https://github.com/clockworklabs/SpacetimeDB/pull/2714 cmd!("cargo", "update", "-vv").run()?; - let cli_path = ci_common::repo_root() - .join("target/debug/spacetimedb-cli") + let cli_path = cargo_target_dir() + .join("debug/spacetimedb-cli") .with_extension(std::env::consts::EXE_EXTENSION); cmd!(cli_path, "build", "--module-path", "modules/module-test",).run()?; diff --git a/tools/gen-bindings/src/main.rs b/tools/gen-bindings/src/main.rs index 88fe7c7cc51..8e5c3ed2802 100644 --- a/tools/gen-bindings/src/main.rs +++ b/tools/gen-bindings/src/main.rs @@ -4,7 +4,7 @@ use clap::Parser; use replace_spacetimedb::{replace_in_tree, ReplaceOptions}; use std::ffi::OsStr; use std::fs; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; #[derive(Parser, Debug)] @@ -43,6 +43,14 @@ fn run_inherit(cmd: impl AsRef, args: &[&str], cwd: Option<&Path>) -> Res Ok(()) } +fn cargo_target_dir(workspace_dir: &Path) -> PathBuf { + match std::env::var_os("CARGO_TARGET_DIR").map(PathBuf::from) { + Some(path) if path.is_absolute() => path, + Some(path) => workspace_dir.join(path), + None => workspace_dir.join("target"), + } +} + fn main() -> Result<()> { let args = Cli::parse(); @@ -62,8 +70,8 @@ fn main() -> Result<()> { // 3) Generate TS client from project run_inherit( - workspace_dir - .join("target/debug/spacetimedb-cli") + cargo_target_dir(workspace_dir) + .join("debug/spacetimedb-cli") .with_extension(std::env::consts::EXE_EXTENSION), &[ "generate", diff --git a/tools/generate-client-api/src/main.rs b/tools/generate-client-api/src/main.rs index e9b794f93a2..440e06cf6b9 100644 --- a/tools/generate-client-api/src/main.rs +++ b/tools/generate-client-api/src/main.rs @@ -3,7 +3,7 @@ use anyhow::{anyhow, Context, Result}; use replace_spacetimedb::{replace_in_tree, ReplaceOptions}; use std::ffi::OsStr; use std::fs; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; use tempfile::NamedTempFile; @@ -25,6 +25,14 @@ fn run_inherit(cmd: impl AsRef, args: &[&str], cwd: Option<&Path>) -> Res Ok(()) } +fn cargo_target_dir(workspace_dir: &Path) -> PathBuf { + match std::env::var_os("CARGO_TARGET_DIR").map(PathBuf::from) { + Some(path) if path.is_absolute() => path, + Some(path) => workspace_dir.join(path), + None => workspace_dir.join("target"), + } +} + /// Run a command and return captured stdout as UTF-8 string. fn run_capture(cmd: &str, args: &[&str]) -> Result { let out = Command::new(cmd) @@ -75,8 +83,8 @@ fn main() -> Result<()> { // 4) Generate TS client run_inherit( - workspace_dir - .join("target/debug/spacetimedb-cli") + cargo_target_dir(workspace_dir) + .join("debug/spacetimedb-cli") .with_extension(std::env::consts::EXE_EXTENSION), &[ "generate", From de4e6ab145d6d90a792e5bfbc410e3d0b01022da Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Tue, 25 Aug 2026 12:54:40 -0700 Subject: [PATCH 44/50] [bfops/test-runner]: more fixes --- .github/workflows/ci.yml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dd02480e879..2e7ef2c3035 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1325,6 +1325,8 @@ jobs: env: RUST_BACKTRACE: full steps: + - *set-cargo-target-dir + - name: Find Git ref env: PR_NUMBER: ${{ github.event.inputs.pr_number }} @@ -1340,6 +1342,9 @@ jobs: uses: actions/checkout@v4 with: ref: ${{ env.GIT_REF }} + fetch-depth: 0 + + - *restore-source-mtimes - uses: dsherret/rust-toolchain-file@v1 - name: Set default rust toolchain @@ -1353,7 +1358,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: cargo-timings-global-json-policy - path: ${{ github.workspace }}/target/cargo-timings/ + path: ${{ env.CARGO_TARGET_DIR }}/cargo-timings/ retention-days: 14 smoketests_mod_rs_complete: @@ -1366,6 +1371,8 @@ jobs: env: RUST_BACKTRACE: full steps: + - *set-cargo-target-dir + - name: Find Git ref env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -1382,6 +1389,10 @@ jobs: uses: actions/checkout@v4 with: ref: ${{ env.GIT_REF }} + fetch-depth: 0 + + - *restore-source-mtimes + - uses: dsherret/rust-toolchain-file@v1 - name: Set default rust toolchain run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) From 1159cdd1bc25f6df5313c815701f5a433c638f67 Mon Sep 17 00:00:00 2001 From: clockwork-labs-bot Date: Tue, 25 Aug 2026 16:01:50 -0400 Subject: [PATCH 45/50] Move codegen git hash out of lib --- crates/{lib => codegen}/build.rs | 0 crates/codegen/src/util.rs | 3 ++- crates/lib/src/version.rs | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) rename crates/{lib => codegen}/build.rs (100%) diff --git a/crates/lib/build.rs b/crates/codegen/build.rs similarity index 100% rename from crates/lib/build.rs rename to crates/codegen/build.rs diff --git a/crates/codegen/src/util.rs b/crates/codegen/src/util.rs index a13a7ff2aba..5a62afdd06f 100644 --- a/crates/codegen/src/util.rs +++ b/crates/codegen/src/util.rs @@ -56,6 +56,7 @@ pub(super) fn print_lines(output: &mut Indenter, lines: &[&str]) { } pub const AUTO_GENERATED_PREFIX: &str = "// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB"; +const GIT_HASH: &str = env!("GIT_HASH"); const AUTO_GENERATED_FILE_COMMENT: &[&str] = &[ "// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE", @@ -72,7 +73,7 @@ pub(super) fn print_auto_generated_version_comment(output: &mut Indenter) { output, "// This was generated using spacetimedb cli version {} (commit {}).", version::spacetimedb_lib_version(), - version::GIT_HASH + GIT_HASH ); writeln!(output); } diff --git a/crates/lib/src/version.rs b/crates/lib/src/version.rs index c0fc2454c05..ba06079aeb6 100644 --- a/crates/lib/src/version.rs +++ b/crates/lib/src/version.rs @@ -1,5 +1,4 @@ const CLI_VERSION: &str = env!("CARGO_PKG_VERSION"); -pub const GIT_HASH: &str = env!("GIT_HASH"); pub fn spacetimedb_lib_version() -> &'static str { CLI_VERSION From c5050e41ec5baff7f2ec79daf65a77df63aa35b7 Mon Sep 17 00:00:00 2001 From: joshua-spacetime Date: Tue, 25 Aug 2026 16:44:46 -0700 Subject: [PATCH 46/50] gut cargo ci wasm-bindings --- .github/workflows/ci.yml | 39 ++++---------- Cargo.lock | 20 +++---- Cargo.toml | 2 +- .../Cargo.toml | 2 +- .../commands/module-latest-deps/src/main.rs | 52 +++++++++++++++++++ tools/ci/commands/wasm-bindings/src/main.rs | 41 --------------- tools/ci/src/main.rs | 4 +- 7 files changed, 76 insertions(+), 84 deletions(-) rename tools/ci/commands/{wasm-bindings => module-latest-deps}/Cargo.toml (84%) create mode 100644 tools/ci/commands/module-latest-deps/src/main.rs delete mode 100644 tools/ci/commands/wasm-bindings/src/main.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ba9420b20ce..eefd9bead33 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -824,47 +824,28 @@ jobs: path: ${{ env.CARGO_TARGET_DIR }}/cargo-timings/ retention-days: 14 - wasm_bindings: - needs: [merge_queue_noop] + module_latest_deps: + needs: [merge_queue_noop, upload-build-artifacts-linux] if: ${{ needs.merge_queue_noop.outputs.skip != 'true' }} name: Build and test wasm bindings runs-on: spacetimedb-new-runner-2 env: CARGO_TARGET_DIR: ${{ github.workspace }}/target RUST_BACKTRACE: full + ARTIFACT_SUFFIX: linux steps: - - uses: actions/checkout@v3 + - *find-git-ref + - *checkout-sources - uses: dsherret/rust-toolchain-file@v1 - - name: Set default rust toolchain - run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) + - *set-default-rust-toolchain - run: echo ::add-matcher::.github/workflows/rust_matcher.json - - *set-native-cache-keys - - *restore-jemalloc - - *configure-cached-jemalloc - - *restore-zstd - - *configure-cached-zstd - - *restore-openssl - - *configure-cached-openssl - - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: 22 - - - uses: ./.github/actions/setup-pnpm - - - name: Run bindgen tests - run: cargo ci wasm-bindings + - *download-build-artifacts + - *extract-build-artifacts - - name: Upload timing reports - if: always() - uses: actions/upload-artifact@v4 - with: - name: cargo-timings-wasm-bindings - path: ${{ env.CARGO_TARGET_DIR }}/cargo-timings/ - retention-days: 14 + - name: Build module with latest compatible dependencies + run: cargo ci module-latest-deps --prebuilt-cli publish_checks: needs: [merge_queue_noop] diff --git a/Cargo.lock b/Cargo.lock index fc5253adb9f..d16dc421a4e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -961,6 +961,16 @@ dependencies = [ "serde_json", ] +[[package]] +name = "ci-module-latest-deps" +version = "0.1.0" +dependencies = [ + "anyhow", + "ci-common", + "clap 4.5.50", + "duct", +] + [[package]] name = "ci-publish-checks" version = "0.1.0" @@ -1033,16 +1043,6 @@ dependencies = [ "duct", ] -[[package]] -name = "ci-wasm-bindings" -version = "0.1.0" -dependencies = [ - "anyhow", - "ci-common", - "clap 4.5.50", - "duct", -] - [[package]] name = "ci-workflow-watch" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 18d5c5a324e..28529189980 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -70,7 +70,7 @@ members = [ "tools/ci", "tools/ci/commands/test", "tools/ci/commands/lint", - "tools/ci/commands/wasm-bindings", + "tools/ci/commands/module-latest-deps", "tools/ci/commands/smoketests", "tools/ci/commands/smoketest-checks", "tools/ci/commands/keynote-bench", diff --git a/tools/ci/commands/wasm-bindings/Cargo.toml b/tools/ci/commands/module-latest-deps/Cargo.toml similarity index 84% rename from tools/ci/commands/wasm-bindings/Cargo.toml rename to tools/ci/commands/module-latest-deps/Cargo.toml index e807f25ea7e..c360db5b600 100644 --- a/tools/ci/commands/wasm-bindings/Cargo.toml +++ b/tools/ci/commands/module-latest-deps/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "ci-wasm-bindings" +name = "ci-module-latest-deps" version = "0.1.0" edition.workspace = true diff --git a/tools/ci/commands/module-latest-deps/src/main.rs b/tools/ci/commands/module-latest-deps/src/main.rs new file mode 100644 index 00000000000..834c20b111d --- /dev/null +++ b/tools/ci/commands/module-latest-deps/src/main.rs @@ -0,0 +1,52 @@ +#![allow(clippy::disallowed_macros)] + +use anyhow::{ensure, Result}; +use clap::Parser; +use duct::cmd; +use std::{env, path::PathBuf}; + +/// Checks that a module builds with the latest compatible dependencies. +#[derive(Parser)] +struct Cli { + /// Use the release CLI already present in the Cargo target directory. + #[arg(long)] + prebuilt_cli: bool, +} + +fn target_dir() -> PathBuf { + match env::var_os("CARGO_TARGET_DIR").map(PathBuf::from) { + Some(path) if path.is_absolute() => path, + Some(path) => ci_common::repo_root().join(path), + None => ci_common::repo_root().join("target"), + } +} + +fn main() -> Result<()> { + let cli = Cli::parse(); + + // Build the CLI before updating the lockfile so a newly published incompatible dependency + // cannot prevent us from exercising the fresh module dependency graph. + let cli_path = if cli.prebuilt_cli { + let path = target_dir() + .join("release/spacetimedb-cli") + .with_extension(env::consts::EXE_EXTENSION); + ensure!( + path.is_file(), + "--prebuilt-cli requires spacetimedb-cli at {}", + path.display() + ); + path + } else { + cmd!("cargo", "build", "-p", "spacetimedb-cli").run()?; + target_dir() + .join("debug/spacetimedb-cli") + .with_extension(env::consts::EXE_EXTENSION) + }; + + // A fresh module gets the latest versions permitted by its dependency constraints rather + // than the exact versions pinned in this repository's committed lockfile. + cmd!("cargo", "update").run()?; + cmd!(cli_path, "build", "--module-path", "modules/module-test").run()?; + + Ok(()) +} diff --git a/tools/ci/commands/wasm-bindings/src/main.rs b/tools/ci/commands/wasm-bindings/src/main.rs deleted file mode 100644 index aa1946d11ac..00000000000 --- a/tools/ci/commands/wasm-bindings/src/main.rs +++ /dev/null @@ -1,41 +0,0 @@ -#![allow(clippy::disallowed_macros)] -use anyhow::Result; -use ci_common::pnpm; -use clap::Parser; -use duct::cmd; - -/// Tests Wasm bindings -/// -/// Runs tests for the codegen crate and builds a test module with the wasm bindings. -#[derive(Parser)] -struct Cli {} - -fn main() -> Result<()> { - Cli::parse(); - - pnpm([ - "install", - "--filter", - "./crates/bindings-typescript...", - "--filter", - "./modules/module-test-ts...", - ]) - .run()?; - pnpm(["build"]).dir("crates/bindings-typescript").run()?; - cmd!("cargo", "test", "-p", "spacetimedb-codegen").run()?; - // Pre-build the CLI so that it _doesn't_ get `cargo update`d, since that may break the build. - cmd!("cargo", "build", "-p", "spacetimedb-cli").run()?; - // Make sure the `Cargo.lock` file reflects the latest available versions. - // This is what users would end up with on a fresh module, so we want to - // catch any compile errors arising from a different transitive closure - // of dependencies than what is in the workspace lock file. - // - // For context see also: https://github.com/clockworklabs/SpacetimeDB/pull/2714 - cmd!("cargo", "update").run()?; - let cli_path = ci_common::repo_root() - .join("target/debug/spacetimedb-cli") - .with_extension(std::env::consts::EXE_EXTENSION); - cmd!(cli_path, "build", "--module-path", "modules/module-test",).run()?; - - Ok(()) -} diff --git a/tools/ci/src/main.rs b/tools/ci/src/main.rs index 32890a44985..d44904087e2 100644 --- a/tools/ci/src/main.rs +++ b/tools/ci/src/main.rs @@ -21,8 +21,8 @@ const COMMANDS: &[Command] = &[ package: "ci-lint", }, Command { - path: &["wasm-bindings"], - package: "ci-wasm-bindings", + path: &["module-latest-deps"], + package: "ci-module-latest-deps", }, Command { path: &["smoketests"], From a325683b895e679029685028e278df6d7e2001fd Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Tue, 25 Aug 2026 16:45:43 -0700 Subject: [PATCH 47/50] [bfops/test-runner]: moar -vv --- tools/gen-bindings/src/main.rs | 2 +- tools/generate-client-api/src/main.rs | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/gen-bindings/src/main.rs b/tools/gen-bindings/src/main.rs index 8e5c3ed2802..be4276c9518 100644 --- a/tools/gen-bindings/src/main.rs +++ b/tools/gen-bindings/src/main.rs @@ -61,7 +61,7 @@ fn main() -> Result<()> { .unwrap(); // 1) Build prerequisite - run_inherit("cargo", &["build"], Some(workspace_dir))?; + run_inherit("cargo", &["build", "-vv"], Some(workspace_dir))?; // 2) Ensure output directory exists if !Path::new(&args.out_dir).exists() { diff --git a/tools/generate-client-api/src/main.rs b/tools/generate-client-api/src/main.rs index 440e06cf6b9..0626a36c199 100644 --- a/tools/generate-client-api/src/main.rs +++ b/tools/generate-client-api/src/main.rs @@ -38,6 +38,7 @@ fn run_capture(cmd: &str, args: &[&str]) -> Result { let out = Command::new(cmd) .args(args) .stdin(Stdio::null()) + .stderr(Stdio::inherit()) .output() .with_context(|| format!("Failed to start {cmd}"))?; if !out.status.success() { @@ -58,7 +59,7 @@ fn main() -> Result<()> { .unwrap(); // 1) Build prerequisite - run_inherit("cargo", &["build"], Some(workspace_dir))?; + run_inherit("cargo", &["build", "-vv"], Some(workspace_dir))?; // 2) Get schema to a temp file (auto-cleaned) let mut tmp_schema = NamedTempFile::new().context("create temp schema file")?; @@ -66,6 +67,7 @@ fn main() -> Result<()> { "cargo", &[ "run", + "-vv", "-p", "spacetimedb-client-api-messages", "--example", From bfb96f384e1569ba86c1d138b1c077542419bf05 Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Tue, 25 Aug 2026 17:12:12 -0700 Subject: [PATCH 48/50] [bfops/test-runner]: proper mtime caching behavior --- .github/workflows/ci.yml | 41 +++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d14e0a4d4d8..3e7f4054292 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -112,16 +112,47 @@ jobs: with: ref: ${{ env.GIT_REF }} # Full history lets git restore-mtime recover each file's actual - # last-change timestamp instead of using the shallow checkout's timestamp. + # last-change timestamp and makes the warmed commit available for + # content-based cache invalidation below. fetch-depth: 0 - # Cargo checks source mtimes for freshness, so restore committed mtimes to - # avoid invalidating otherwise reusable artifacts in the prebuilt target cache. + # cargo has a behavior that's a bit unfortunate for us here. It does not know the mtime of the files that + # were used to build its artifacts; it just knows the mtime of the artifact. + # So, if you have a sequence of events like: + # 1. cache source commit X happens at time X + # 2. PR commit Y happens at time Y > X + # 3. cache is warmed from commit X at time Z > Y + # + # cargo then sees "artifact built at time Z is more recent than time Y, so it must be up to date". + # + # So here we restore committed mtimes to reuse warm artifacts, then touch files that + # differ from the warmed commit so they will look more recent than the artifact, + # and cargo will properly rebuild anything depending on those files. - &restore-source-mtimes - name: Restore source mtimes from git history + name: Restore source mtimes and invalidate changed files if: runner.os == 'Linux' shell: bash - run: git restore-mtime --quiet + run: | + cached_commit_file="${CARGO_TARGET_DIR}/.warm-cache-commit-SpacetimeDB" + if [[ -f "${cached_commit_file}" ]]; then + cached_commit="$(<"${cached_commit_file}")" + else + cached_commit="" + fi + + if [[ -n "${cached_commit}" ]] && git cat-file -e "${cached_commit}^{commit}" 2>/dev/null; then + git restore-mtime --quiet + echo "Invalidating files changed since cached commit ${cached_commit}" + while IFS= read -r -d '' path; do + if [[ -L "${path}" ]]; then + touch -h -- "${path}" + elif [[ -e "${path}" ]]; then + touch -- "${path}" + fi + done < <(git diff --name-only -z "${cached_commit}" HEAD --) + else + echo "::warning::Warm-cache commit is unavailable; leaving checkout mtimes unchanged" + fi - uses: dsherret/rust-toolchain-file@v1 - &set-default-rust-toolchain From 3604ba0aad81f71b16c452d9121b4f3e413f3158 Mon Sep 17 00:00:00 2001 From: joshua-spacetime Date: Tue, 25 Aug 2026 17:55:02 -0700 Subject: [PATCH 49/50] Address Zeke's comments --- .cargo/config.toml | 1 + .github/workflows/ci.yml | 9 ++- modules/benchmarks-ts/package.json | 6 +- modules/module-test-ts/package.json | 6 +- .../sdk-test-case-conversion-ts/package.json | 6 +- .../package.json | 6 +- .../package.json | 6 +- modules/sdk-test-procedure-ts/package.json | 6 +- modules/sdk-test-ts/package.json | 6 +- modules/sdk-test-view-pk-ts/package.json | 6 +- sdks/csharp/tools~/gen-quickstart.sh | 2 +- sdks/csharp/tools~/gen-regression-tests.sh | 6 +- sdks/csharp/tools~/run-regression-tests.sh | 12 ++-- .../chat-react-ts/spacetimedb/package.json | 6 +- .../commands/module-latest-deps/src/main.rs | 18 ++--- tools/ci/commands/run-spacetime/src/main.rs | 2 +- tools/ci/commands/test/src/main.rs | 17 +++-- tools/ci/commands/typescript-test/src/main.rs | 66 ++++++------------- tools/ci/common/src/lib.rs | 54 +++++++-------- tools/ci/src/main.rs | 17 ++--- tools/gen-bindings/src/main.rs | 3 +- 21 files changed, 116 insertions(+), 145 deletions(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index 7b7b2eb4e1f..e0b12c98bca 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -4,6 +4,7 @@ rustflags = ["--cfg", "tokio_unstable"] [alias] llm = "run --package xtask-llm-benchmark --bin llm_benchmark --" ci = "run -p ci --" +spacetime = "ci other-workflows run-spacetime" regen = "run -p regen --" smoketest = "ci smoketests --" smoketests = "smoketest" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index eefd9bead33..0dac88c7699 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -579,6 +579,7 @@ jobs: CARGO_TARGET_DIR: ${{ github.workspace }}/target RUST_BACKTRACE: full ARTIFACT_SUFFIX: linux + SPACETIME_BIN: ${{ github.workspace }}/target/release/spacetimedb-cli steps: - name: Find Git ref env: @@ -682,7 +683,7 @@ jobs: - name: Run tests run: | source ~/emsdk/emsdk_env.sh - cargo ci test --prebuilt-runtime + cargo ci test --no-build - name: Upload timing reports if: always() @@ -833,6 +834,7 @@ jobs: CARGO_TARGET_DIR: ${{ github.workspace }}/target RUST_BACKTRACE: full ARTIFACT_SUFFIX: linux + SPACETIME_BIN: ${{ github.workspace }}/target/release/spacetimedb-cli steps: - *find-git-ref - *checkout-sources @@ -845,7 +847,7 @@ jobs: - *extract-build-artifacts - name: Build module with latest compatible dependencies - run: cargo ci module-latest-deps --prebuilt-cli + run: cargo ci module-latest-deps --no-build publish_checks: needs: [merge_queue_noop] @@ -1582,6 +1584,7 @@ jobs: CARGO_TARGET_DIR: ${{ github.workspace }}/target RUST_BACKTRACE: full ARTIFACT_SUFFIX: linux + SPACETIME_BIN: ${{ github.workspace }}/target/release/spacetimedb-cli steps: - *find-git-ref - *checkout-sources @@ -1613,7 +1616,7 @@ jobs: - *extract-build-artifacts - name: Run TypeScript tests - run: cargo ci typescript-test --prebuilt-runtime + run: cargo ci typescript-test --no-build - name: Upload timing reports if: always() diff --git a/modules/benchmarks-ts/package.json b/modules/benchmarks-ts/package.json index 839846845c8..3dd18348bb2 100644 --- a/modules/benchmarks-ts/package.json +++ b/modules/benchmarks-ts/package.json @@ -4,9 +4,9 @@ "description": "", "main": "index.js", "scripts": { - "build": "cargo ci run-spacetime build", - "generate-ts": "cargo ci run-spacetime generate --lang typescript --out-dir ts-codegen", - "publish": "cargo ci run-spacetime publish" + "build": "cargo spacetime build", + "generate-ts": "cargo spacetime generate --lang typescript --out-dir ts-codegen", + "publish": "cargo spacetime publish" }, "keywords": [], "author": "", diff --git a/modules/module-test-ts/package.json b/modules/module-test-ts/package.json index f961418a3a8..c5ed04bbe20 100644 --- a/modules/module-test-ts/package.json +++ b/modules/module-test-ts/package.json @@ -3,9 +3,9 @@ "license": "ISC", "type": "module", "scripts": { - "build": "cargo ci run-spacetime build", - "generate-ts": "cargo ci run-spacetime generate --lang typescript --out-dir ts-codegen", - "publish": "cargo ci run-spacetime publish" + "build": "cargo spacetime build", + "generate-ts": "cargo spacetime generate --lang typescript --out-dir ts-codegen", + "publish": "cargo spacetime publish" }, "dependencies": { "spacetimedb": "workspace:^" diff --git a/modules/sdk-test-case-conversion-ts/package.json b/modules/sdk-test-case-conversion-ts/package.json index 58872ce2cdc..f18f60c3e5c 100644 --- a/modules/sdk-test-case-conversion-ts/package.json +++ b/modules/sdk-test-case-conversion-ts/package.json @@ -4,9 +4,9 @@ "description": "", "main": "index.js", "scripts": { - "build": "cargo ci run-spacetime build", - "generate-ts": "cargo ci run-spacetime generate --lang typescript --out-dir ts-codegen", - "publish": "cargo ci run-spacetime publish" + "build": "cargo spacetime build", + "generate-ts": "cargo spacetime generate --lang typescript --out-dir ts-codegen", + "publish": "cargo spacetime publish" }, "keywords": [], "author": "", diff --git a/modules/sdk-test-connect-disconnect-ts/package.json b/modules/sdk-test-connect-disconnect-ts/package.json index 604fefb5c63..10b1b1d76d6 100644 --- a/modules/sdk-test-connect-disconnect-ts/package.json +++ b/modules/sdk-test-connect-disconnect-ts/package.json @@ -4,9 +4,9 @@ "description": "", "main": "index.js", "scripts": { - "build": "cargo ci run-spacetime build", - "generate-ts": "cargo ci run-spacetime generate --lang typescript --out-dir ts-codegen", - "publish": "cargo ci run-spacetime publish" + "build": "cargo spacetime build", + "generate-ts": "cargo spacetime generate --lang typescript --out-dir ts-codegen", + "publish": "cargo spacetime publish" }, "keywords": [], "author": "", diff --git a/modules/sdk-test-procedural-view-pk-ts/package.json b/modules/sdk-test-procedural-view-pk-ts/package.json index fe8bfe1e4bf..c9ec6933973 100644 --- a/modules/sdk-test-procedural-view-pk-ts/package.json +++ b/modules/sdk-test-procedural-view-pk-ts/package.json @@ -4,9 +4,9 @@ "license": "ISC", "type": "module", "scripts": { - "build": "cargo ci run-spacetime build", - "generate-ts": "cargo ci run-spacetime generate --lang typescript --out-dir ts-codegen", - "publish": "cargo ci run-spacetime publish" + "build": "cargo spacetime build", + "generate-ts": "cargo spacetime generate --lang typescript --out-dir ts-codegen", + "publish": "cargo spacetime publish" }, "dependencies": { "spacetimedb": "workspace:^" diff --git a/modules/sdk-test-procedure-ts/package.json b/modules/sdk-test-procedure-ts/package.json index 42f060786c0..97f104e94cc 100644 --- a/modules/sdk-test-procedure-ts/package.json +++ b/modules/sdk-test-procedure-ts/package.json @@ -3,9 +3,9 @@ "license": "ISC", "type": "module", "scripts": { - "build": "cargo ci run-spacetime build", - "generate-ts": "cargo ci run-spacetime generate --lang typescript --out-dir ts-codegen", - "publish": "cargo ci run-spacetime publish" + "build": "cargo spacetime build", + "generate-ts": "cargo spacetime generate --lang typescript --out-dir ts-codegen", + "publish": "cargo spacetime publish" }, "dependencies": { "spacetimedb": "workspace:^" diff --git a/modules/sdk-test-ts/package.json b/modules/sdk-test-ts/package.json index f961418a3a8..c5ed04bbe20 100644 --- a/modules/sdk-test-ts/package.json +++ b/modules/sdk-test-ts/package.json @@ -3,9 +3,9 @@ "license": "ISC", "type": "module", "scripts": { - "build": "cargo ci run-spacetime build", - "generate-ts": "cargo ci run-spacetime generate --lang typescript --out-dir ts-codegen", - "publish": "cargo ci run-spacetime publish" + "build": "cargo spacetime build", + "generate-ts": "cargo spacetime generate --lang typescript --out-dir ts-codegen", + "publish": "cargo spacetime publish" }, "dependencies": { "spacetimedb": "workspace:^" diff --git a/modules/sdk-test-view-pk-ts/package.json b/modules/sdk-test-view-pk-ts/package.json index 51b91759342..28918205874 100644 --- a/modules/sdk-test-view-pk-ts/package.json +++ b/modules/sdk-test-view-pk-ts/package.json @@ -4,9 +4,9 @@ "license": "ISC", "type": "module", "scripts": { - "build": "cargo ci run-spacetime build", - "generate-ts": "cargo ci run-spacetime generate --lang typescript --out-dir ts-codegen", - "publish": "cargo ci run-spacetime publish" + "build": "cargo spacetime build", + "generate-ts": "cargo spacetime generate --lang typescript --out-dir ts-codegen", + "publish": "cargo spacetime publish" }, "dependencies": { "spacetimedb": "workspace:^" diff --git a/sdks/csharp/tools~/gen-quickstart.sh b/sdks/csharp/tools~/gen-quickstart.sh index 4c2a3c05fa7..834dcbcd111 100755 --- a/sdks/csharp/tools~/gen-quickstart.sh +++ b/sdks/csharp/tools~/gen-quickstart.sh @@ -68,4 +68,4 @@ if [ -n "$DOTNET_VERSION" ]; then BUILD_OPTIONS+=("--build-options=--dotnet-version $DOTNET_VERSION") fi -cargo ci run-spacetime generate -y -l csharp -o "$STDB_PATH/templates/chat-console-cs/module_bindings" --module-path "$STDB_PATH/templates/chat-console-cs/spacetimedb" "${BUILD_OPTIONS[@]}" +cargo spacetime generate -y -l csharp -o "$STDB_PATH/templates/chat-console-cs/module_bindings" --module-path "$STDB_PATH/templates/chat-console-cs/spacetimedb" "${BUILD_OPTIONS[@]}" diff --git a/sdks/csharp/tools~/gen-regression-tests.sh b/sdks/csharp/tools~/gen-regression-tests.sh index b0c4e7f4ad3..d7bd005cf45 100755 --- a/sdks/csharp/tools~/gen-regression-tests.sh +++ b/sdks/csharp/tools~/gen-regression-tests.sh @@ -83,6 +83,6 @@ if [ -n "$DOTNET_VERSION" ]; then BUILD_OPTIONS+=("--build-options=--dotnet-version $DOTNET_VERSION") fi -cargo ci run-spacetime generate -y -l csharp -o "$SDK_PATH/examples~/regression-tests/client/module_bindings" --module-path "$SDK_PATH/examples~/regression-tests/server" "${BUILD_OPTIONS[@]}" -cargo ci run-spacetime generate -y -l csharp -o "$SDK_PATH/examples~/regression-tests/republishing/client/module_bindings" --module-path "$SDK_PATH/examples~/regression-tests/republishing/server-republish" "${BUILD_OPTIONS[@]}" -cargo ci run-spacetime generate -y -l csharp -o "$SDK_PATH/examples~/regression-tests/procedure-client/module_bindings" --module-path "$STDB_PATH/modules/sdk-test-procedure" "${BUILD_OPTIONS[@]}" +cargo spacetime generate -y -l csharp -o "$SDK_PATH/examples~/regression-tests/client/module_bindings" --module-path "$SDK_PATH/examples~/regression-tests/server" "${BUILD_OPTIONS[@]}" +cargo spacetime generate -y -l csharp -o "$SDK_PATH/examples~/regression-tests/republishing/client/module_bindings" --module-path "$SDK_PATH/examples~/regression-tests/republishing/server-republish" "${BUILD_OPTIONS[@]}" +cargo spacetime generate -y -l csharp -o "$SDK_PATH/examples~/regression-tests/procedure-client/module_bindings" --module-path "$STDB_PATH/modules/sdk-test-procedure" "${BUILD_OPTIONS[@]}" diff --git a/sdks/csharp/tools~/run-regression-tests.sh b/sdks/csharp/tools~/run-regression-tests.sh index ea5cb58a779..8415f319ee7 100644 --- a/sdks/csharp/tools~/run-regression-tests.sh +++ b/sdks/csharp/tools~/run-regression-tests.sh @@ -110,13 +110,13 @@ for dotnet_version in "${DOTNET_VERSIONS[@]}"; do "$SDK_PATH/tools~/gen-regression-tests.sh" "$dotnet_version" # Publish module for btree test - cargo ci run-spacetime publish --dotnet-version "$dotnet_version" -c -y --server "$SPACETIMEDB_SERVER_URL" -p "$SDK_PATH/examples~/regression-tests/server" btree-repro + cargo spacetime publish --dotnet-version "$dotnet_version" -c -y --server "$SPACETIMEDB_SERVER_URL" -p "$SDK_PATH/examples~/regression-tests/server" btree-repro # Publish module for republishing module test - cargo ci run-spacetime publish --dotnet-version "$dotnet_version" -c -y --server "$SPACETIMEDB_SERVER_URL" -p "$SDK_PATH/examples~/regression-tests/republishing/server-initial" republish-test - cargo ci run-spacetime call --server "$SPACETIMEDB_SERVER_URL" republish-test insert 1 - cargo ci run-spacetime publish --dotnet-version "$dotnet_version" --server "$SPACETIMEDB_SERVER_URL" -p "$SDK_PATH/examples~/regression-tests/republishing/server-republish" --break-clients republish-test - cargo ci run-spacetime call --server "$SPACETIMEDB_SERVER_URL" republish-test insert 2 + cargo spacetime publish --dotnet-version "$dotnet_version" -c -y --server "$SPACETIMEDB_SERVER_URL" -p "$SDK_PATH/examples~/regression-tests/republishing/server-initial" republish-test + cargo spacetime call --server "$SPACETIMEDB_SERVER_URL" republish-test insert 1 + cargo spacetime publish --dotnet-version "$dotnet_version" --server "$SPACETIMEDB_SERVER_URL" -p "$SDK_PATH/examples~/regression-tests/republishing/server-republish" --break-clients republish-test + cargo spacetime call --server "$SPACETIMEDB_SERVER_URL" republish-test insert 2 echo "Cleanup obj~ folders generated in $SDK_PATH/examples~/regression-tests/procedure-client" # There is a bug in the code generator that creates obj~ folders in the output directory using a Rust project. @@ -124,7 +124,7 @@ for dotnet_version in "${DOTNET_VERSIONS[@]}"; do rm -rf "$SDK_PATH/examples~/regression-tests/procedure-client/module_bindings"/*/obj~ # Publish module for procedure tests - cargo ci run-spacetime publish --dotnet-version "$dotnet_version" -c -y --server "$SPACETIMEDB_SERVER_URL" -p "$STDB_PATH/modules/sdk-test-procedure" procedure-tests + cargo spacetime publish --dotnet-version "$dotnet_version" -c -y --server "$SPACETIMEDB_SERVER_URL" -p "$STDB_PATH/modules/sdk-test-procedure" procedure-tests # Run clients against the modules published with this .NET version. run_client "$SDK_PATH/examples~/regression-tests/client" "$dotnet_version" diff --git a/templates/chat-react-ts/spacetimedb/package.json b/templates/chat-react-ts/spacetimedb/package.json index 84620dae731..1662934e7a3 100644 --- a/templates/chat-react-ts/spacetimedb/package.json +++ b/templates/chat-react-ts/spacetimedb/package.json @@ -3,9 +3,9 @@ "license": "ISC", "type": "module", "scripts": { - "build": "cargo ci run-spacetime build", - "generate-ts": "cargo ci run-spacetime generate --lang typescript --out-dir ts-codegen", - "publish": "cargo ci run-spacetime publish" + "build": "cargo spacetime build", + "generate-ts": "cargo spacetime generate --lang typescript --out-dir ts-codegen", + "publish": "cargo spacetime publish" }, "dependencies": { "spacetimedb": "workspace:^" diff --git a/tools/ci/commands/module-latest-deps/src/main.rs b/tools/ci/commands/module-latest-deps/src/main.rs index 834c20b111d..f07af82da33 100644 --- a/tools/ci/commands/module-latest-deps/src/main.rs +++ b/tools/ci/commands/module-latest-deps/src/main.rs @@ -8,9 +8,9 @@ use std::{env, path::PathBuf}; /// Checks that a module builds with the latest compatible dependencies. #[derive(Parser)] struct Cli { - /// Use the release CLI already present in the Cargo target directory. + /// Do not build the CLI; use the binary selected by SPACETIME_BIN. #[arg(long)] - prebuilt_cli: bool, + no_build: bool, } fn target_dir() -> PathBuf { @@ -26,17 +26,13 @@ fn main() -> Result<()> { // Build the CLI before updating the lockfile so a newly published incompatible dependency // cannot prevent us from exercising the fresh module dependency graph. - let cli_path = if cli.prebuilt_cli { - let path = target_dir() - .join("release/spacetimedb-cli") - .with_extension(env::consts::EXE_EXTENSION); + let cli_path = if cli.no_build { + ci_common::require_spacetime_bin()? + } else { ensure!( - path.is_file(), - "--prebuilt-cli requires spacetimedb-cli at {}", - path.display() + env::var_os("SPACETIME_BIN").is_none(), + "SPACETIME_BIN requires --no-build" ); - path - } else { cmd!("cargo", "build", "-p", "spacetimedb-cli").run()?; target_dir() .join("debug/spacetimedb-cli") diff --git a/tools/ci/commands/run-spacetime/src/main.rs b/tools/ci/commands/run-spacetime/src/main.rs index f7820e664ee..8a387c18fb7 100644 --- a/tools/ci/commands/run-spacetime/src/main.rs +++ b/tools/ci/commands/run-spacetime/src/main.rs @@ -56,7 +56,7 @@ fn local_cli() -> Result { fn main() -> Result<()> { let args = env::args_os().skip(1).collect::>(); if args.is_empty() { - bail!("Usage: cargo ci run-spacetime [args...]"); + bail!("Usage: cargo spacetime [args...]"); } let cli = match env::var_os("SPACETIME_BIN") { diff --git a/tools/ci/commands/test/src/main.rs b/tools/ci/commands/test/src/main.rs index c6db37a4f64..a8b4b55fd16 100644 --- a/tools/ci/commands/test/src/main.rs +++ b/tools/ci/commands/test/src/main.rs @@ -1,5 +1,5 @@ #![allow(clippy::disallowed_macros)] -use anyhow::Result; +use anyhow::{ensure, Result}; use ci_common::pnpm; use clap::Parser; use duct::cmd; @@ -11,16 +11,21 @@ use duct::cmd; /// This expects to run in a clean git state. #[derive(Parser)] struct Cli { - /// Use release CLI and standalone binaries already present in the Cargo target directory. + /// Do not build CLI and standalone; use the binaries selected by SPACETIME_BIN. #[arg(long)] - prebuilt_runtime: bool, + no_build: bool, } fn main() -> Result<()> { let cli = Cli::parse(); - if cli.prebuilt_runtime { - ci_common::require_prebuilt_runtime()?; + if cli.no_build { + ci_common::require_runtime()?; + } else { + ensure!( + std::env::var_os("SPACETIME_BIN").is_none(), + "SPACETIME_BIN requires --no-build" + ); } pnpm(["build"]).dir("crates/bindings-typescript").run()?; @@ -61,7 +66,7 @@ fn main() -> Result<()> { .run()?; // The SDK test harness uses the same child-process server guard as smoketests, // which expects release CLI/standalone binaries to already exist. - if !cli.prebuilt_runtime { + if !cli.no_build { cmd!( "cargo", "build", diff --git a/tools/ci/commands/typescript-test/src/main.rs b/tools/ci/commands/typescript-test/src/main.rs index 3cdcef23bf2..8fc8d4ce34f 100644 --- a/tools/ci/commands/typescript-test/src/main.rs +++ b/tools/ci/commands/typescript-test/src/main.rs @@ -1,46 +1,30 @@ #![allow(clippy::disallowed_macros)] -use anyhow::{bail, Result}; +use anyhow::{bail, ensure, Result}; use ci_common::pnpm; use clap::Parser; -use duct::Expression; /// Runs TypeScript workspace tests and template build checks. #[derive(Parser)] struct Cli { - /// Use release CLI and standalone binaries already present in the Cargo target directory. + /// Do not build CLI and standalone; use the binaries selected by SPACETIME_BIN. #[arg(long)] - prebuilt_runtime: bool, -} - -fn with_runtime(command: Expression, runtime: Option<&ci_common::PrebuiltRuntime>) -> Expression { - match runtime { - Some(runtime) => command.env("SPACETIME_BIN", &runtime.cli), - None => command, - } + no_build: bool, } fn main() -> Result<()> { let cli = Cli::parse(); - let prebuilt_runtime = cli - .prebuilt_runtime - .then(ci_common::require_prebuilt_runtime) - .transpose()?; + if cli.no_build { + ci_common::require_runtime()?; + } else { + ensure!( + std::env::var_os("SPACETIME_BIN").is_none(), + "SPACETIME_BIN requires --no-build" + ); + } - with_runtime( - pnpm(["build"]).dir("crates/bindings-typescript"), - prebuilt_runtime.as_ref(), - ) - .run()?; - with_runtime( - pnpm(["test"]).dir("crates/bindings-typescript"), - prebuilt_runtime.as_ref(), - ) - .run()?; - with_runtime( - pnpm(["generate"]).dir("templates/chat-react-ts"), - prebuilt_runtime.as_ref(), - ) - .run()?; + pnpm(["build"]).dir("crates/bindings-typescript").run()?; + pnpm(["test"]).dir("crates/bindings-typescript").run()?; + pnpm(["generate"]).dir("templates/chat-react-ts").run()?; let diff_status = duct::cmd!( "bash", "tools/check-diff.sh", @@ -50,20 +34,12 @@ fn main() -> Result<()> { if !diff_status.status.success() { bail!("Bindings are dirty. Please generate bindings again and commit them to this branch."); } - with_runtime( - pnpm(["build"]).dir("templates/chat-react-ts"), - prebuilt_runtime.as_ref(), - ) - .run()?; - with_runtime( - pnpm(["-r", "--filter", "./**", "run", "build"]).dir("templates"), - prebuilt_runtime.as_ref(), - ) - .run()?; - with_runtime( - pnpm(["-r", "--filter", "./**", "run", "build"]).dir("crates/bindings-typescript"), - prebuilt_runtime.as_ref(), - ) - .run()?; + pnpm(["build"]).dir("templates/chat-react-ts").run()?; + pnpm(["-r", "--filter", "./**", "run", "build"]) + .dir("templates") + .run()?; + pnpm(["-r", "--filter", "./**", "run", "build"]) + .dir("crates/bindings-typescript") + .run()?; Ok(()) } diff --git a/tools/ci/common/src/lib.rs b/tools/ci/common/src/lib.rs index c8b293f5c9d..063383cd0ba 100644 --- a/tools/ci/common/src/lib.rs +++ b/tools/ci/common/src/lib.rs @@ -1,15 +1,10 @@ -use anyhow::{bail, ensure, Result}; +use anyhow::{bail, ensure, Context, Result}; use duct::{cmd, Expression}; use std::env; use std::ffi::OsStr; use std::path::Path; use std::path::PathBuf; -pub struct PrebuiltRuntime { - pub cli: PathBuf, - pub standalone: PathBuf, -} - pub fn ensure_repo_root() -> Result<()> { if !Path::new("Cargo.toml").exists() { bail!("You must execute this command from the SpacetimeDB repository root (where Cargo.toml is located)"); @@ -26,29 +21,34 @@ pub fn repo_root() -> PathBuf { .to_path_buf() } -pub fn require_prebuilt_runtime() -> Result { - let target_dir = env::var_os("CARGO_TARGET_DIR") +pub fn require_spacetime_bin() -> Result { + let path = env::var_os("SPACETIME_BIN") .map(PathBuf::from) - .unwrap_or_else(|| repo_root().join("target")); - let release_dir = target_dir.join("release"); - let binary_path = |name: &str| release_dir.join(name).with_extension(env::consts::EXE_EXTENSION); - let runtime = PrebuiltRuntime { - cli: binary_path("spacetimedb-cli"), - standalone: binary_path("spacetimedb-standalone"), - }; - - for (name, path) in [ - ("spacetimedb-cli", &runtime.cli), - ("spacetimedb-standalone", &runtime.standalone), - ] { - ensure!( - path.is_file(), - "--prebuilt-runtime requires {name} at {}", - path.display() - ); - } + .context("--no-build requires SPACETIME_BIN")?; + ensure!( + path.is_absolute(), + "SPACETIME_BIN must be an absolute path, got {}", + path.display() + ); + ensure!( + path.is_file(), + "SpacetimeDB CLI binary does not exist at {}", + path.display() + ); + Ok(path) +} - Ok(runtime) +pub fn require_runtime() -> Result<()> { + let cli = require_spacetime_bin()?; + let standalone = cli + .with_file_name("spacetimedb-standalone") + .with_extension(env::consts::EXE_EXTENSION); + ensure!( + standalone.is_file(), + "SpacetimeDB standalone binary does not exist beside the CLI at {}", + standalone.display() + ); + Ok(()) } pub fn pnpm(args: I) -> Expression diff --git a/tools/ci/src/main.rs b/tools/ci/src/main.rs index d44904087e2..a6592c4a6cd 100644 --- a/tools/ci/src/main.rs +++ b/tools/ci/src/main.rs @@ -80,15 +80,12 @@ const COMMANDS: &[Command] = &[ path: &["other-workflows", "watch"], package: "ci-workflow-watch", }, + Command { + path: &["other-workflows", "run-spacetime"], + package: "ci-run-spacetime", + }, ]; -// Utilities are available as explicit subcommands, but are not run by a bare -// `cargo ci` invocation. -const UTILITY_COMMANDS: &[Command] = &[Command { - path: &["run-spacetime"], - package: "ci-run-spacetime", -}]; - fn print_help() { println!("Usage: cargo ci [--skip ...]"); println!(" cargo ci [ARGS]..."); @@ -97,17 +94,11 @@ fn print_help() { for command in COMMANDS { println!(" {}", command.path.join(" ")); } - println!(); - println!("Utilities:"); - for command in UTILITY_COMMANDS { - println!(" {}", command.path.join(" ")); - } } fn command_for(args: &[String]) -> Option<(&'static Command, usize)> { COMMANDS .iter() - .chain(UTILITY_COMMANDS) .filter_map(|command| { args.get(..command.path.len()) .is_some_and(|head| head.iter().map(String::as_str).eq(command.path.iter().copied())) diff --git a/tools/gen-bindings/src/main.rs b/tools/gen-bindings/src/main.rs index 8cdb5f15a03..c5cbcf665d2 100644 --- a/tools/gen-bindings/src/main.rs +++ b/tools/gen-bindings/src/main.rs @@ -55,8 +55,7 @@ fn main() -> Result<()> { run_inherit( "cargo", &[ - "ci", - "run-spacetime", + "spacetime", "generate", "-y", "--lang", From af34681d9a9c85856d2c59aae5cfcef5ed5d3cb9 Mon Sep 17 00:00:00 2001 From: Zeke Foppa Date: Wed, 26 Aug 2026 13:05:44 -0700 Subject: [PATCH 50/50] [bfops/test-runner]: bump CI