Skip to content

Commit 118e59d

Browse files
authored
CI - Do some basic checks that crates are publishable (#2660)
Co-authored-by: Zeke Foppa <[email protected]>
1 parent 69ec803 commit 118e59d

File tree

8 files changed

+106
-10
lines changed

8 files changed

+106
-10
lines changed

.github/workflows/ci.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,30 @@ jobs:
219219
- name: Run bindgen tests
220220
run: cargo test -p spacetimedb-cli
221221

222+
publish_checks:
223+
name: Check that packages are publishable
224+
runs-on: ubuntu-latest
225+
permissions: read-all
226+
steps:
227+
- uses: actions/checkout@v3
228+
- name: Set up Python env
229+
run: |
230+
test -d venv || python3 -m venv venv
231+
venv/bin/pip3 install argparse toml
232+
- name: Run checks
233+
run: |
234+
FAILED=0
235+
# This definition of ROOTS and invocation of find-publish-list.py is copied from publish-crates.sh
236+
ROOTS=(bindings sdk cli standalone)
237+
for crate in $(venv/bin/python3 tools/find-publish-list.py --recursive --quiet "${ROOTS[@]}"); do
238+
if ! venv/bin/python3 tools/crate-publish-checks.py "crates/$crate"; then
239+
FAILED=$(( $FAILED + 1 ))
240+
fi
241+
done
242+
if [ $FAILED -gt 0 ]; then
243+
exit 1
244+
fi
245+
222246
update:
223247
name: Test spacetimedb-update flow
224248
permissions: read-all

crates/core/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ perfmap = []
132132
[dev-dependencies]
133133
spacetimedb-lib = { path = "../lib", features = ["proptest"] }
134134
spacetimedb-sats = { path = "../sats", features = ["proptest"] }
135-
spacetimedb-commitlog = { workspace = true, features = ["test"] }
135+
spacetimedb-commitlog = { path = "../commitlog", features = ["test"] }
136136

137137
criterion.workspace = true
138138
# Also as dev-dependencies for use in _this_ crate's tests.

crates/expr/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,5 @@ spacetimedb-sql-parser.workspace = true
2020

2121
[dev-dependencies]
2222
pretty_assertions.workspace = true
23-
spacetimedb = { workspace = true, features = ["unstable"] }
24-
spacetimedb-lib.workspace = true
23+
spacetimedb = { path = "../bindings", features = ["unstable"] }
24+
spacetimedb-lib = { path = "../lib" }

crates/lib/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ proptest = { workspace = true, optional = true }
4848
proptest-derive = { workspace = true, optional = true }
4949

5050
[dev-dependencies]
51-
spacetimedb-sats = { workspace = true, features = ["test"] }
51+
spacetimedb-sats = { path = "../sats", features = ["test"] }
5252
bytes.workspace = true
5353
serde_json.workspace = true
5454
insta.workspace = true

crates/schema/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ enum-as-inner.workspace = true
3131
enum-map.workspace = true
3232

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

3939
proptest.workspace = true
4040
serial_test.workspace = true

crates/snapshot/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ tokio-util = { workspace = true, features = ["io"] }
2828
zstd-framed.workspace = true
2929

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

3434
anyhow.workspace = true
3535
env_logger.workspace = true

crates/table/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ proptest = { workspace = true, optional = true }
5050
proptest-derive = { workspace = true, optional = true }
5151

5252
[dev-dependencies]
53-
spacetimedb-schema = { workspace = true, features = ["test"] }
54-
spacetimedb-sats = { workspace = true, features = ["proptest"] }
53+
spacetimedb-schema = { path = "../schema", features = ["test"] }
54+
spacetimedb-sats = { path = "../sats", features = ["proptest"] }
5555
criterion.workspace = true
5656
proptest.workspace = true
5757
proptest-derive.workspace = true

tools/crate-publish-checks.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import toml
2+
import argparse
3+
import sys
4+
from pathlib import Path
5+
6+
def find_non_path_spacetimedb_deps(dev_deps):
7+
non_path_spacetimedb = []
8+
for name, details in dev_deps.items():
9+
if not name.startswith("spacetimedb"):
10+
continue
11+
12+
if isinstance(details, dict):
13+
if "path" not in details:
14+
non_path_spacetimedb.append(name)
15+
else:
16+
# String dependency = version from crates.io
17+
non_path_spacetimedb.append(name)
18+
return non_path_spacetimedb
19+
20+
def check_cargo_metadata(data):
21+
package = data.get("package", {})
22+
missing_fields = []
23+
24+
# Accept either license OR license-file
25+
if "license" not in package and "license-file" not in package:
26+
missing_fields.append("license/license-file")
27+
28+
if "description" not in package:
29+
missing_fields.append("description")
30+
31+
return missing_fields
32+
33+
if __name__ == "__main__":
34+
parser = argparse.ArgumentParser(description="Check Cargo.toml for metadata and dev-dependencies.")
35+
parser.add_argument("directory", help="Directory to search for Cargo.toml")
36+
37+
args = parser.parse_args()
38+
cargo_toml_path = Path(args.directory) / "Cargo.toml"
39+
40+
try:
41+
if not cargo_toml_path.exists():
42+
raise FileNotFoundError(f"{cargo_toml_path} not found.")
43+
44+
data = toml.load(cargo_toml_path)
45+
46+
# Check dev-dependencies
47+
dev_deps = data.get("dev-dependencies", {})
48+
bad_deps = find_non_path_spacetimedb_deps(dev_deps)
49+
50+
# Check license/license-file and description
51+
missing_fields = check_cargo_metadata(data)
52+
53+
exit_code = 0
54+
55+
if bad_deps:
56+
print(f"❌ These dev-dependencies in {cargo_toml_path} must be converted to use `path` in order to not impede crate publishing:")
57+
for dep in bad_deps:
58+
print(f" - {dep}")
59+
exit_code = 1
60+
61+
if missing_fields:
62+
print(f"❌ Missing required fields in [package] of {cargo_toml_path}: {', '.join(missing_fields)}")
63+
exit_code = 1
64+
65+
if exit_code == 0:
66+
print(f"✅ {cargo_toml_path} passed all checks.")
67+
68+
sys.exit(exit_code)
69+
70+
except Exception as e:
71+
print(f"⚠️ Error: {e}")
72+
sys.exit(2)

0 commit comments

Comments
 (0)