2020-07-25 15:57:18 +02:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
import argparse
|
2020-07-26 14:33:16 +02:00
|
|
|
from collections import defaultdict
|
2024-08-07 05:46:37 +02:00
|
|
|
from pathlib import Path
|
|
|
|
import sys
|
2020-07-25 15:57:18 +02:00
|
|
|
|
2020-07-26 14:33:16 +02:00
|
|
|
from esphome.config import get_component, get_platform
|
2023-07-12 02:08:03 +02:00
|
|
|
from esphome.const import KEY_CORE, KEY_TARGET_FRAMEWORK
|
2024-08-07 05:46:37 +02:00
|
|
|
from esphome.core import CORE
|
|
|
|
from esphome.helpers import write_file_if_changed
|
2020-07-25 15:57:18 +02:00
|
|
|
|
|
|
|
parser = argparse.ArgumentParser()
|
2021-03-07 20:03:16 +01:00
|
|
|
parser.add_argument(
|
|
|
|
"--check", help="Check if the CODEOWNERS file is up to date.", action="store_true"
|
|
|
|
)
|
2020-07-25 15:57:18 +02:00
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
|
|
# The root directory of the repo
|
|
|
|
root = Path(__file__).parent.parent
|
2021-03-07 20:03:16 +01:00
|
|
|
components_dir = root / "esphome" / "components"
|
2020-07-25 15:57:18 +02:00
|
|
|
|
|
|
|
BASE = """
|
|
|
|
# This file is generated by script/build_codeowners.py
|
|
|
|
# People marked here will be automatically requested for a review
|
|
|
|
# when the code that they own is touched.
|
|
|
|
#
|
|
|
|
# Every time an issue is created with a label corresponding to an integration,
|
|
|
|
# the integration's code owner is automatically notified.
|
|
|
|
|
|
|
|
# Core Code
|
2024-05-16 12:33:33 +02:00
|
|
|
pyproject.toml @esphome/core
|
2020-07-25 15:57:18 +02:00
|
|
|
esphome/*.py @esphome/core
|
|
|
|
esphome/core/* @esphome/core
|
|
|
|
|
|
|
|
# Integrations
|
|
|
|
""".strip()
|
|
|
|
|
|
|
|
parts = [BASE]
|
|
|
|
|
2021-03-19 09:16:27 +01:00
|
|
|
# Fake some directory so that get_component works
|
2020-07-25 15:57:18 +02:00
|
|
|
CORE.config_path = str(root)
|
2023-07-12 02:08:03 +02:00
|
|
|
CORE.data[KEY_CORE] = {KEY_TARGET_FRAMEWORK: None}
|
2020-07-25 15:57:18 +02:00
|
|
|
|
2020-07-26 14:33:16 +02:00
|
|
|
codeowners = defaultdict(list)
|
|
|
|
|
|
|
|
for path in components_dir.iterdir():
|
2020-07-25 15:57:18 +02:00
|
|
|
if not path.is_dir():
|
|
|
|
continue
|
2021-03-07 20:03:16 +01:00
|
|
|
if not (path / "__init__.py").is_file():
|
2020-07-25 15:57:18 +02:00
|
|
|
continue
|
2020-07-26 14:33:16 +02:00
|
|
|
|
2020-07-25 15:57:18 +02:00
|
|
|
name = path.name
|
|
|
|
comp = get_component(name)
|
2020-10-27 00:41:57 +01:00
|
|
|
if comp is None:
|
2021-03-07 20:03:16 +01:00
|
|
|
print(
|
|
|
|
f"Cannot find component {name}. Make sure current path is pip installed ESPHome"
|
|
|
|
)
|
2020-10-27 00:41:57 +01:00
|
|
|
sys.exit(1)
|
|
|
|
|
2021-03-07 20:03:16 +01:00
|
|
|
codeowners[f"esphome/components/{name}/*"].extend(comp.codeowners)
|
2020-07-26 14:33:16 +02:00
|
|
|
|
|
|
|
for platform_path in path.iterdir():
|
|
|
|
platform_name = platform_path.stem
|
|
|
|
platform = get_platform(platform_name, name)
|
|
|
|
if platform is None:
|
|
|
|
continue
|
|
|
|
|
|
|
|
if platform_path.is_dir():
|
|
|
|
# Sub foldered platforms get their own line
|
2021-03-07 20:03:16 +01:00
|
|
|
if not (platform_path / "__init__.py").is_file():
|
2020-07-26 14:33:16 +02:00
|
|
|
continue
|
2021-03-07 20:03:16 +01:00
|
|
|
codeowners[f"esphome/components/{name}/{platform_name}/*"].extend(
|
|
|
|
platform.codeowners
|
|
|
|
)
|
2020-07-26 14:33:16 +02:00
|
|
|
continue
|
|
|
|
|
|
|
|
# Non-subfoldered platforms add to codeowners at component level
|
2021-03-07 20:03:16 +01:00
|
|
|
if not platform_path.is_file() or platform_path.name == "__init__.py":
|
2020-07-26 14:33:16 +02:00
|
|
|
continue
|
2021-03-07 20:03:16 +01:00
|
|
|
codeowners[f"esphome/components/{name}/*"].extend(platform.codeowners)
|
2020-07-26 14:33:16 +02:00
|
|
|
|
|
|
|
|
|
|
|
for path, owners in sorted(codeowners.items()):
|
|
|
|
owners = sorted(set(owners))
|
|
|
|
if not owners:
|
|
|
|
continue
|
|
|
|
for owner in owners:
|
2021-03-07 20:03:16 +01:00
|
|
|
if not owner.startswith("@"):
|
|
|
|
print(
|
|
|
|
f"Codeowner {owner} for integration {path} must start with an '@' symbol!"
|
|
|
|
)
|
2020-07-26 14:33:16 +02:00
|
|
|
sys.exit(1)
|
|
|
|
parts.append(f"{path} {' '.join(owners)}")
|
2020-07-25 15:57:18 +02:00
|
|
|
|
|
|
|
|
|
|
|
# End newline
|
2021-03-07 20:03:16 +01:00
|
|
|
parts.append("")
|
|
|
|
content = "\n".join(parts)
|
|
|
|
codeowners_file = root / "CODEOWNERS"
|
2020-07-25 15:57:18 +02:00
|
|
|
|
|
|
|
if args.check:
|
|
|
|
if codeowners_file.read_text() != content:
|
|
|
|
print("CODEOWNERS file is not up to date.")
|
|
|
|
print("Please run `script/build_codeowners.py`")
|
|
|
|
sys.exit(1)
|
|
|
|
print("CODEOWNERS file is up to date")
|
|
|
|
else:
|
|
|
|
write_file_if_changed(codeowners_file, content)
|
|
|
|
print("Wrote CODEOWNERS")
|