diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3847660c2b8..01d9b732c09 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1180,3 +1180,57 @@ jobs: fi echo "No Python smoketest changes detected." + + smoketests_mod_rs_complete: + name: Check smoketests/mod.rs is complete + runs-on: ubuntu-latest + 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: Set default rust toolchain + run: rustup default $(rustup show active-toolchain | cut -d' ' -f1) + - 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 + + # 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 + shell: bash + 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: Verify crates/smoketests/tests/smoketests/mod.rs lists all entries + run: | + cargo ci smoketests check-mod-list diff --git a/crates/smoketests/tests/integration.rs b/crates/smoketests/tests/integration.rs new file mode 100644 index 00000000000..dd50b65bb8b --- /dev/null +++ b/crates/smoketests/tests/integration.rs @@ -0,0 +1,2 @@ +// Single test binary entry point - includes all smoketests +mod smoketests; diff --git a/crates/smoketests/tests/mod.rs b/crates/smoketests/tests/mod.rs deleted file mode 100644 index 358436c0ea1..00000000000 --- a/crates/smoketests/tests/mod.rs +++ /dev/null @@ -1,36 +0,0 @@ -// All smoketest modules -pub mod add_remove_index; -pub mod auto_inc; -pub mod auto_migration; -pub mod call; -pub mod cli; -pub mod client_connection_errors; -pub mod confirmed_reads; -pub mod connect_disconnect_from_cli; -pub mod create_project; -pub mod csharp_module; -pub mod default_module_clippy; -pub mod delete_database; -pub mod describe; -pub mod detect_wasm_bindgen; -pub mod dml; -pub mod domains; -pub mod energy; -pub mod fail_initial_publish; -pub mod filtering; -pub mod http_egress; -pub mod module_nested_op; -pub mod modules; -pub mod namespaces; -pub mod new_user_flow; -pub mod panic; -pub mod permissions; -pub mod pg_wire; -pub mod quickstart; -pub mod restart; -pub mod rls; -pub mod schedule_reducer; -pub mod servers; -pub mod sql; -pub mod timestamp_route; -pub mod views; diff --git a/crates/smoketests/tests/add_remove_index.rs b/crates/smoketests/tests/smoketests/add_remove_index.rs similarity index 100% rename from crates/smoketests/tests/add_remove_index.rs rename to crates/smoketests/tests/smoketests/add_remove_index.rs diff --git a/crates/smoketests/tests/auto_inc.rs b/crates/smoketests/tests/smoketests/auto_inc.rs similarity index 100% rename from crates/smoketests/tests/auto_inc.rs rename to crates/smoketests/tests/smoketests/auto_inc.rs diff --git a/crates/smoketests/tests/auto_migration.rs b/crates/smoketests/tests/smoketests/auto_migration.rs similarity index 100% rename from crates/smoketests/tests/auto_migration.rs rename to crates/smoketests/tests/smoketests/auto_migration.rs diff --git a/crates/smoketests/tests/call.rs b/crates/smoketests/tests/smoketests/call.rs similarity index 100% rename from crates/smoketests/tests/call.rs rename to crates/smoketests/tests/smoketests/call.rs diff --git a/crates/smoketests/tests/cli/dev.rs b/crates/smoketests/tests/smoketests/cli/dev.rs similarity index 100% rename from crates/smoketests/tests/cli/dev.rs rename to crates/smoketests/tests/smoketests/cli/dev.rs diff --git a/crates/smoketests/tests/cli/generate.rs b/crates/smoketests/tests/smoketests/cli/generate.rs similarity index 100% rename from crates/smoketests/tests/cli/generate.rs rename to crates/smoketests/tests/smoketests/cli/generate.rs diff --git a/crates/smoketests/tests/cli/mod.rs b/crates/smoketests/tests/smoketests/cli/mod.rs similarity index 100% rename from crates/smoketests/tests/cli/mod.rs rename to crates/smoketests/tests/smoketests/cli/mod.rs diff --git a/crates/smoketests/tests/cli/publish.rs b/crates/smoketests/tests/smoketests/cli/publish.rs similarity index 100% rename from crates/smoketests/tests/cli/publish.rs rename to crates/smoketests/tests/smoketests/cli/publish.rs diff --git a/crates/smoketests/tests/cli/server.rs b/crates/smoketests/tests/smoketests/cli/server.rs similarity index 100% rename from crates/smoketests/tests/cli/server.rs rename to crates/smoketests/tests/smoketests/cli/server.rs diff --git a/crates/smoketests/tests/client_connection_errors.rs b/crates/smoketests/tests/smoketests/client_connection_errors.rs similarity index 100% rename from crates/smoketests/tests/client_connection_errors.rs rename to crates/smoketests/tests/smoketests/client_connection_errors.rs diff --git a/crates/smoketests/tests/confirmed_reads.rs b/crates/smoketests/tests/smoketests/confirmed_reads.rs similarity index 100% rename from crates/smoketests/tests/confirmed_reads.rs rename to crates/smoketests/tests/smoketests/confirmed_reads.rs diff --git a/crates/smoketests/tests/connect_disconnect_from_cli.rs b/crates/smoketests/tests/smoketests/connect_disconnect_from_cli.rs similarity index 100% rename from crates/smoketests/tests/connect_disconnect_from_cli.rs rename to crates/smoketests/tests/smoketests/connect_disconnect_from_cli.rs diff --git a/crates/smoketests/tests/create_project.rs b/crates/smoketests/tests/smoketests/create_project.rs similarity index 100% rename from crates/smoketests/tests/create_project.rs rename to crates/smoketests/tests/smoketests/create_project.rs diff --git a/crates/smoketests/tests/csharp_module.rs b/crates/smoketests/tests/smoketests/csharp_module.rs similarity index 100% rename from crates/smoketests/tests/csharp_module.rs rename to crates/smoketests/tests/smoketests/csharp_module.rs diff --git a/crates/smoketests/tests/default_module_clippy.rs b/crates/smoketests/tests/smoketests/default_module_clippy.rs similarity index 100% rename from crates/smoketests/tests/default_module_clippy.rs rename to crates/smoketests/tests/smoketests/default_module_clippy.rs diff --git a/crates/smoketests/tests/delete_database.rs b/crates/smoketests/tests/smoketests/delete_database.rs similarity index 100% rename from crates/smoketests/tests/delete_database.rs rename to crates/smoketests/tests/smoketests/delete_database.rs diff --git a/crates/smoketests/tests/describe.rs b/crates/smoketests/tests/smoketests/describe.rs similarity index 100% rename from crates/smoketests/tests/describe.rs rename to crates/smoketests/tests/smoketests/describe.rs diff --git a/crates/smoketests/tests/detect_wasm_bindgen.rs b/crates/smoketests/tests/smoketests/detect_wasm_bindgen.rs similarity index 100% rename from crates/smoketests/tests/detect_wasm_bindgen.rs rename to crates/smoketests/tests/smoketests/detect_wasm_bindgen.rs diff --git a/crates/smoketests/tests/dml.rs b/crates/smoketests/tests/smoketests/dml.rs similarity index 100% rename from crates/smoketests/tests/dml.rs rename to crates/smoketests/tests/smoketests/dml.rs diff --git a/crates/smoketests/tests/domains.rs b/crates/smoketests/tests/smoketests/domains.rs similarity index 100% rename from crates/smoketests/tests/domains.rs rename to crates/smoketests/tests/smoketests/domains.rs diff --git a/crates/smoketests/tests/energy.rs b/crates/smoketests/tests/smoketests/energy.rs similarity index 100% rename from crates/smoketests/tests/energy.rs rename to crates/smoketests/tests/smoketests/energy.rs diff --git a/crates/smoketests/tests/fail_initial_publish.rs b/crates/smoketests/tests/smoketests/fail_initial_publish.rs similarity index 100% rename from crates/smoketests/tests/fail_initial_publish.rs rename to crates/smoketests/tests/smoketests/fail_initial_publish.rs diff --git a/crates/smoketests/tests/filtering.rs b/crates/smoketests/tests/smoketests/filtering.rs similarity index 100% rename from crates/smoketests/tests/filtering.rs rename to crates/smoketests/tests/smoketests/filtering.rs diff --git a/crates/smoketests/tests/http_egress.rs b/crates/smoketests/tests/smoketests/http_egress.rs similarity index 100% rename from crates/smoketests/tests/http_egress.rs rename to crates/smoketests/tests/smoketests/http_egress.rs diff --git a/crates/smoketests/tests/smoketests/mod.rs b/crates/smoketests/tests/smoketests/mod.rs new file mode 100644 index 00000000000..ab815c5fa4b --- /dev/null +++ b/crates/smoketests/tests/smoketests/mod.rs @@ -0,0 +1,37 @@ +// All smoketest modules +mod add_remove_index; +mod auto_inc; +mod auto_migration; +mod call; +mod cli; +mod client_connection_errors; +mod confirmed_reads; +mod connect_disconnect_from_cli; +mod create_project; +mod csharp_module; +mod default_module_clippy; +mod delete_database; +mod describe; +mod detect_wasm_bindgen; +mod dml; +mod domains; +mod energy; +mod fail_initial_publish; +mod filtering; +mod http_egress; +mod module_nested_op; +mod modules; +mod namespaces; +mod new_user_flow; +mod panic; +mod permissions; +mod pg_wire; +mod publish_upgrade_prompt; +mod quickstart; +mod restart; +mod rls; +mod schedule_reducer; +mod servers; +mod sql; +mod timestamp_route; +mod views; diff --git a/crates/smoketests/tests/module_nested_op.rs b/crates/smoketests/tests/smoketests/module_nested_op.rs similarity index 100% rename from crates/smoketests/tests/module_nested_op.rs rename to crates/smoketests/tests/smoketests/module_nested_op.rs diff --git a/crates/smoketests/tests/modules.rs b/crates/smoketests/tests/smoketests/modules.rs similarity index 100% rename from crates/smoketests/tests/modules.rs rename to crates/smoketests/tests/smoketests/modules.rs diff --git a/crates/smoketests/tests/namespaces.rs b/crates/smoketests/tests/smoketests/namespaces.rs similarity index 100% rename from crates/smoketests/tests/namespaces.rs rename to crates/smoketests/tests/smoketests/namespaces.rs diff --git a/crates/smoketests/tests/new_user_flow.rs b/crates/smoketests/tests/smoketests/new_user_flow.rs similarity index 100% rename from crates/smoketests/tests/new_user_flow.rs rename to crates/smoketests/tests/smoketests/new_user_flow.rs diff --git a/crates/smoketests/tests/panic.rs b/crates/smoketests/tests/smoketests/panic.rs similarity index 100% rename from crates/smoketests/tests/panic.rs rename to crates/smoketests/tests/smoketests/panic.rs diff --git a/crates/smoketests/tests/permissions.rs b/crates/smoketests/tests/smoketests/permissions.rs similarity index 100% rename from crates/smoketests/tests/permissions.rs rename to crates/smoketests/tests/smoketests/permissions.rs diff --git a/crates/smoketests/tests/pg_wire.rs b/crates/smoketests/tests/smoketests/pg_wire.rs similarity index 100% rename from crates/smoketests/tests/pg_wire.rs rename to crates/smoketests/tests/smoketests/pg_wire.rs diff --git a/crates/smoketests/tests/publish_upgrade_prompt.rs b/crates/smoketests/tests/smoketests/publish_upgrade_prompt.rs similarity index 100% rename from crates/smoketests/tests/publish_upgrade_prompt.rs rename to crates/smoketests/tests/smoketests/publish_upgrade_prompt.rs diff --git a/crates/smoketests/tests/quickstart.rs b/crates/smoketests/tests/smoketests/quickstart.rs similarity index 100% rename from crates/smoketests/tests/quickstart.rs rename to crates/smoketests/tests/smoketests/quickstart.rs diff --git a/crates/smoketests/tests/restart.rs b/crates/smoketests/tests/smoketests/restart.rs similarity index 100% rename from crates/smoketests/tests/restart.rs rename to crates/smoketests/tests/smoketests/restart.rs diff --git a/crates/smoketests/tests/rls.rs b/crates/smoketests/tests/smoketests/rls.rs similarity index 100% rename from crates/smoketests/tests/rls.rs rename to crates/smoketests/tests/smoketests/rls.rs diff --git a/crates/smoketests/tests/schedule_reducer.rs b/crates/smoketests/tests/smoketests/schedule_reducer.rs similarity index 100% rename from crates/smoketests/tests/schedule_reducer.rs rename to crates/smoketests/tests/smoketests/schedule_reducer.rs diff --git a/crates/smoketests/tests/servers.rs b/crates/smoketests/tests/smoketests/servers.rs similarity index 100% rename from crates/smoketests/tests/servers.rs rename to crates/smoketests/tests/smoketests/servers.rs diff --git a/crates/smoketests/tests/sql.rs b/crates/smoketests/tests/smoketests/sql.rs similarity index 100% rename from crates/smoketests/tests/sql.rs rename to crates/smoketests/tests/smoketests/sql.rs diff --git a/crates/smoketests/tests/timestamp_route.rs b/crates/smoketests/tests/smoketests/timestamp_route.rs similarity index 100% rename from crates/smoketests/tests/timestamp_route.rs rename to crates/smoketests/tests/smoketests/timestamp_route.rs diff --git a/crates/smoketests/tests/views.rs b/crates/smoketests/tests/smoketests/views.rs similarity index 98% rename from crates/smoketests/tests/views.rs rename to crates/smoketests/tests/smoketests/views.rs index b7bab89696f..fd65870f137 100644 --- a/crates/smoketests/tests/views.rs +++ b/crates/smoketests/tests/smoketests/views.rs @@ -59,7 +59,7 @@ fn test_st_view_tables() { fn test_fail_publish_namespace_collision() { let mut test = Smoketest::builder() // Can't be precompiled because the code is intentionally broken - .module_code(include_str!("../modules/views-broken-namespace/src/lib.rs")) + .module_code(include_str!("../../modules/views-broken-namespace/src/lib.rs")) .autopublish(false) .build(); @@ -75,7 +75,7 @@ fn test_fail_publish_namespace_collision() { fn test_fail_publish_wrong_return_type() { let mut test = Smoketest::builder() // Can't be precompiled because the code is intentionally broken - .module_code(include_str!("../modules/views-broken-return-type/src/lib.rs")) + .module_code(include_str!("../../modules/views-broken-return-type/src/lib.rs")) .autopublish(false) .build(); diff --git a/tools/ci/README.md b/tools/ci/README.md index c3fc615ddbe..c01598359e7 100644 --- a/tools/ci/README.md +++ b/tools/ci/README.md @@ -121,6 +121,17 @@ Usage: prepare - `--help`: Print help (see a summary with '-h') +#### `check-mod-list` + +**Usage:** +```bash +Usage: check-mod-list +``` + +**Options:** + +- `--help`: + #### `help` **Usage:** diff --git a/tools/ci/src/main.rs b/tools/ci/src/main.rs index 240814f3287..0acf398502c 100644 --- a/tools/ci/src/main.rs +++ b/tools/ci/src/main.rs @@ -12,6 +12,9 @@ const README_PATH: &str = "tools/ci/README.md"; mod ci_docs; mod smoketest; +mod util; + +use util::ensure_repo_root; /// SpacetimeDB CI tasks /// @@ -35,13 +38,6 @@ struct Cli { skip: Vec, } -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)"); - } - Ok(()) -} - fn check_global_json_policy() -> Result<()> { ensure_repo_root()?; diff --git a/tools/ci/src/smoketest.rs b/tools/ci/src/smoketest.rs index 60deac8441d..efc0781b4fa 100644 --- a/tools/ci/src/smoketest.rs +++ b/tools/ci/src/smoketest.rs @@ -1,8 +1,13 @@ #![allow(clippy::disallowed_macros)] -use anyhow::{ensure, Result}; +use anyhow::{bail, ensure, Result}; use clap::{Args, Subcommand}; -use std::env; +use duct::cmd; +use std::ffi::OsStr; +use std::path::Path; use std::process::{Command, Stdio}; +use std::{env, fs}; + +use crate::util; #[derive(Args)] /// This command first builds the spacetimedb-cli and spacetimedb-standalone binaries, @@ -35,6 +40,7 @@ enum SmoketestCmd { /// /// Use this before running `cargo test --all` to ensure binaries are built. Prepare, + CheckModList, } pub fn run(args: SmoketestsArgs) -> Result<()> { @@ -44,6 +50,11 @@ pub fn run(args: SmoketestsArgs) -> Result<()> { eprintln!("Binaries ready. You can now run `cargo test --all`."); Ok(()) } + Some(SmoketestCmd::CheckModList) => { + check_smoketests_mod_rs_complete()?; + eprintln!("smoketests/mod.rs is up to date."); + Ok(()) + } None => run_smoketest(args.server, args.dotnet, args.args), } } @@ -177,3 +188,64 @@ fn set_env(cmd: &mut Command, server: Option, dotnet: bool) { } cmd.env("SMOKETESTS_DOTNET", if dotnet { "1" } else { "0" }); } + +fn check_smoketests_mod_rs_complete() -> Result<()> { + util::ensure_repo_root()?; + + let expected_dir = Path::new("crates/smoketests/tests/smoketests"); + let mut expected = std::collections::BTreeSet::::new(); + for entry in fs::read_dir(expected_dir)? { + let entry = entry?; + let path = entry.path(); + let name = entry.file_name(); + let name = name.to_string_lossy(); + if name == "mod.rs" { + continue; + } + if name.starts_with('.') { + continue; + } + + let ft = entry.file_type()?; + if ft.is_dir() { + expected.insert(name.to_string()); + } else if ft.is_file() && path.extension() == Some(OsStr::new("rs")) { + if let Some(stem) = path.file_stem() { + expected.insert(stem.to_string_lossy().to_string()); + } + } + } + + let out = cmd!("cargo", "test", "-p", "spacetimedb-smoketests", "--", "--list",).read()?; + + let mut present = std::collections::BTreeSet::::new(); + for line in out.lines() { + let line = line.trim(); + let parts: Vec<&str> = line.split("::").collect(); + if parts.len() < 2 { + continue; + } + if parts[0] != "smoketests" { + continue; + } + present.insert(parts[1].to_string()); + } + + let missing = expected + .into_iter() + .filter(|m| !present.contains(m)) + .collect::>(); + + if !missing.is_empty() { + bail!( + "crates/smoketests/tests/smoketests/mod.rs appears incomplete; missing modules (not present in `cargo test -- --list`):\n{}", + missing + .iter() + .map(|m| format!("- mod {m};")) + .collect::>() + .join("\n") + ); + } + + Ok(()) +} diff --git a/tools/ci/src/util.rs b/tools/ci/src/util.rs new file mode 100644 index 00000000000..ac35a7a465b --- /dev/null +++ b/tools/ci/src/util.rs @@ -0,0 +1,11 @@ +#![allow(clippy::disallowed_macros)] + +use anyhow::{bail, Result}; +use std::path::Path; + +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)"); + } + Ok(()) +}