mirror of
https://github.com/hanzoui/workflow-templates-broken-zap-2026-06-08.git
synced 2026-10-30 20:44:35 +00:00
193 lines
5.6 KiB
Python
193 lines
5.6 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Validate subgraph blueprints.
|
|
|
|
This script validates:
|
|
1. JSON syntax for all blueprint files
|
|
2. index.json against the schema
|
|
3. Blueprint structure (definitions.subgraphs present with required fields)
|
|
4. blueprints_bundles.json consistency with files on disk
|
|
"""
|
|
|
|
import argparse
|
|
import json
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
try:
|
|
import jsonschema
|
|
HAS_JSONSCHEMA = True
|
|
except ImportError:
|
|
HAS_JSONSCHEMA = False
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
BLUEPRINTS_DIR = ROOT / "blueprints"
|
|
BUNDLES_CONFIG = ROOT / "blueprints_bundles.json"
|
|
|
|
|
|
def validate_json_syntax() -> list[str]:
|
|
"""Check that all blueprint JSON files have valid syntax."""
|
|
errors = []
|
|
for bp_file in sorted(BLUEPRINTS_DIR.glob("*.json")):
|
|
try:
|
|
with bp_file.open() as f:
|
|
json.load(f)
|
|
except json.JSONDecodeError as e:
|
|
errors.append(f"{bp_file.name}: Invalid JSON - {e}")
|
|
return errors
|
|
|
|
|
|
def validate_index_schema() -> list[str]:
|
|
"""Validate index.json against the schema."""
|
|
if not HAS_JSONSCHEMA:
|
|
print("Warning: jsonschema not installed, skipping schema validation")
|
|
return []
|
|
|
|
errors = []
|
|
schema_path = BLUEPRINTS_DIR / "index.schema.json"
|
|
index_path = BLUEPRINTS_DIR / "index.json"
|
|
|
|
if not schema_path.exists():
|
|
errors.append("index.schema.json not found")
|
|
return errors
|
|
if not index_path.exists():
|
|
errors.append("index.json not found")
|
|
return errors
|
|
|
|
try:
|
|
with schema_path.open() as f:
|
|
schema = json.load(f)
|
|
with index_path.open() as f:
|
|
index = json.load(f)
|
|
jsonschema.validate(index, schema)
|
|
except jsonschema.ValidationError as e:
|
|
errors.append(f"Schema validation failed: {e.message}")
|
|
except json.JSONDecodeError as e:
|
|
errors.append(f"JSON parse error: {e}")
|
|
|
|
return errors
|
|
|
|
|
|
def validate_blueprint_structure() -> list[str]:
|
|
"""Check that each blueprint has the required structure."""
|
|
errors = []
|
|
|
|
for bp_file in sorted(BLUEPRINTS_DIR.glob("*.json")):
|
|
if bp_file.name.startswith("index"):
|
|
continue
|
|
|
|
try:
|
|
with bp_file.open() as f:
|
|
data = json.load(f)
|
|
|
|
if "definitions" not in data:
|
|
errors.append(f'{bp_file.name}: Missing "definitions" key')
|
|
continue
|
|
|
|
subgraphs = data.get("definitions", {}).get("subgraphs", [])
|
|
if not subgraphs:
|
|
errors.append(f'{bp_file.name}: Missing "definitions.subgraphs" array')
|
|
continue
|
|
|
|
sg = subgraphs[0]
|
|
if "name" not in sg:
|
|
errors.append(f"{bp_file.name}: Missing subgraph name")
|
|
if "inputs" not in sg:
|
|
errors.append(f"{bp_file.name}: Missing subgraph inputs")
|
|
if "outputs" not in sg:
|
|
errors.append(f"{bp_file.name}: Missing subgraph outputs")
|
|
if "nodes" not in sg:
|
|
errors.append(f"{bp_file.name}: Missing subgraph nodes")
|
|
|
|
except json.JSONDecodeError:
|
|
pass # Already caught in syntax check
|
|
|
|
return errors
|
|
|
|
|
|
def validate_bundles_consistency() -> list[str]:
|
|
"""Check that blueprints_bundles.json matches files on disk."""
|
|
errors = []
|
|
|
|
if not BUNDLES_CONFIG.exists():
|
|
errors.append("blueprints_bundles.json not found")
|
|
return errors
|
|
|
|
try:
|
|
with BUNDLES_CONFIG.open() as f:
|
|
bundles = json.load(f)
|
|
except json.JSONDecodeError as e:
|
|
errors.append(f"blueprints_bundles.json: Invalid JSON - {e}")
|
|
return errors
|
|
|
|
blueprint_ids = set(bundles.get("blueprints", []))
|
|
|
|
on_disk = {
|
|
p.stem
|
|
for p in BLUEPRINTS_DIR.glob("*.json")
|
|
if not p.name.startswith("index")
|
|
}
|
|
|
|
missing_from_bundles = on_disk - blueprint_ids
|
|
missing_on_disk = blueprint_ids - on_disk
|
|
|
|
if missing_from_bundles:
|
|
errors.append(f"Blueprints not in bundles.json: {sorted(missing_from_bundles)}")
|
|
if missing_on_disk:
|
|
errors.append(f"Bundles.json references missing files: {sorted(missing_on_disk)}")
|
|
|
|
return errors
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="Validate subgraph blueprints")
|
|
parser.parse_args()
|
|
|
|
all_errors = []
|
|
|
|
print("Checking JSON syntax...")
|
|
errors = validate_json_syntax()
|
|
if errors:
|
|
all_errors.extend(errors)
|
|
print(f" ❌ {len(errors)} syntax error(s)")
|
|
else:
|
|
print(" ✅ All JSON files have valid syntax")
|
|
|
|
print("Validating index.json against schema...")
|
|
errors = validate_index_schema()
|
|
if errors:
|
|
all_errors.extend(errors)
|
|
print(f" ❌ {len(errors)} schema error(s)")
|
|
else:
|
|
print(" ✅ index.json validates against schema")
|
|
|
|
print("Validating blueprint structure...")
|
|
errors = validate_blueprint_structure()
|
|
if errors:
|
|
all_errors.extend(errors)
|
|
print(f" ❌ {len(errors)} structure error(s)")
|
|
else:
|
|
print(" ✅ All blueprints have valid structure")
|
|
|
|
print("Checking blueprints_bundles.json consistency...")
|
|
errors = validate_bundles_consistency()
|
|
if errors:
|
|
all_errors.extend(errors)
|
|
print(f" ❌ {len(errors)} consistency error(s)")
|
|
else:
|
|
print(" ✅ blueprints_bundles.json is consistent")
|
|
|
|
if all_errors:
|
|
print("\n❌ Validation failed with errors:")
|
|
for err in all_errors:
|
|
print(f" - {err}")
|
|
print("\nRun: python scripts/import_blueprints.py")
|
|
sys.exit(1)
|
|
else:
|
|
print("\n✅ All validations passed")
|
|
sys.exit(0)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|