mirror of
https://github.com/home-assistant/core.git
synced 2026-09-25 17:04:04 -04:00
Generate and use requirements lock files
This commit is contained in:
@@ -104,15 +104,12 @@ jobs:
|
||||
- name: Generate partial Python venv restore key
|
||||
id: generate_python_cache_key
|
||||
env:
|
||||
HASH_REQUIREMENTS_TEST: ${{ hashFiles('requirements_test.txt', 'requirements_test_pre_commit.txt') }}
|
||||
HASH_REQUIREMENTS: ${{ hashFiles('requirements.txt') }}
|
||||
HASH_REQUIREMENTS_ALL: ${{ hashFiles('requirements_all.txt') }}
|
||||
HASH_PACKAGE_CONSTRAINTS: ${{ hashFiles('homeassistant/package_constraints.txt') }}
|
||||
HASH_REQUIREMENTS_CI_LOCK: ${{ hashFiles('requirements_ci.lock') }}
|
||||
HASH_GEN_REQUIREMENTS: ${{ hashFiles('script/gen_requirements_all.py') }}
|
||||
run: |
|
||||
# Include HA_SHORT_VERSION to force the immediate creation
|
||||
# of a new uv cache entry after a version bump.
|
||||
echo "key=venv-${CACHE_VERSION}-${HA_SHORT_VERSION}-${HASH_REQUIREMENTS_TEST}-${HASH_REQUIREMENTS}-${HASH_REQUIREMENTS_ALL}-${HASH_PACKAGE_CONSTRAINTS}-${HASH_GEN_REQUIREMENTS}" >> $GITHUB_OUTPUT
|
||||
echo "key=venv-${CACHE_VERSION}-${HA_SHORT_VERSION}-${HASH_REQUIREMENTS_CI_LOCK}-${HASH_GEN_REQUIREMENTS}" >> $GITHUB_OUTPUT
|
||||
- name: Filter for core changes
|
||||
uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
|
||||
id: core
|
||||
@@ -365,7 +362,7 @@ jobs:
|
||||
RUNNER_OS: ${{ runner.os }}
|
||||
RUNNER_ARCH: ${{ runner.arch }}
|
||||
PYTHON_VERSION: ${{ steps.python.outputs.python-version }}
|
||||
HASH_FILES: ${{ hashFiles('requirements.txt', 'requirements_all.txt', 'requirements_test.txt', 'homeassistant/package_constraints.txt') }}
|
||||
HASH_FILES: ${{ hashFiles('requirements_ci.lock') }}
|
||||
run: |
|
||||
partial_key="${RUNNER_OS}-${RUNNER_ARCH}-${PYTHON_VERSION}-uv-"
|
||||
echo "partial_key=${partial_key}" >> $GITHUB_OUTPUT
|
||||
@@ -414,8 +411,7 @@ jobs:
|
||||
python -m venv venv
|
||||
. venv/bin/activate
|
||||
python --version
|
||||
uv pip install -r requirements.txt
|
||||
uv pip install -r requirements_all.txt -r requirements_test.txt
|
||||
uv pip install -r requirements_ci.lock --require-hashes
|
||||
uv pip install -e . --config-settings editable_mode=compat
|
||||
- name: Dump pip freeze
|
||||
run: |
|
||||
|
||||
+14051
File diff suppressed because it is too large
Load Diff
+14519
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,9 @@ from operator import itemgetter
|
||||
from pathlib import Path
|
||||
import pkgutil
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import tomllib
|
||||
from typing import Any
|
||||
|
||||
@@ -261,6 +263,11 @@ IGNORE_PRE_COMMIT_HOOK_ID = (
|
||||
|
||||
PACKAGE_REGEX = re.compile(r"^(?:--.+\s)?([-_\.\w\d]+).*==.+$")
|
||||
|
||||
PIP_COMPILE_LOCK_FILES = {
|
||||
"requirements_all.lock": ("requirements_all.txt",),
|
||||
"requirements_ci.lock": ("requirements_all.txt", "requirements_test.txt"),
|
||||
}
|
||||
|
||||
|
||||
def explore_module(package: str, explore_children: bool) -> list[str]:
|
||||
"""Explore the modules."""
|
||||
@@ -554,6 +561,28 @@ def diff_file(filename: str, content: str) -> list[str]:
|
||||
)
|
||||
|
||||
|
||||
def generate_lock_file(output_path: str, source_file: tuple[str, ...]) -> None:
|
||||
"""Resolve requirements_all.txt into a hash-pinned lock file.
|
||||
|
||||
This shells out to `uv pip compile --generate-hashes`, which performs a
|
||||
full networked dependency resolution, so callers should only invoke it
|
||||
when requirements/dependencies have changed.
|
||||
"""
|
||||
subprocess.run(
|
||||
[
|
||||
"uv",
|
||||
"pip",
|
||||
"compile",
|
||||
"--generate-hashes",
|
||||
"--quiet",
|
||||
"--output-file",
|
||||
output_path,
|
||||
*source_file,
|
||||
],
|
||||
check=True,
|
||||
)
|
||||
|
||||
|
||||
def main(validate: bool, ci: bool) -> int:
|
||||
"""Run the script."""
|
||||
if not Path("requirements_all.txt").is_file():
|
||||
@@ -596,6 +625,16 @@ def main(validate: bool, ci: bool) -> int:
|
||||
if diff:
|
||||
errors.append("".join(diff))
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmp_dir:
|
||||
for lock_file, source_files in PIP_COMPILE_LOCK_FILES.items():
|
||||
tmp_lock = str(Path(tmp_dir) / lock_file)
|
||||
generate_lock_file(tmp_lock, source_files)
|
||||
lock_diff = diff_file(
|
||||
lock_file, Path(tmp_lock).read_text(encoding="utf-8")
|
||||
)
|
||||
if lock_diff:
|
||||
errors.append("".join(lock_diff))
|
||||
|
||||
if errors:
|
||||
print("ERROR - FOUND THE FOLLOWING DIFFERENCES")
|
||||
print()
|
||||
@@ -607,9 +646,25 @@ def main(validate: bool, ci: bool) -> int:
|
||||
|
||||
return 0
|
||||
|
||||
sourcefile_to_lockfile = {}
|
||||
for lock_file, source_files in PIP_COMPILE_LOCK_FILES.items():
|
||||
for source_file in source_files:
|
||||
sourcefile_to_lockfile.setdefault(source_file, []).append(lock_file)
|
||||
print(sourcefile_to_lockfile)
|
||||
generate_lock_files = set()
|
||||
|
||||
for filename, content in files:
|
||||
if lock_files := sourcefile_to_lockfile.get(filename):
|
||||
file = Path(filename)
|
||||
if not file.is_file() or file.read_text(encoding="utf-8") != content:
|
||||
generate_lock_files.update(lock_files)
|
||||
|
||||
Path(filename).write_text(content)
|
||||
|
||||
for lock_file in generate_lock_files:
|
||||
source_files = PIP_COMPILE_LOCK_FILES[lock_file]
|
||||
generate_lock_file(lock_file, source_files)
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user