mirror of
https://github.com/clockworklabs/SpacetimeDB.git
synced 2026-05-06 15:49:35 -04:00
CI - Do some basic checks that crates are publishable (#2660)
Co-authored-by: Zeke Foppa <bfops@users.noreply.github.com>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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" }
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
Reference in New Issue
Block a user