diff --git a/.github/workflows/builder.yml b/.github/workflows/builder.yml index d1fd9f41eea..09277721e48 100644 --- a/.github/workflows/builder.yml +++ b/.github/workflows/builder.yml @@ -95,6 +95,7 @@ jobs: packages: write id-token: write strategy: + fail-fast: false matrix: arch: ${{ fromJson(needs.init.outputs.architectures) }} steps: diff --git a/Dockerfile b/Dockerfile index da46f71ad22..700964d93ea 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,47 +6,50 @@ FROM ${BUILD_FROM} # Synchronize with homeassistant/core.py:async_stop ENV \ - S6_SERVICES_GRACETIME=240000 + S6_SERVICES_GRACETIME=240000 \ + UV_SYSTEM_PYTHON=true ARG QEMU_CPU +# Install uv +RUN pip3 install uv==0.1.22 + WORKDIR /usr/src ## Setup Home Assistant Core dependencies COPY requirements.txt homeassistant/ COPY homeassistant/package_constraints.txt homeassistant/homeassistant/ RUN \ - pip3 install \ - --only-binary=:all: \ + uv pip install \ + --no-build \ -r homeassistant/requirements.txt COPY requirements_all.txt home_assistant_frontend-* home_assistant_intents-* homeassistant/ RUN \ if ls homeassistant/home_assistant_frontend*.whl 1> /dev/null 2>&1; then \ - pip3 install homeassistant/home_assistant_frontend-*.whl; \ + uv pip install homeassistant/home_assistant_frontend-*.whl; \ fi \ && if ls homeassistant/home_assistant_intents*.whl 1> /dev/null 2>&1; then \ - pip3 install homeassistant/home_assistant_intents-*.whl; \ + uv pip install homeassistant/home_assistant_intents-*.whl; \ fi \ && if [ "${BUILD_ARCH}" = "i386" ]; then \ LD_PRELOAD="/usr/local/lib/libjemalloc.so.2" \ MALLOC_CONF="background_thread:true,metadata_thp:auto,dirty_decay_ms:20000,muzzy_decay_ms:20000" \ - linux32 pip3 install \ - --only-binary=:all: \ + linux32 uv pip install \ + --no-build \ -r homeassistant/requirements_all.txt; \ else \ LD_PRELOAD="/usr/local/lib/libjemalloc.so.2" \ MALLOC_CONF="background_thread:true,metadata_thp:auto,dirty_decay_ms:20000,muzzy_decay_ms:20000" \ - pip3 install \ - --only-binary=:all: \ + uv pip install \ + --no-build \ -r homeassistant/requirements_all.txt; \ fi ## Setup Home Assistant Core COPY . homeassistant/ RUN \ - pip3 install \ - --only-binary=:all: \ + uv pip install \ -e ./homeassistant \ && python3 -m compileall \ homeassistant/homeassistant diff --git a/requirements_test.txt b/requirements_test.txt index e189526adaf..e19cfc1a363 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -51,4 +51,4 @@ types-pytz==2023.3.1.1 types-PyYAML==6.0.12.12 types-requests==2.31.0.3 types-xmltodict==0.13.0.3 -uv==0.1.17 \ No newline at end of file +uv==0.1.22 \ No newline at end of file diff --git a/script/hassfest/docker.py b/script/hassfest/docker.py index 49b457f8a74..8a3c3b6937d 100644 --- a/script/hassfest/docker.py +++ b/script/hassfest/docker.py @@ -4,6 +4,7 @@ from homeassistant import core from homeassistant.util import executor, thread from .model import Config, Integration +from .requirements import PACKAGE_REGEX, PIP_VERSION_RANGE_SEPARATOR DOCKERFILE_TEMPLATE = r"""# Automatically generated by hassfest. # @@ -13,47 +14,50 @@ FROM ${{BUILD_FROM}} # Synchronize with homeassistant/core.py:async_stop ENV \ - S6_SERVICES_GRACETIME={timeout} + S6_SERVICES_GRACETIME={timeout} \ + UV_SYSTEM_PYTHON=true ARG QEMU_CPU +# Install uv +RUN pip3 install uv=={uv_version} + WORKDIR /usr/src ## Setup Home Assistant Core dependencies COPY requirements.txt homeassistant/ COPY homeassistant/package_constraints.txt homeassistant/homeassistant/ RUN \ - pip3 install \ - --only-binary=:all: \ + uv pip install \ + --no-build \ -r homeassistant/requirements.txt COPY requirements_all.txt home_assistant_frontend-* home_assistant_intents-* homeassistant/ RUN \ if ls homeassistant/home_assistant_frontend*.whl 1> /dev/null 2>&1; then \ - pip3 install homeassistant/home_assistant_frontend-*.whl; \ + uv pip install homeassistant/home_assistant_frontend-*.whl; \ fi \ && if ls homeassistant/home_assistant_intents*.whl 1> /dev/null 2>&1; then \ - pip3 install homeassistant/home_assistant_intents-*.whl; \ + uv pip install homeassistant/home_assistant_intents-*.whl; \ fi \ && if [ "${{BUILD_ARCH}}" = "i386" ]; then \ LD_PRELOAD="/usr/local/lib/libjemalloc.so.2" \ MALLOC_CONF="background_thread:true,metadata_thp:auto,dirty_decay_ms:20000,muzzy_decay_ms:20000" \ - linux32 pip3 install \ - --only-binary=:all: \ + linux32 uv pip install \ + --no-build \ -r homeassistant/requirements_all.txt; \ else \ LD_PRELOAD="/usr/local/lib/libjemalloc.so.2" \ MALLOC_CONF="background_thread:true,metadata_thp:auto,dirty_decay_ms:20000,muzzy_decay_ms:20000" \ - pip3 install \ - --only-binary=:all: \ + uv pip install \ + --no-build \ -r homeassistant/requirements_all.txt; \ fi ## Setup Home Assistant Core COPY . homeassistant/ RUN \ - pip3 install \ - --only-binary=:all: \ + uv pip install \ -e ./homeassistant \ && python3 -m compileall \ homeassistant/homeassistant @@ -65,6 +69,28 @@ WORKDIR /config """ +def _get_uv_version() -> str: + with open("requirements_test.txt") as fp: + for _, line in enumerate(fp): + if match := PACKAGE_REGEX.match(line): + pkg, sep, version = match.groups() + + if pkg != "uv": + continue + + if sep != "==" or not version: + raise RuntimeError( + 'Requirement uv need to be pinned "uv==".' + ) + + for part in version.split(";", 1)[0].split(","): + version_part = PIP_VERSION_RANGE_SEPARATOR.match(part) + if version_part: + return version_part.group(2) + + raise RuntimeError("Invalid uv requirement in requirements_test.txt") + + def _generate_dockerfile() -> str: timeout = ( core.STOPPING_STAGE_SHUTDOWN_TIMEOUT @@ -75,7 +101,9 @@ def _generate_dockerfile() -> str: + thread.THREADING_SHUTDOWN_TIMEOUT + 10 ) - return DOCKERFILE_TEMPLATE.format(timeout=timeout * 1000) + return DOCKERFILE_TEMPLATE.format( + timeout=timeout * 1000, uv_version=_get_uv_version() + ) def validate(integrations: dict[str, Integration], config: Config) -> None: