From 0cfb937d07f9144c2268dee6afdf3fb2b42509d2 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Wed, 8 Feb 2023 21:48:58 +0100 Subject: [PATCH] Enforce sorting of manifests (#87020) --- script/hassfest/manifest.py | 33 +++++++++++++++++++++++++++++++++ script/hassfest/model.py | 2 ++ 2 files changed, 35 insertions(+) diff --git a/script/hassfest/manifest.py b/script/hassfest/manifest.py index 6774e909140..89a3d70afc7 100644 --- a/script/hassfest/manifest.py +++ b/script/hassfest/manifest.py @@ -2,7 +2,9 @@ from __future__ import annotations from enum import IntEnum +import json from pathlib import Path +import subprocess from typing import Any from urllib.parse import urlparse @@ -361,8 +363,39 @@ def validate_manifest(integration: Integration, core_components_dir: Path) -> No validate_version(integration) +_SORT_KEYS = {"domain": ".domain", "name": ".name"} + + +def _sort_manifest_keys(key: str) -> str: + return _SORT_KEYS.get(key, key) + + +def sort_manifest(integration: Integration) -> bool: + """Sort manifest.""" + keys = list(integration.manifest.keys()) + if (keys_sorted := sorted(keys, key=_sort_manifest_keys)) != keys: + manifest = {key: integration.manifest[key] for key in keys_sorted} + integration.manifest_path.write_text(json.dumps(manifest, indent=2)) + integration.add_error( + "manifest", + "Manifest keys have been sorted: domain, name, then alphabetical order", + ) + return True + return False + + def validate(integrations: dict[str, Integration], config: Config) -> None: """Handle all integrations manifests.""" core_components_dir = config.root / "homeassistant/components" + manifests_resorted = [] for integration in integrations.values(): validate_manifest(integration, core_components_dir) + if not integration.errors: + if sort_manifest(integration): + manifests_resorted.append(integration.manifest_path) + if manifests_resorted: + subprocess.run( + ["pre-commit", "run", "--hook-stage", "manual", "prettier", "--files"] + + manifests_resorted, + stdout=subprocess.DEVNULL, + ) diff --git a/script/hassfest/model.py b/script/hassfest/model.py index 52af5f6c791..e4f93c80e81 100644 --- a/script/hassfest/model.py +++ b/script/hassfest/model.py @@ -130,6 +130,7 @@ class Integration: path: pathlib.Path _manifest: dict[str, Any] | None = None + manifest_path: pathlib.Path | None = None errors: list[Error] = field(default_factory=list) warnings: list[Error] = field(default_factory=list) translated_name: bool = False @@ -223,3 +224,4 @@ class Integration: return self._manifest = manifest + self.manifest_path = manifest_path