Validate template-bundles.yml structure and consistency.
This script validates the template bundles configuration file to ensure:
1. Valid YAML syntax
2. Required fields are present
3. Bundle dependencies reference existing bundles
4. File paths follow expected patterns
5. Examples reference valid bundles
The script reads .rhiza/template.yml to find the template repository,
then fetches template-bundles.yml from that remote repository.
Exit codes
0 - Validation passed
1 - Validation failed
find_repo_root()
Find the repository root directory.
Returns:
| Type |
Description |
Path
|
Path to the repository root
|
Source code in src/rhiza_hooks/check_template_bundles.py
| def find_repo_root() -> Path:
"""Find the repository root directory.
Returns:
Path to the repository root
"""
current = Path.cwd()
while current != current.parent:
if (current / ".git").exists():
return current
current = current.parent
return Path.cwd()
|
main(argv=None)
Main entry point.
Source code in src/rhiza_hooks/check_template_bundles.py
| def main(argv: list[str] | None = None) -> int:
"""Main entry point."""
if isinstance(sys.stdout, io.TextIOWrapper):
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
parser = argparse.ArgumentParser(description="Validate template-bundles.yml from remote template repository")
parser.add_argument(
"filenames",
nargs="*",
help="Filenames to check (should be .rhiza/template.yml)",
)
args = parser.parse_args(argv)
# Get configuration path
config_path = _get_config_path(args)
# Load and validate configuration
config, templates_set = _load_and_validate_config(config_path)
if config is None or templates_set is None:
return 0
# Get template repository and branch
template_repo = config.get("template-repository")
template_branch = config.get("template-branch")
if not template_repo or not template_branch:
print(f"Missing template-repository or template-branch in {config_path}")
return 1
# Fetch and validate remote bundles
data, _fetch_errors = _validate_remote_bundles(template_repo, template_branch, templates_set, config_path)
if data is None:
return 1
# Validate templates
bundles = data.get("bundles", {})
errors = _validate_templates_in_bundles(templates_set, bundles, config_path)
if errors:
print("\n✗ Template bundles validation failed:")
for error in errors:
print(f" - {error}")
return 1
print("✓ Template bundles validation passed!")
return 0
|
validate_template_bundles(bundles_path, templates_to_check=None)
Validate template bundles configuration.
Parameters:
| Name |
Type |
Description |
Default |
bundles_path
|
Path
|
Path to template-bundles.yml
|
required
|
templates_to_check
|
set[str] | None
|
Optional set of template names to validate. If None, validate all.
|
None
|
Returns:
| Type |
Description |
tuple[bool, list[str]]
|
Tuple of (success, error_messages)
|
Source code in src/rhiza_hooks/check_template_bundles.py
| def validate_template_bundles(bundles_path: Path, templates_to_check: set[str] | None = None) -> tuple[bool, list[str]]:
"""Validate template bundles configuration.
Args:
bundles_path: Path to template-bundles.yml
templates_to_check: Optional set of template names to validate. If None, validate all.
Returns:
Tuple of (success, error_messages)
"""
# Load YAML file
success, data_or_errors = _load_yaml_file(bundles_path)
if not success:
# Type narrowing: when success is False, data_or_errors is list[str]
return False, cast(list[str], data_or_errors)
# Type narrowing: when success is True, data_or_errors is dict[Any, Any]
data = cast(dict[Any, Any], data_or_errors)
# Validate top-level fields
errors = _validate_top_level_fields(data)
if errors:
return False, errors
# Validate bundles section
bundles = data.get("bundles", {})
if not isinstance(bundles, dict):
return False, ["'bundles' must be a dictionary"]
bundle_names = cast(set[str], set(bundles.keys()))
# If templates_to_check is specified, verify they exist
if templates_to_check is not None:
for template in templates_to_check:
if template not in bundle_names:
errors.append(f"Template '{template}' specified in .rhiza/template.yml not found in bundles")
# Determine which bundles to validate
bundles_to_validate = templates_to_check if templates_to_check is not None else bundle_names
# Validate each bundle
for bundle_name in bundles_to_validate:
if bundle_name in bundles:
bundle_config = bundles[bundle_name]
errors.extend(_validate_bundle_structure(bundle_name, bundle_config, bundle_names))
# Validate examples section (only if validating all bundles)
if templates_to_check is None and "examples" in data:
errors.extend(_validate_examples(data["examples"], bundle_names))
# Validate metadata if present (only if validating all bundles)
if templates_to_check is None and "metadata" in data:
errors.extend(_validate_metadata(data["metadata"], bundles))
return len(errors) == 0, errors
|