Build all of the typescript examples in CI #16239
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| on: | |
| pull_request: | |
| push: | |
| branches: | |
| - master | |
| merge_group: | |
| workflow_dispatch: | |
| inputs: | |
| pr_number: | |
| description: "Pull Request Number" | |
| required: false | |
| default: "" | |
| name: CI | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.event.inputs.pr_number || format('sha-{0}', github.sha) }} | |
| cancel-in-progress: true | |
| jobs: | |
| docker_smoketests: | |
| needs: [lints, llm_ci_check] | |
| name: Smoketests | |
| strategy: | |
| matrix: | |
| runner: [spacetimedb-new-runner, windows-latest] | |
| include: | |
| - runner: spacetimedb-new-runner | |
| smoketest_args: --docker | |
| container: | |
| image: localhost:5000/spacetimedb-ci:latest | |
| options: --privileged | |
| - runner: windows-latest | |
| smoketest_args: --no-build-cli | |
| container: null | |
| runs-on: ${{ matrix.runner }} | |
| container: ${{ matrix.container }} | |
| timeout-minutes: 120 | |
| env: | |
| CARGO_TARGET_DIR: ${{ github.workspace }}/target | |
| 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: Cache Rust dependencies | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| workspaces: ${{ github.workspace }} | |
| shared-key: spacetimedb | |
| cache-on-failure: false | |
| cache-all-crates: true | |
| cache-workspace-crates: true | |
| prefix-key: v1 | |
| - uses: actions/setup-dotnet@v4 | |
| with: | |
| global-json-file: global.json | |
| # nodejs and pnpm are required for the typescript quickstart smoketest | |
| - name: Set up Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 18 | |
| - uses: pnpm/action-setup@v4 | |
| with: | |
| run_install: true | |
| - name: Install psql (Windows) | |
| if: runner.os == 'Windows' | |
| run: choco install psql -y --no-progress | |
| shell: powershell | |
| - name: Build crates | |
| run: cargo build -p spacetimedb-cli -p spacetimedb-standalone -p spacetimedb-update | |
| - name: Start Docker daemon | |
| if: runner.os == 'Linux' | |
| run: /usr/local/bin/start-docker.sh | |
| - name: Build and start database (Linux) | |
| if: runner.os == 'Linux' | |
| run: | | |
| # Our .dockerignore omits `target`, which our CI Dockerfile needs. | |
| rm .dockerignore | |
| docker compose -f .github/docker-compose.yml up -d | |
| - name: Build and start database (Windows) | |
| if: runner.os == 'Windows' | |
| run: | | |
| # Fail properly if any individual command fails | |
| $ErrorActionPreference = 'Stop' | |
| $PSNativeCommandUseErrorActionPreference = $true | |
| Start-Process target/debug/spacetimedb-cli.exe -ArgumentList 'start --pg-port 5432' | |
| 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 | |
| - uses: actions/setup-python@v5 | |
| with: { python-version: "3.12" } | |
| if: runner.os == 'Windows' | |
| - name: Install python deps | |
| run: python -m pip install -r smoketests/requirements.txt | |
| - name: Run smoketests | |
| # Note: clear_database and replication only work in private | |
| run: cargo ci smoketests -- ${{ matrix.smoketest_args }} -x clear_database replication teams | |
| - name: Stop containers (Linux) | |
| if: always() && runner.os == 'Linux' | |
| run: docker compose -f .github/docker-compose.yml down | |
| test: | |
| needs: [lints, llm_ci_check] | |
| name: Test Suite | |
| runs-on: spacetimedb-new-runner | |
| container: | |
| image: localhost:5000/spacetimedb-ci:latest | |
| options: >- | |
| --privileged | |
| env: | |
| CARGO_TARGET_DIR: ${{ github.workspace }}/target | |
| 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: Cache Rust dependencies | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| workspaces: ${{ github.workspace }} | |
| shared-key: spacetimedb | |
| # Let the smoketests job save the cache since it builds the most things | |
| save-if: false | |
| prefix-key: v1 | |
| - uses: actions/setup-dotnet@v3 | |
| with: | |
| global-json-file: global.json | |
| - name: Set up Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 18 | |
| - uses: pnpm/action-setup@v4 | |
| with: | |
| run_install: true | |
| - name: Build typescript module sdk | |
| working-directory: crates/bindings-typescript | |
| run: pnpm build | |
| - name: Run tests | |
| run: cargo ci test | |
| lints: | |
| name: Lints | |
| runs-on: spacetimedb-new-runner | |
| container: | |
| image: localhost:5000/spacetimedb-ci:latest | |
| options: >- | |
| --privileged | |
| env: | |
| CARGO_TARGET_DIR: ${{ github.workspace }}/target | |
| steps: | |
| - name: Checkout sources | |
| uses: actions/checkout@v3 | |
| - uses: dsherret/rust-toolchain-file@v1 | |
| - run: echo ::add-matcher::.github/workflows/rust_matcher.json | |
| - name: Cache Rust dependencies | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| workspaces: ${{ github.workspace }} | |
| shared-key: spacetimedb | |
| # Let the smoketests job save the cache since it builds the most things | |
| save-if: false | |
| prefix-key: v1 | |
| - uses: actions/setup-dotnet@v3 | |
| with: | |
| global-json-file: global.json | |
| - name: Run ci lint | |
| run: cargo ci lint | |
| wasm_bindings: | |
| name: Build and test wasm bindings | |
| runs-on: spacetimedb-new-runner | |
| container: | |
| image: localhost:5000/spacetimedb-ci:latest | |
| options: >- | |
| --privileged | |
| env: | |
| CARGO_TARGET_DIR: ${{ github.workspace }}/target | |
| steps: | |
| - uses: actions/checkout@v3 | |
| - uses: dsherret/rust-toolchain-file@v1 | |
| - run: echo ::add-matcher::.github/workflows/rust_matcher.json | |
| - name: Cache Rust dependencies | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| workspaces: ${{ github.workspace }} | |
| shared-key: spacetimedb | |
| # Let the smoketests job save the cache since it builds the most things | |
| save-if: false | |
| prefix-key: v1 | |
| - name: Run bindgen tests | |
| run: cargo ci wasm-bindings | |
| publish_checks: | |
| name: Check that packages are publishable | |
| runs-on: spacetimedb-new-runner | |
| container: | |
| image: localhost:5000/spacetimedb-ci:latest | |
| options: >- | |
| --privileged | |
| permissions: read-all | |
| steps: | |
| - uses: actions/checkout@v3 | |
| - name: Set up Python env | |
| run: | | |
| test -d venv || python3 -m venv venv | |
| venv/bin/pip3 install argparse toml | |
| - name: Run checks | |
| run: | | |
| set -ueo pipefail | |
| FAILED=0 | |
| ROOTS=(spacetimedb spacetimedb-sdk) | |
| CRATES=$(venv/bin/python3 tools/find-publish-list.py --recursive --directories --quiet "${ROOTS[@]}") | |
| for crate_dir in $CRATES; do | |
| if ! venv/bin/python3 tools/crate-publish-checks.py "${crate_dir}"; then | |
| FAILED=$(( $FAILED + 1 )) | |
| fi | |
| done | |
| if [ $FAILED -gt 0 ]; then | |
| exit 1 | |
| fi | |
| update: | |
| name: Test spacetimedb-update flow (${{ matrix.target }}) | |
| permissions: read-all | |
| strategy: | |
| matrix: | |
| include: | |
| - runner: spacetimedb-new-runner | |
| target: x86_64-unknown-linux-gnu | |
| container: | |
| image: localhost:5000/spacetimedb-ci:latest | |
| options: --privileged | |
| - { target: aarch64-unknown-linux-gnu, runner: arm-runner } | |
| - { target: aarch64-apple-darwin, runner: macos-latest } | |
| - { target: x86_64-pc-windows-msvc, runner: windows-latest } | |
| runs-on: ${{ matrix.runner }} | |
| container: ${{ matrix.container }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v3 | |
| - name: Install Rust | |
| uses: dsherret/rust-toolchain-file@v1 | |
| - name: Install rust target | |
| run: rustup target add ${{ matrix.target }} | |
| - name: Install packages | |
| if: ${{ matrix.runner == 'arm-runner' }} | |
| shell: bash | |
| run: sudo apt install -y libssl-dev | |
| - name: Build spacetimedb-update | |
| run: cargo build --features github-token-auth --target ${{ matrix.target }} -p spacetimedb-update | |
| if: runner.os == 'Windows' | |
| - name: Run self-install | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| shell: bash | |
| run: | | |
| ROOT_DIR="$(mktemp -d)" | |
| # NOTE(bfops): We need the `github-token-auth` feature because we otherwise tend to get ratelimited when we try to fetch `/releases/latest`. | |
| # My best guess is that, on the GitHub runners, the "anonymous" ratelimit is shared by *all* users of that runner (I think this because it | |
| # happens very frequently on the `macos-runner`, but we haven't seen it on any others). | |
| cargo run --features github-token-auth --target ${{ matrix.target }} -p spacetimedb-update -- self-install --root-dir="${ROOT_DIR}" --yes | |
| "${ROOT_DIR}"/spacetime --root-dir="${ROOT_DIR}" help | |
| if: runner.os == 'Windows' | |
| - name: Test spacetimedb-update | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: cargo ci update-flow --target=${{ matrix.target }} --github-token-auth | |
| if: runner.os != 'Windows' | |
| 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 | |
| # 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 | |
| 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: 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 | |
| ' | |
| ci_command_docs: | |
| name: Check CI command docs | |
| runs-on: ubuntu-latest | |
| 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: Check for docs change | |
| run: cargo ci self-docs --check | |
| cli_docs: | |
| name: Check CLI docs | |
| permissions: read-all | |
| runs-on: spacetimedb-new-runner | |
| container: | |
| image: localhost:5000/spacetimedb-ci:latest | |
| options: >- | |
| --privileged | |
| env: | |
| CARGO_TARGET_DIR: ${{ github.workspace }}/target | |
| 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: 18 | |
| - uses: pnpm/action-setup@v4 | |
| with: | |
| run_install: true | |
| - name: Get pnpm store directory | |
| shell: bash | |
| run: | | |
| echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV | |
| - uses: actions/cache@v4 | |
| name: Setup pnpm cache | |
| with: | |
| path: ${{ env.STORE_PATH }} | |
| key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} | |
| restore-keys: | | |
| ${{ runner.os }}-pnpm-store- | |
| - uses: dsherret/rust-toolchain-file@v1 | |
| - name: Cache Rust dependencies | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| workspaces: ${{ github.workspace }} | |
| shared-key: spacetimedb | |
| # Let the smoketests job save the cache since it builds the most things | |
| save-if: false | |
| prefix-key: v1 | |
| - name: Check for docs change | |
| run: | | |
| cargo ci cli-docs | |
| llm_ci_check: | |
| name: Verify LLM benchmark is up to date | |
| permissions: | |
| contents: read | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: Swatinem/rust-cache@v2 | |
| - name: Run hash check (both langs) | |
| run: cargo llm ci-check | |
| unity-testsuite: | |
| needs: [lints, llm_ci_check] | |
| # Skip if this is an external contribution. | |
| # The license secrets will be empty, so the step would fail anyway. | |
| if: ${{ github.event_name != 'pull_request' || !github.event.pull_request.head.repo.fork }} | |
| permissions: | |
| contents: read | |
| checks: write | |
| runs-on: spacetimedb-new-runner | |
| container: | |
| image: localhost:5000/spacetimedb-ci:latest | |
| options: >- | |
| --privileged | |
| --cgroupns=host | |
| timeout-minutes: 30 | |
| env: | |
| CARGO_TARGET_DIR: ${{ github.workspace }}/target | |
| steps: | |
| - name: Checkout repository | |
| id: checkout-stdb | |
| uses: actions/checkout@v4 | |
| # 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 ../.. | |
| # 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: Cache Rust dependencies | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| workspaces: ${{ github.workspace }} | |
| shared-key: spacetimedb | |
| # Let the main CI job save the cache since it builds the most things | |
| save-if: false | |
| prefix-key: v1 | |
| - name: Install SpacetimeDB CLI from the local checkout | |
| run: | | |
| 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: 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: | | |
| # Replace the com.clockworklabs.spacetimedbsdk dependency with the current branch. | |
| # Note: Pointing to a local directory does not work, because our earlier steps nuke our meta files, which then causes Unity to not properly respect the DLLs (e.g. | |
| # codegen does not work properly). | |
| yq e -i '.dependencies["com.clockworklabs.spacetimedbsdk"] = "https://github.com/clockworklabs/SpacetimeDB.git?path=sdks/csharp#${{ github.head_ref }}"' manifest.json | |
| cat manifest.json | |
| - uses: actions/cache@v3 | |
| with: | |
| path: demo/Blackholio/client-unity/Library | |
| key: Unity-${{ github.head_ref }} | |
| restore-keys: Unity- | |
| # We need this to support "Docker in Docker" | |
| - name: Start Docker daemon | |
| run: /usr/local/bin/start-docker.sh | |
| - name: Run Unity tests | |
| uses: game-ci/unity-test-runner@v4 | |
| with: | |
| unityVersion: 2022.3.32f1 # Adjust Unity version to a valid tag | |
| 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 }} | |
| csharp-testsuite: | |
| needs: [lints, llm_ci_check] | |
| runs-on: spacetimedb-new-runner | |
| container: | |
| image: localhost:5000/spacetimedb-ci:latest | |
| options: >- | |
| --privileged | |
| --cgroupns=host | |
| timeout-minutes: 30 | |
| env: | |
| CARGO_TARGET_DIR: ${{ github.workspace }}/target | |
| steps: | |
| - name: Checkout repository | |
| id: checkout-stdb | |
| uses: actions/checkout@v4 | |
| # 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: Run .NET tests | |
| working-directory: sdks/csharp | |
| run: dotnet test -warnaserror | |
| - 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: Cache Rust dependencies | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| workspaces: ${{ github.workspace }} | |
| shared-key: spacetimedb | |
| # Let the main CI job save the cache since it builds the most things | |
| save-if: false | |
| prefix-key: v1 | |
| - name: Install SpacetimeDB CLI from the local checkout | |
| run: | | |
| 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 | |
| # This step shouldn't be needed, but somehow we end up with caches that are missing librusty_v8.a. | |
| # ChatGPT suspects that this could be due to different build invocations using the same target dir, | |
| # and this makes sense to me because we only see it in this job where we mix `cargo build -p` with | |
| # `cargo build --manifest-path` (which apparently build different dependency trees). | |
| # However, we've been unable to fix it so... /shrug | |
| - name: Check v8 outputs | |
| run: | | |
| find "${CARGO_TARGET_DIR}"/ -type f | grep '[/_]v8' || true | |
| if ! [ -f "${CARGO_TARGET_DIR}"/debug/gn_out/obj/librusty_v8.a ]; then | |
| echo "Could not find v8 output file librusty_v8.a; rebuilding manually." | |
| cargo clean -p v8 || true | |
| cargo build -p v8 | |
| fi | |
| - name: Check quickstart-chat bindings are up to date | |
| working-directory: sdks/csharp | |
| run: | | |
| bash tools~/gen-quickstart.sh | |
| "${GITHUB_WORKSPACE}"/tools/check-diff.sh examples~/quickstart-chat || { | |
| echo 'Error: quickstart-chat bindings have changed. Please run `sdks/csharp/tools~/gen-quickstart.sh`.' | |
| exit 1 | |
| } | |
| - 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 | |
| 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 | |
| } | |
| internal-tests: | |
| name: Internal Tests | |
| needs: [lints, llm_ci_check] | |
| # 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) }} | |
| permissions: | |
| contents: read | |
| runs-on: ubuntu-latest | |
| env: | |
| TARGET_OWNER: clockworklabs | |
| TARGET_REPO: SpacetimeDBPrivate | |
| steps: | |
| - id: dispatch | |
| name: Trigger tests | |
| uses: actions/github-script@v7 | |
| with: | |
| github-token: ${{ secrets.SPACETIMEDB_PRIVATE_TOKEN }} | |
| script: | | |
| const workflowId = 'ci.yml'; | |
| const targetRef = 'master'; | |
| const targetOwner = process.env.TARGET_OWNER; | |
| const targetRepo = process.env.TARGET_REPO; | |
| // Use the ref for pull requests because the head sha is brittle (github does some extra dance where it merges in master). | |
| const publicRef = (context.eventName === 'pull_request') ? context.payload.pull_request.head.ref : context.sha; | |
| const preDispatch = new Date().toISOString(); | |
| // Dispatch the workflow in the target repository | |
| await github.rest.actions.createWorkflowDispatch({ | |
| owner: targetOwner, | |
| repo: targetRepo, | |
| workflow_id: workflowId, | |
| ref: targetRef, | |
| inputs: { public_ref: publicRef } | |
| }); | |
| const sleep = (ms) => new Promise(r => setTimeout(r, ms)); | |
| // Find the dispatched run by name | |
| let runId = null; | |
| for (let attempt = 0; attempt < 20 && !runId; attempt++) { // up to ~10 minutes to locate the run | |
| await sleep(5000); | |
| const runsResp = await github.rest.actions.listWorkflowRuns({ | |
| owner: targetOwner, | |
| repo: targetRepo, | |
| workflow_id: workflowId, | |
| event: 'workflow_dispatch', | |
| branch: targetRef, | |
| per_page: 50, | |
| }); | |
| const expectedName = `CI [public_ref=${publicRef}]`; | |
| const candidates = runsResp.data.workflow_runs | |
| .filter(r => r.name === expectedName && new Date(r.created_at) >= new Date(preDispatch)) | |
| .sort((a, b) => new Date(b.created_at) - new Date(a.created_at)); | |
| if (candidates.length > 0) { | |
| runId = candidates[0].id; | |
| break; | |
| } | |
| } | |
| if (!runId) { | |
| core.setFailed('Failed to locate dispatched run in the private repository.'); | |
| return; | |
| } | |
| const runUrl = `https://github.com/${targetOwner}/${targetRepo}/actions/runs/${runId}`; | |
| core.info(`View run: ${runUrl}`); | |
| core.setOutput('run_id', String(runId)); | |
| core.setOutput('run_url', runUrl); | |
| - name: Wait for Internal Tests to complete | |
| 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 }}`); | |
| const runUrl = `${{ steps.dispatch.outputs.run_url }}`; | |
| const sleep = (ms) => new Promise(r => setTimeout(r, ms)); | |
| core.info(`Waiting for workflow result... ${runUrl}`); | |
| let conclusion = null; | |
| for (let attempt = 0; attempt < 240; attempt++) { // up to ~2 hours | |
| const runResp = await github.rest.actions.getWorkflowRun({ | |
| owner: targetOwner, | |
| repo: targetRepo, | |
| run_id: runId | |
| }); | |
| const { status, conclusion: c } = runResp.data; | |
| if (status === 'completed') { | |
| conclusion = c || 'success'; | |
| break; | |
| } | |
| await sleep(30000); | |
| } | |
| if (!conclusion) { | |
| core.setFailed('Timed out waiting for private workflow to complete.'); | |
| return; | |
| } | |
| if (conclusion !== 'success') { | |
| core.setFailed(`Private workflow failed with conclusion: ${conclusion}`); | |
| } | |
| - name: Cancel invoked run if workflow cancelled | |
| if: ${{ cancelled() }} | |
| 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, | |
| }); |