diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0032331c269..735ab8f62ee 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -619,31 +619,7 @@ jobs: 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 @@ -681,19 +657,8 @@ jobs: # 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 ci dlls + - name: Prepare Unity test workspace + run: cargo ci unity-tests - name: Check Unity meta files uses: DeNA/unity-meta-check@v3 @@ -703,23 +668,6 @@ jobs: 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 - - uses: actions/cache@v3 with: path: demo/Blackholio/client-unity/Library @@ -764,32 +712,6 @@ jobs: 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 - - - name: Run .NET tests - working-directory: sdks/csharp - run: dotnet test -warnaserror --no-restore - - - 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 @@ -833,15 +755,6 @@ jobs: # 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 - 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 - } - # 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 @@ -852,18 +765,8 @@ jobs: # 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 - } + - name: Run C# tests + run: cargo ci csharp-tests internal-tests: name: Internal Tests diff --git a/tools/ci/README.md b/tools/ci/README.md index dbe452243f0..c8650ffc1a2 100644 --- a/tools/ci/README.md +++ b/tools/ci/README.md @@ -228,6 +228,28 @@ Usage: docs - `--help`: Print help +### `csharp-tests` + +**Usage:** +```bash +Usage: csharp-tests +``` + +**Options:** + +- `--help`: Print help + +### `unity-tests` + +**Usage:** +```bash +Usage: unity-tests +``` + +**Options:** + +- `--help`: Print help + ### `help` **Usage:** diff --git a/tools/ci/src/main.rs b/tools/ci/src/main.rs index 3c31c366324..e4fd7c971c3 100644 --- a/tools/ci/src/main.rs +++ b/tools/ci/src/main.rs @@ -1,8 +1,9 @@ #![allow(clippy::disallowed_macros)] -use anyhow::{bail, Result}; +use anyhow::{bail, ensure, Result}; use clap::{CommandFactory, Parser, Subcommand}; use duct::cmd; +use regex::Regex; use std::ffi::OsStr; use std::ffi::OsString; use std::path::Path; @@ -278,6 +279,10 @@ enum CiCmd { TypescriptTest, /// Builds the docs site. Docs, + /// Runs the C# SDK test suite and binding checks. + CsharpTests, + /// Prepares the Unity test workspace and publishes the local test module. + UnityTests, } fn run_all_clap_subcommands(skips: &[String]) -> Result<()> { @@ -443,6 +448,132 @@ fn run_docs_build() -> Result<()> { Ok(()) } +fn prepare_csharp_sdk_solution() -> Result<()> { + cmd!( + "dotnet", + "pack", + "crates/bindings-csharp/BSATN.Runtime", + "-c", + "Release" + ) + .run()?; + cmd!("dotnet", "pack", "crates/bindings-csharp/Runtime", "-c", "Release").run()?; + cmd!("bash", "./tools~/write-nuget-config.sh", "../..") + .dir("sdks/csharp") + .run()?; + cmd!( + "dotnet", + "restore", + "--configfile", + "NuGet.Config", + "SpacetimeDB.ClientSDK.sln" + ) + .dir("sdks/csharp") + .run()?; + Ok(()) +} + +fn run_local_spacetime_script(script_name: &str, body: &str) -> Result<()> { + let script = format!( + r#"set -euo pipefail +spacetime start >"/tmp/{script_name}.log" 2>&1 & +STDB_PID=$! +trap 'kill "$STDB_PID" >/dev/null 2>&1 || true' EXIT +sleep 3 +{body} +"# + ); + cmd!("bash", "-lc", &script).run()?; + Ok(()) +} + +fn run_csharp_tests() -> Result<()> { + prepare_csharp_sdk_solution()?; + + cmd!("dotnet", "test", "-warnaserror", "--no-restore") + .dir("sdks/csharp") + .run()?; + cmd!( + "dotnet", + "format", + "--no-restore", + "--verify-no-changes", + "SpacetimeDB.ClientSDK.sln" + ) + .dir("sdks/csharp") + .run()?; + + cmd!("bash", "tools~/gen-quickstart.sh").dir("sdks/csharp").run()?; + let diff_status = cmd!("bash", "tools/check-diff.sh", "sdks/csharp/examples~/quickstart-chat").run()?; + if !diff_status.status.success() { + bail!("quickstart-chat bindings have changed. Please run `sdks/csharp/tools~/gen-quickstart.sh`."); + } + + run_local_spacetime_script( + "spacetimedb-csharp-tests", + r#"bash sdks/csharp/tools~/run-regression-tests.sh"#, + )?; + let diff_status = cmd!("bash", "tools/check-diff.sh", "sdks/csharp/examples~/regression-tests").run()?; + if !diff_status.status.success() { + bail!("Bindings are dirty. Please run `sdks/csharp/tools~/gen-regression-tests.sh`."); + } + + Ok(()) +} + +fn patch_blackholio_server_dependency() -> Result<()> { + let cargo_toml_path = Path::new("demo/Blackholio/server-rust/Cargo.toml"); + let existing = fs::read_to_string(cargo_toml_path)?; + let dependency_line = Regex::new(r#"(?m)^spacetimedb\s*=.*$"#)?; + let updated = dependency_line.replace(&existing, r#"spacetimedb = { path = "../../../crates/bindings" }"#); + + ensure!( + updated.as_ref() != existing, + "Failed to patch demo/Blackholio/server-rust/Cargo.toml with local spacetimedb dependency" + ); + + fs::write(cargo_toml_path, updated.as_ref())?; + Ok(()) +} + +fn run_unity_tests() -> Result<()> { + prepare_csharp_sdk_solution()?; + patch_blackholio_server_dependency()?; + + cmd!("bash", "./generate.sh", "-y") + .dir("demo/Blackholio/server-rust") + .run()?; + let diff_status = cmd!( + "bash", + "tools/check-diff.sh", + "demo/Blackholio/client-unity/Assets/Scripts/autogen", + ) + .run()?; + if !diff_status.status.success() { + bail!("Bindings are dirty. Please run `demo/Blackholio/server-rust/generate.sh`."); + } + + run_dlls()?; + + run_local_spacetime_script( + "spacetimedb-unity-tests", + r#"spacetime logout && spacetime login --server-issued-login local +cd demo/Blackholio/server-rust +bash ./publish.sh"#, + )?; + + cmd!( + "bash", + "-lc", + r#"cd demo/Blackholio/client-unity/Packages +yq e -i '.dependencies["com.clockworklabs.spacetimedbsdk"] = "file:../../../../sdks/csharp"' manifest.json +cat manifest.json"# + ) + .run()?; + + Ok(()) +} + fn main() -> Result<()> { env_logger::init(); @@ -715,6 +846,14 @@ fn main() -> Result<()> { run_docs_build()?; } + Some(CiCmd::CsharpTests) => { + run_csharp_tests()?; + } + + Some(CiCmd::UnityTests) => { + run_unity_tests()?; + } + None => run_all_clap_subcommands(&cli.skip)?, }