ci: migrate workflows and releases to Gitea
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Validate the local repository structure used to package the integration."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
|
||||
REPOSITORY_ROOT = Path(__file__).resolve().parent.parent
|
||||
CUSTOM_COMPONENTS = REPOSITORY_ROOT / "custom_components"
|
||||
|
||||
|
||||
def load_json(path: Path) -> dict[str, Any]:
|
||||
try:
|
||||
value = json.loads(path.read_text(encoding="utf-8"))
|
||||
except (OSError, json.JSONDecodeError) as error:
|
||||
raise ValueError(f"Could not read valid JSON from {path.relative_to(REPOSITORY_ROOT)}: {error}") from error
|
||||
|
||||
if not isinstance(value, dict):
|
||||
raise ValueError(f"Expected a JSON object in {path.relative_to(REPOSITORY_ROOT)}")
|
||||
return value
|
||||
|
||||
|
||||
def main() -> None:
|
||||
integration_directories = sorted(
|
||||
path for path in CUSTOM_COMPONENTS.iterdir() if path.is_dir() and path.name != "__pycache__"
|
||||
)
|
||||
if len(integration_directories) != 1:
|
||||
names = ", ".join(path.name for path in integration_directories) or "none"
|
||||
raise ValueError(f"Expected exactly one integration under custom_components; found: {names}")
|
||||
|
||||
integration_directory = integration_directories[0]
|
||||
manifest = load_json(integration_directory / "manifest.json")
|
||||
required_manifest_fields = {
|
||||
"codeowners",
|
||||
"documentation",
|
||||
"domain",
|
||||
"issue_tracker",
|
||||
"name",
|
||||
"version",
|
||||
}
|
||||
missing_fields = sorted(required_manifest_fields - manifest.keys())
|
||||
if missing_fields:
|
||||
raise ValueError(f"manifest.json is missing required fields: {', '.join(missing_fields)}")
|
||||
if manifest["domain"] != integration_directory.name:
|
||||
raise ValueError("manifest.json domain must match its custom_components directory")
|
||||
if not isinstance(manifest["codeowners"], list) or not manifest["codeowners"]:
|
||||
raise ValueError("manifest.json codeowners must be a non-empty list")
|
||||
if not (integration_directory / "brand" / "icon.png").is_file():
|
||||
raise ValueError("The integration must include brand/icon.png")
|
||||
|
||||
hacs_manifest = load_json(REPOSITORY_ROOT / "hacs.json")
|
||||
if not isinstance(hacs_manifest.get("name"), str) or not hacs_manifest["name"].strip():
|
||||
raise ValueError("hacs.json must include a non-empty name")
|
||||
if hacs_manifest.get("zip_release") is True:
|
||||
filename = hacs_manifest.get("filename")
|
||||
if not isinstance(filename, str) or not filename.endswith(".zip"):
|
||||
raise ValueError("hacs.json zip_release requires a .zip filename")
|
||||
|
||||
if not (REPOSITORY_ROOT / "README.md").is_file():
|
||||
raise ValueError("The repository must include README.md")
|
||||
|
||||
print(f"Repository structure is valid for integration {manifest['domain']} {manifest['version']}.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user