mirror of
https://github.com/esphome/esphome.git
synced 2025-10-10 22:03:46 +01:00
[clang-tidy] Include sdkconfig.defaults in hash calculation (#11091)
This commit is contained in:
@@ -48,9 +48,10 @@ def parse_requirement_line(line: str) -> tuple[str, str] | None:
|
||||
return None
|
||||
|
||||
|
||||
def get_clang_tidy_version_from_requirements() -> str:
|
||||
def get_clang_tidy_version_from_requirements(repo_root: Path | None = None) -> str:
|
||||
"""Get clang-tidy version from requirements_dev.txt"""
|
||||
requirements_path = Path(__file__).parent.parent / "requirements_dev.txt"
|
||||
repo_root = _ensure_repo_root(repo_root)
|
||||
requirements_path = repo_root / "requirements_dev.txt"
|
||||
lines = read_file_lines(requirements_path)
|
||||
|
||||
for line in lines:
|
||||
@@ -68,30 +69,49 @@ def read_file_bytes(path: Path) -> bytes:
|
||||
return f.read()
|
||||
|
||||
|
||||
def calculate_clang_tidy_hash() -> str:
|
||||
def get_repo_root() -> Path:
|
||||
"""Get the repository root directory."""
|
||||
return Path(__file__).parent.parent
|
||||
|
||||
|
||||
def _ensure_repo_root(repo_root: Path | None) -> Path:
|
||||
"""Ensure repo_root is a Path, using default if None."""
|
||||
return repo_root if repo_root is not None else get_repo_root()
|
||||
|
||||
|
||||
def calculate_clang_tidy_hash(repo_root: Path | None = None) -> str:
|
||||
"""Calculate hash of clang-tidy configuration and version"""
|
||||
repo_root = _ensure_repo_root(repo_root)
|
||||
|
||||
hasher = hashlib.sha256()
|
||||
|
||||
# Hash .clang-tidy file
|
||||
clang_tidy_path = Path(__file__).parent.parent / ".clang-tidy"
|
||||
clang_tidy_path = repo_root / ".clang-tidy"
|
||||
content = read_file_bytes(clang_tidy_path)
|
||||
hasher.update(content)
|
||||
|
||||
# Hash clang-tidy version from requirements_dev.txt
|
||||
version = get_clang_tidy_version_from_requirements()
|
||||
version = get_clang_tidy_version_from_requirements(repo_root)
|
||||
hasher.update(version.encode())
|
||||
|
||||
# Hash the entire platformio.ini file
|
||||
platformio_path = Path(__file__).parent.parent / "platformio.ini"
|
||||
platformio_path = repo_root / "platformio.ini"
|
||||
platformio_content = read_file_bytes(platformio_path)
|
||||
hasher.update(platformio_content)
|
||||
|
||||
# Hash sdkconfig.defaults file
|
||||
sdkconfig_path = repo_root / "sdkconfig.defaults"
|
||||
if sdkconfig_path.exists():
|
||||
sdkconfig_content = read_file_bytes(sdkconfig_path)
|
||||
hasher.update(sdkconfig_content)
|
||||
|
||||
return hasher.hexdigest()
|
||||
|
||||
|
||||
def read_stored_hash() -> str | None:
|
||||
def read_stored_hash(repo_root: Path | None = None) -> str | None:
|
||||
"""Read the stored hash from file"""
|
||||
hash_file = Path(__file__).parent.parent / ".clang-tidy.hash"
|
||||
repo_root = _ensure_repo_root(repo_root)
|
||||
hash_file = repo_root / ".clang-tidy.hash"
|
||||
if hash_file.exists():
|
||||
lines = read_file_lines(hash_file)
|
||||
return lines[0].strip() if lines else None
|
||||
@@ -104,9 +124,10 @@ def write_file_content(path: Path, content: str) -> None:
|
||||
f.write(content)
|
||||
|
||||
|
||||
def write_hash(hash_value: str) -> None:
|
||||
def write_hash(hash_value: str, repo_root: Path | None = None) -> None:
|
||||
"""Write hash to file"""
|
||||
hash_file = Path(__file__).parent.parent / ".clang-tidy.hash"
|
||||
repo_root = _ensure_repo_root(repo_root)
|
||||
hash_file = repo_root / ".clang-tidy.hash"
|
||||
# Strip any trailing newlines to ensure consistent formatting
|
||||
write_file_content(hash_file, hash_value.strip() + "\n")
|
||||
|
||||
@@ -134,8 +155,28 @@ def main() -> None:
|
||||
stored_hash = read_stored_hash()
|
||||
|
||||
if args.check:
|
||||
# Exit 0 if full scan needed (hash changed or no hash file)
|
||||
sys.exit(0 if current_hash != stored_hash else 1)
|
||||
# Check if hash changed OR if .clang-tidy.hash was updated in this PR
|
||||
# This is used in CI to determine if a full clang-tidy scan is needed
|
||||
hash_changed = current_hash != stored_hash
|
||||
|
||||
# Lazy import to avoid requiring dependencies that aren't needed for other modes
|
||||
from helpers import changed_files # noqa: E402
|
||||
|
||||
hash_file_updated = ".clang-tidy.hash" in changed_files()
|
||||
|
||||
# Exit 0 if full scan needed
|
||||
sys.exit(0 if (hash_changed or hash_file_updated) else 1)
|
||||
|
||||
elif args.verify:
|
||||
# Verify that hash file is up to date with current configuration
|
||||
# This is used in pre-commit and CI checks to ensure hash was updated
|
||||
if current_hash != stored_hash:
|
||||
print("ERROR: Clang-tidy configuration has changed but hash not updated!")
|
||||
print(f"Expected: {current_hash}")
|
||||
print(f"Found: {stored_hash}")
|
||||
print("\nPlease run: script/clang_tidy_hash.py --update")
|
||||
sys.exit(1)
|
||||
print("Hash verification passed")
|
||||
|
||||
elif args.update:
|
||||
write_hash(current_hash)
|
||||
@@ -151,15 +192,6 @@ def main() -> None:
|
||||
print("Clang-tidy hash unchanged")
|
||||
sys.exit(0)
|
||||
|
||||
elif args.verify:
|
||||
if current_hash != stored_hash:
|
||||
print("ERROR: Clang-tidy configuration has changed but hash not updated!")
|
||||
print(f"Expected: {current_hash}")
|
||||
print(f"Found: {stored_hash}")
|
||||
print("\nPlease run: script/clang_tidy_hash.py --update")
|
||||
sys.exit(1)
|
||||
print("Hash verification passed")
|
||||
|
||||
else:
|
||||
print(f"Current hash: {current_hash}")
|
||||
print(f"Stored hash: {stored_hash}")
|
||||
|
Reference in New Issue
Block a user