Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,30 @@ jobs:
- name: Run bindgen tests
run: cargo test -p spacetimedb-cli

publish_checks:
name: Check that packages are publishable
runs-on: ubuntu-latest
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: |
FAILED=0
# This definition of ROOTS and invocation of find-publish-list.py is copied from publish-crates.sh
ROOTS=(bindings sdk cli standalone)
for crate in $(venv/bin/python3 tools/find-publish-list.py --recursive --quiet "${ROOTS[@]}"); do
if ! venv/bin/python3 tools/crate-publish-checks.py "crates/$crate"; then
FAILED=$(( $FAILED + 1 ))
fi
done
if [ $FAILED -gt 0 ]; then
exit 1
fi

update:
name: Test spacetimedb-update flow
permissions: read-all
Expand Down
2 changes: 1 addition & 1 deletion crates/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ perfmap = []
[dev-dependencies]
spacetimedb-lib = { path = "../lib", features = ["proptest"] }
spacetimedb-sats = { path = "../sats", features = ["proptest"] }
spacetimedb-commitlog = { workspace = true, features = ["test"] }
spacetimedb-commitlog = { path = "../commitlog", features = ["test"] }

criterion.workspace = true
# Also as dev-dependencies for use in _this_ crate's tests.
Expand Down
4 changes: 2 additions & 2 deletions crates/expr/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@ spacetimedb-sql-parser.workspace = true

[dev-dependencies]
pretty_assertions.workspace = true
spacetimedb = { workspace = true, features = ["unstable"] }
spacetimedb-lib.workspace = true
spacetimedb = { path = "../bindings", features = ["unstable"] }
spacetimedb-lib = { path = "../lib" }
2 changes: 1 addition & 1 deletion crates/lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ proptest = { workspace = true, optional = true }
proptest-derive = { workspace = true, optional = true }

[dev-dependencies]
spacetimedb-sats = { workspace = true, features = ["test"] }
spacetimedb-sats = { path = "../sats", features = ["test"] }
bytes.workspace = true
serde_json.workspace = true
insta.workspace = true
Expand Down
4 changes: 2 additions & 2 deletions crates/schema/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ enum-as-inner.workspace = true
enum-map.workspace = true

[dev-dependencies]
spacetimedb-lib = { workspace = true, features = ["test"] }
spacetimedb-lib = { path = "../lib", features = ["test"] }
# these are circular dependencies, but only in tests, so it's fine
spacetimedb-testing = { path = "../testing" }
spacetimedb-cli.workspace = true
spacetimedb-cli = { path = "../cli" }

proptest.workspace = true
serial_test.workspace = true
4 changes: 2 additions & 2 deletions crates/snapshot/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ tokio-util = { workspace = true, features = ["io"] }
zstd-framed.workspace = true

[dev-dependencies]
spacetimedb-core = { workspace = true, features = ["test"] }
spacetimedb-schema.workspace = true
spacetimedb-core = { path = "../core", features = ["test"] }
spacetimedb-schema = { path = "../schema" }

anyhow.workspace = true
env_logger.workspace = true
Expand Down
4 changes: 2 additions & 2 deletions crates/table/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ proptest = { workspace = true, optional = true }
proptest-derive = { workspace = true, optional = true }

[dev-dependencies]
spacetimedb-schema = { workspace = true, features = ["test"] }
spacetimedb-sats = { workspace = true, features = ["proptest"] }
spacetimedb-schema = { path = "../schema", features = ["test"] }
spacetimedb-sats = { path = "../sats", features = ["proptest"] }
criterion.workspace = true
proptest.workspace = true
proptest-derive.workspace = true
Expand Down
72 changes: 72 additions & 0 deletions tools/crate-publish-checks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import toml
import argparse
import sys
from pathlib import Path

def find_non_path_spacetimedb_deps(dev_deps):
non_path_spacetimedb = []
for name, details in dev_deps.items():
if not name.startswith("spacetimedb"):
continue

if isinstance(details, dict):
if "path" not in details:
non_path_spacetimedb.append(name)
else:
# String dependency = version from crates.io
non_path_spacetimedb.append(name)
return non_path_spacetimedb

def check_cargo_metadata(data):
package = data.get("package", {})
missing_fields = []

# Accept either license OR license-file
if "license" not in package and "license-file" not in package:
missing_fields.append("license/license-file")

if "description" not in package:
missing_fields.append("description")

return missing_fields

if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Check Cargo.toml for metadata and dev-dependencies.")
parser.add_argument("directory", help="Directory to search for Cargo.toml")

args = parser.parse_args()
cargo_toml_path = Path(args.directory) / "Cargo.toml"

try:
if not cargo_toml_path.exists():
raise FileNotFoundError(f"{cargo_toml_path} not found.")

data = toml.load(cargo_toml_path)

# Check dev-dependencies
dev_deps = data.get("dev-dependencies", {})
bad_deps = find_non_path_spacetimedb_deps(dev_deps)

# Check license/license-file and description
missing_fields = check_cargo_metadata(data)

exit_code = 0

if bad_deps:
print(f"❌ These dev-dependencies in {cargo_toml_path} must be converted to use `path` in order to not impede crate publishing:")
for dep in bad_deps:
print(f" - {dep}")
exit_code = 1

if missing_fields:
print(f"❌ Missing required fields in [package] of {cargo_toml_path}: {', '.join(missing_fields)}")
exit_code = 1

if exit_code == 0:
print(f"✅ {cargo_toml_path} passed all checks.")

sys.exit(exit_code)

except Exception as e:
print(f"⚠️ Error: {e}")
sys.exit(2)
Loading