From 96b98c9cb970ff6677a03f4dc359e990484eef29 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Sat, 14 Feb 2026 12:01:29 +0100 Subject: [PATCH] Remove YAML anchors / expand GitHub CI workflows (#162987) --- .github/workflows/builder.yml | 8 +- .github/workflows/ci.yaml | 557 ++++++++++++++++++++++++---------- .github/workflows/wheels.yml | 52 ++-- 3 files changed, 436 insertions(+), 181 deletions(-) diff --git a/.github/workflows/builder.yml b/.github/workflows/builder.yml index d0325a5ed99..fd263a95913 100644 --- a/.github/workflows/builder.yml +++ b/.github/workflows/builder.yml @@ -190,8 +190,7 @@ jobs: username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - - &install_cosign - name: Install Cosign + - name: Install Cosign uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0 with: cosign-release: "v2.5.3" @@ -355,7 +354,10 @@ jobs: matrix: registry: ["ghcr.io/home-assistant", "docker.io/homeassistant"] steps: - - *install_cosign + - name: Install Cosign + uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0 + with: + cosign-release: "v2.5.3" - name: Login to DockerHub if: matrix.registry == 'docker.io/homeassistant' diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 580b0918eba..fe8e83fe882 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -74,7 +74,7 @@ concurrency: jobs: info: name: Collect information & changes data - runs-on: &runs-on-ubuntu ubuntu-24.04 + runs-on: ubuntu-24.04 outputs: # In case of issues with the partial run, use the following line instead: # test_full_suite: 'true' @@ -95,8 +95,7 @@ jobs: lint_only: ${{ steps.info.outputs.lint_only }} skip_coverage: ${{ steps.info.outputs.skip_coverage }} steps: - - &checkout - name: Check out code from GitHub + - name: Check out code from GitHub uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Generate partial Python venv restore key id: generate_python_cache_key @@ -200,7 +199,7 @@ jobs: || [[ "${{ github.event.inputs.pylint-only }}" == "true" ]] \ || [[ "${{ github.event.inputs.mypy-only }}" == "true" ]] \ || [[ "${{ github.event.inputs.audit-licenses-only }}" == "true" ]] \ - || [[ "${{ github.event_name }}" == "push" \ + || [[ "${{ github.event_name }}" == "push" \ && "${{ github.event.repository.full_name }}" != "home-assistant/core" ]]; then lint_only="true" @@ -239,14 +238,15 @@ jobs: prek: name: Run prek checks - runs-on: *runs-on-ubuntu + runs-on: ubuntu-24.04 needs: [info] if: | github.event.inputs.pylint-only != 'true' && github.event.inputs.mypy-only != 'true' && github.event.inputs.audit-licenses-only != 'true' steps: - - *checkout + - name: Check out code from GitHub + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Register problem matchers run: | echo "::add-matcher::.github/workflows/matchers/yamllint.json" @@ -261,7 +261,7 @@ jobs: lint-hadolint: name: Check ${{ matrix.file }} - runs-on: *runs-on-ubuntu + runs-on: ubuntu-24.04 needs: [info] if: | github.event.inputs.pylint-only != 'true' @@ -275,7 +275,8 @@ jobs: - Dockerfile.dev - script/hassfest/docker/Dockerfile steps: - - *checkout + - name: Check out code from GitHub + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Register hadolint problem matcher run: | echo "::add-matcher::.github/workflows/matchers/hadolint.json" @@ -286,18 +287,18 @@ jobs: base: name: Prepare dependencies - runs-on: *runs-on-ubuntu + runs-on: ubuntu-24.04 needs: [info] timeout-minutes: 60 strategy: matrix: - python-version: &matrix-python ${{ fromJson(needs.info.outputs.python_versions) }} + python-version: ${{ fromJson(needs.info.outputs.python_versions) }} steps: - - *checkout - - &setup-python-matrix - name: Set up Python ${{ matrix.python-version }} + - name: Check out code from GitHub + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: Set up Python ${{ matrix.python-version }} id: python - uses: &actions-setup-python actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: ${{ matrix.python-version }} check-latest: true @@ -310,15 +311,15 @@ jobs: env.HA_SHORT_VERSION }}-$(date -u '+%Y-%m-%dT%H:%M:%s')" >> $GITHUB_OUTPUT - name: Restore base Python virtual environment id: cache-venv - uses: &actions-cache actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 with: path: venv - key: &key-python-venv >- + key: >- ${{ runner.os }}-${{ runner.arch }}-${{ steps.python.outputs.python-version }}-${{ needs.info.outputs.python_cache_key }} - name: Restore uv wheel cache if: steps.cache-venv.outputs.cache-hit != 'true' - uses: *actions-cache + uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 with: path: ${{ env.UV_CACHE_DIR }} key: >- @@ -330,13 +331,13 @@ jobs: env.HA_SHORT_VERSION }}- - name: Check if apt cache exists id: cache-apt-check - uses: *actions-cache + uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 with: lookup-only: ${{ steps.cache-venv.outputs.cache-hit == 'true' }} - path: &path-apt-cache | + path: | ${{ env.APT_CACHE_DIR }} ${{ env.APT_LIST_CACHE_DIR }} - key: &key-apt-cache >- + key: >- ${{ runner.os }}-${{ runner.arch }}-${{ needs.info.outputs.apt_cache_key }} - name: Install additional OS dependencies if: | @@ -374,10 +375,13 @@ jobs: fi - name: Save apt cache if: steps.cache-apt-check.outputs.cache-hit != 'true' - uses: &actions-cache-save actions/cache/save@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + uses: actions/cache/save@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 with: - path: *path-apt-cache - key: *key-apt-cache + path: | + ${{ env.APT_CACHE_DIR }} + ${{ env.APT_LIST_CACHE_DIR }} + key: >- + ${{ runner.os }}-${{ runner.arch }}-${{ needs.info.outputs.apt_cache_key }} - name: Create Python virtual environment if: steps.cache-venv.outputs.cache-hit != 'true' run: | @@ -397,7 +401,7 @@ jobs: python --version uv pip freeze >> pip_freeze.txt - name: Upload pip_freeze artifact - uses: &actions-upload-artifact actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: pip-freeze-${{ matrix.python-version }} path: pip_freeze.txt @@ -407,15 +411,14 @@ jobs: - name: Remove generated requirements_all if: steps.cache-venv.outputs.cache-hit != 'true' run: rm requirements_all_pytest.txt requirements_all_wheels_*.txt - - &check-dirty - name: Check dirty + - name: Check dirty run: | ./script/check_dirty hassfest: name: Check hassfest - runs-on: *runs-on-ubuntu - needs: &needs-base + runs-on: ubuntu-24.04 + needs: - info - base if: | @@ -423,13 +426,15 @@ jobs: && github.event.inputs.mypy-only != 'true' && github.event.inputs.audit-licenses-only != 'true' steps: - - &cache-restore-apt - name: Restore apt cache - uses: &actions-cache-restore actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + - name: Restore apt cache + uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 with: - path: *path-apt-cache + path: | + ${{ env.APT_CACHE_DIR }} + ${{ env.APT_LIST_CACHE_DIR }} fail-on-cache-miss: true - key: *key-apt-cache + key: >- + ${{ runner.os }}-${{ runner.arch }}-${{ needs.info.outputs.apt_cache_key }} - name: Install additional OS dependencies timeout-minutes: 10 run: | @@ -441,22 +446,23 @@ jobs: -o Dir::Cache=${{ env.APT_CACHE_DIR }} \ -o Dir::State::Lists=${{ env.APT_LIST_CACHE_DIR }} \ libturbojpeg - - *checkout - - &setup-python-default - name: Set up Python ${{ env.DEFAULT_PYTHON }} + - name: Check out code from GitHub + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: Set up Python ${{ env.DEFAULT_PYTHON }} id: python - uses: *actions-setup-python + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: ${{ env.DEFAULT_PYTHON }} check-latest: true - - &cache-restore-python-default - name: Restore full Python ${{ env.DEFAULT_PYTHON }} virtual environment + - name: Restore full Python ${{ env.DEFAULT_PYTHON }} virtual environment id: cache-venv - uses: *actions-cache-restore + uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 with: path: venv fail-on-cache-miss: true - key: *key-python-venv + key: >- + ${{ runner.os }}-${{ runner.arch }}-${{ steps.python.outputs.python-version }}-${{ + needs.info.outputs.python_cache_key }} - name: Run hassfest run: | . venv/bin/activate @@ -464,16 +470,32 @@ jobs: gen-requirements-all: name: Check all requirements - runs-on: *runs-on-ubuntu - needs: *needs-base + runs-on: ubuntu-24.04 + needs: + - info + - base if: | github.event.inputs.pylint-only != 'true' && github.event.inputs.mypy-only != 'true' && github.event.inputs.audit-licenses-only != 'true' steps: - - *checkout - - *setup-python-default - - *cache-restore-python-default + - name: Check out code from GitHub + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: Set up Python ${{ env.DEFAULT_PYTHON }} + id: python + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + with: + python-version: ${{ env.DEFAULT_PYTHON }} + check-latest: true + - name: Restore full Python ${{ env.DEFAULT_PYTHON }} virtual environment + id: cache-venv + uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + with: + path: venv + fail-on-cache-miss: true + key: >- + ${{ runner.os }}-${{ runner.arch }}-${{ steps.python.outputs.python-version }}-${{ + needs.info.outputs.python_cache_key }} - name: Run gen_requirements_all.py run: | . venv/bin/activate @@ -481,7 +503,7 @@ jobs: gen-copilot-instructions: name: Check copilot instructions - runs-on: *runs-on-ubuntu + runs-on: ubuntu-24.04 needs: - info if: | @@ -489,23 +511,32 @@ jobs: && github.event.inputs.mypy-only != 'true' && github.event.inputs.audit-licenses-only != 'true' steps: - - *checkout - - *setup-python-default + - name: Check out code from GitHub + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: Set up Python ${{ env.DEFAULT_PYTHON }} + id: python + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + with: + python-version: ${{ env.DEFAULT_PYTHON }} + check-latest: true - name: Run gen_copilot_instructions.py run: | python -m script.gen_copilot_instructions validate dependency-review: name: Dependency review - runs-on: *runs-on-ubuntu - needs: *needs-base + runs-on: ubuntu-24.04 + needs: + - info + - base if: | github.event.inputs.pylint-only != 'true' && github.event.inputs.mypy-only != 'true' && needs.info.outputs.requirements == 'true' && github.event_name == 'pull_request' steps: - - *checkout + - name: Check out code from GitHub + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Dependency review uses: actions/dependency-review-action@3c4e3dcb1aa7874d2c16be7d79418e9b7efd6261 # v4.8.2 with: @@ -513,8 +544,10 @@ jobs: audit-licenses: name: Audit licenses - runs-on: *runs-on-ubuntu - needs: *needs-base + runs-on: ubuntu-24.04 + needs: + - info + - base if: | (github.event.inputs.pylint-only != 'true' && github.event.inputs.mypy-only != 'true' @@ -523,24 +556,31 @@ jobs: strategy: fail-fast: false matrix: - python-version: *matrix-python + python-version: ${{ fromJson(needs.info.outputs.python_versions) }} steps: - - *checkout - - *setup-python-matrix - - &cache-restore-python-matrix - name: Restore full Python ${{ matrix.python-version }} virtual environment + - name: Check out code from GitHub + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: Set up Python ${{ matrix.python-version }} + id: python + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + with: + python-version: ${{ matrix.python-version }} + check-latest: true + - name: Restore full Python ${{ matrix.python-version }} virtual environment id: cache-venv - uses: *actions-cache-restore + uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 with: path: venv fail-on-cache-miss: true - key: *key-python-venv + key: >- + ${{ runner.os }}-${{ runner.arch }}-${{ steps.python.outputs.python-version }}-${{ + needs.info.outputs.python_cache_key }} - name: Extract license data run: | . venv/bin/activate python -m script.licenses extract --output-file=licenses-${{ matrix.python-version }}.json - name: Upload licenses - uses: *actions-upload-artifact + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: licenses-${{ github.run_number }}-${{ matrix.python-version }} path: licenses-${{ matrix.python-version }}.json @@ -551,19 +591,34 @@ jobs: pylint: name: Check pylint - runs-on: *runs-on-ubuntu - needs: *needs-base + runs-on: ubuntu-24.04 + needs: + - info + - base timeout-minutes: 20 if: | github.event.inputs.mypy-only != 'true' && github.event.inputs.audit-licenses-only != 'true' || github.event.inputs.pylint-only == 'true' steps: - - *checkout - - *setup-python-default - - *cache-restore-python-default - - &problem-matcher-pylint - name: Register pylint problem matcher + - name: Check out code from GitHub + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: Set up Python ${{ env.DEFAULT_PYTHON }} + id: python + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + with: + python-version: ${{ env.DEFAULT_PYTHON }} + check-latest: true + - name: Restore full Python ${{ env.DEFAULT_PYTHON }} virtual environment + id: cache-venv + uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + with: + path: venv + fail-on-cache-miss: true + key: >- + ${{ runner.os }}-${{ runner.arch }}-${{ steps.python.outputs.python-version }}-${{ + needs.info.outputs.python_cache_key }} + - name: Register pylint problem matcher run: | echo "::add-matcher::.github/workflows/matchers/pylint.json" - name: Run pylint (fully) @@ -582,8 +637,10 @@ jobs: pylint-tests: name: Check pylint on tests - runs-on: *runs-on-ubuntu - needs: *needs-base + runs-on: ubuntu-24.04 + needs: + - info + - base timeout-minutes: 20 if: | (github.event.inputs.mypy-only != 'true' @@ -591,10 +648,26 @@ jobs: || github.event.inputs.pylint-only == 'true') && (needs.info.outputs.tests_glob || needs.info.outputs.test_full_suite == 'true') steps: - - *checkout - - *setup-python-default - - *cache-restore-python-default - - *problem-matcher-pylint + - name: Check out code from GitHub + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: Set up Python ${{ env.DEFAULT_PYTHON }} + id: python + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + with: + python-version: ${{ env.DEFAULT_PYTHON }} + check-latest: true + - name: Restore full Python ${{ env.DEFAULT_PYTHON }} virtual environment + id: cache-venv + uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + with: + path: venv + fail-on-cache-miss: true + key: >- + ${{ runner.os }}-${{ runner.arch }}-${{ steps.python.outputs.python-version }}-${{ + needs.info.outputs.python_cache_key }} + - name: Register pylint problem matcher + run: | + echo "::add-matcher::.github/workflows/matchers/pylint.json" - name: Run pylint (fully) if: needs.info.outputs.test_full_suite == 'true' run: | @@ -611,15 +684,23 @@ jobs: mypy: name: Check mypy - runs-on: *runs-on-ubuntu - needs: *needs-base + runs-on: ubuntu-24.04 + needs: + - info + - base if: | github.event.inputs.pylint-only != 'true' && github.event.inputs.audit-licenses-only != 'true' || github.event.inputs.mypy-only == 'true' steps: - - *checkout - - *setup-python-default + - name: Check out code from GitHub + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: Set up Python ${{ env.DEFAULT_PYTHON }} + id: python + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + with: + python-version: ${{ env.DEFAULT_PYTHON }} + check-latest: true - name: Generate partial mypy restore key id: generate-mypy-key run: | @@ -627,9 +708,17 @@ jobs: echo "version=$mypy_version" >> $GITHUB_OUTPUT echo "key=mypy-${{ env.MYPY_CACHE_VERSION }}-$mypy_version-${{ env.HA_SHORT_VERSION }}-$(date -u '+%Y-%m-%dT%H:%M:%s')" >> $GITHUB_OUTPUT - - *cache-restore-python-default + - name: Restore full Python ${{ env.DEFAULT_PYTHON }} virtual environment + id: cache-venv + uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + with: + path: venv + fail-on-cache-miss: true + key: >- + ${{ runner.os }}-${{ runner.arch }}-${{ steps.python.outputs.python-version }}-${{ + needs.info.outputs.python_cache_key }} - name: Restore mypy cache - uses: *actions-cache + uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 with: path: .mypy_cache key: >- @@ -658,7 +747,7 @@ jobs: prepare-pytest-full: name: Split tests for full run - runs-on: *runs-on-ubuntu + runs-on: ubuntu-24.04 if: | needs.info.outputs.lint_only != 'true' && needs.info.outputs.test_full_suite == 'true' @@ -670,7 +759,15 @@ jobs: - prek - mypy steps: - - *cache-restore-apt + - name: Restore apt cache + uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + with: + path: | + ${{ env.APT_CACHE_DIR }} + ${{ env.APT_LIST_CACHE_DIR }} + fail-on-cache-miss: true + key: >- + ${{ runner.os }}-${{ runner.arch }}-${{ needs.info.outputs.apt_cache_key }} - name: Install additional OS dependencies timeout-minutes: 10 run: | @@ -684,15 +781,29 @@ jobs: bluez \ ffmpeg \ libturbojpeg - - *checkout - - *setup-python-default - - *cache-restore-python-default + - name: Check out code from GitHub + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: Set up Python ${{ env.DEFAULT_PYTHON }} + id: python + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + with: + python-version: ${{ env.DEFAULT_PYTHON }} + check-latest: true + - name: Restore full Python ${{ env.DEFAULT_PYTHON }} virtual environment + id: cache-venv + uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + with: + path: venv + fail-on-cache-miss: true + key: >- + ${{ runner.os }}-${{ runner.arch }}-${{ steps.python.outputs.python-version }}-${{ + needs.info.outputs.python_cache_key }} - name: Run split_tests.py run: | . venv/bin/activate python -m script.split_tests ${{ needs.info.outputs.test_group_count }} tests - name: Upload pytest_buckets - uses: *actions-upload-artifact + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: pytest_buckets path: pytest_buckets.txt @@ -700,7 +811,7 @@ jobs: pytest-full: name: Run tests Python ${{ matrix.python-version }} (${{ matrix.group }}) - runs-on: *runs-on-ubuntu + runs-on: ubuntu-24.04 needs: - info - base @@ -715,10 +826,18 @@ jobs: strategy: fail-fast: false matrix: - python-version: *matrix-python - group: &matrix-group ${{ fromJson(needs.info.outputs.test_groups) }} + python-version: ${{ fromJson(needs.info.outputs.python_versions) }} + group: ${{ fromJson(needs.info.outputs.test_groups) }} steps: - - *cache-restore-apt + - name: Restore apt cache + uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + with: + path: | + ${{ env.APT_CACHE_DIR }} + ${{ env.APT_LIST_CACHE_DIR }} + fail-on-cache-miss: true + key: >- + ${{ runner.os }}-${{ runner.arch }}-${{ needs.info.outputs.apt_cache_key }} - name: Install additional OS dependencies timeout-minutes: 10 run: | @@ -733,23 +852,34 @@ jobs: ffmpeg \ libturbojpeg \ libxml2-utils - - *checkout - - *setup-python-matrix - - *cache-restore-python-matrix - - &problem-matcher-python - name: Register Python problem matcher + - name: Check out code from GitHub + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: Set up Python ${{ matrix.python-version }} + id: python + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + with: + python-version: ${{ matrix.python-version }} + check-latest: true + - name: Restore full Python ${{ matrix.python-version }} virtual environment + id: cache-venv + uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + with: + path: venv + fail-on-cache-miss: true + key: >- + ${{ runner.os }}-${{ runner.arch }}-${{ steps.python.outputs.python-version }}-${{ + needs.info.outputs.python_cache_key }} + - name: Register Python problem matcher run: | echo "::add-matcher::.github/workflows/matchers/python.json" - - &problem-matcher-pytest-slow - name: Register pytest slow test problem matcher + - name: Register pytest slow test problem matcher run: | echo "::add-matcher::.github/workflows/matchers/pytest-slow.json" - name: Download pytest_buckets - uses: &actions-download-artifact actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 with: name: pytest_buckets - - &compile-english-translations - name: Compile English translations + - name: Compile English translations run: | . venv/bin/activate python3 -m script.translations develop --all @@ -785,20 +915,19 @@ jobs: 2>&1 | tee pytest-${{ matrix.python-version }}-${{ matrix.group }}.txt - name: Upload pytest output if: success() || failure() && steps.pytest-full.conclusion == 'failure' - uses: *actions-upload-artifact + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: pytest-${{ github.run_number }}-${{ matrix.python-version }}-${{ matrix.group }} path: pytest-*.txt overwrite: true - name: Upload coverage artifact if: needs.info.outputs.skip_coverage != 'true' - uses: *actions-upload-artifact + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: coverage-${{ matrix.python-version }}-${{ matrix.group }} path: coverage.xml overwrite: true - - &beautify-test-results - name: Beautify test results + - name: Beautify test results # For easier identification of parsing errors if: needs.info.outputs.skip_coverage != 'true' run: | @@ -806,17 +935,19 @@ jobs: mv "junit.xml-tmp" "junit.xml" - name: Upload test results artifact if: needs.info.outputs.skip_coverage != 'true' && !cancelled() - uses: *actions-upload-artifact + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: test-results-full-${{ matrix.python-version }}-${{ matrix.group }} path: junit.xml - name: Remove pytest_buckets run: rm pytest_buckets.txt - - *check-dirty + - name: Check dirty + run: | + ./script/check_dirty pytest-mariadb: name: Run ${{ matrix.mariadb-group }} tests Python ${{ matrix.python-version }} - runs-on: *runs-on-ubuntu + runs-on: ubuntu-24.04 services: mariadb: image: ${{ matrix.mariadb-group }} @@ -838,10 +969,18 @@ jobs: strategy: fail-fast: false matrix: - python-version: *matrix-python + python-version: ${{ fromJson(needs.info.outputs.python_versions) }} mariadb-group: ${{ fromJson(needs.info.outputs.mariadb_groups) }} steps: - - *cache-restore-apt + - name: Restore apt cache + uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + with: + path: | + ${{ env.APT_CACHE_DIR }} + ${{ env.APT_LIST_CACHE_DIR }} + fail-on-cache-miss: true + key: >- + ${{ runner.os }}-${{ runner.arch }}-${{ needs.info.outputs.apt_cache_key }} - name: Install additional OS dependencies timeout-minutes: 10 run: | @@ -857,16 +996,37 @@ jobs: libturbojpeg \ libmariadb-dev-compat \ libxml2-utils - - *checkout - - *setup-python-matrix - - *cache-restore-python-matrix - - *problem-matcher-python - - *problem-matcher-pytest-slow + - name: Check out code from GitHub + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: Set up Python ${{ matrix.python-version }} + id: python + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + with: + python-version: ${{ matrix.python-version }} + check-latest: true + - name: Restore full Python ${{ matrix.python-version }} virtual environment + id: cache-venv + uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + with: + path: venv + fail-on-cache-miss: true + key: >- + ${{ runner.os }}-${{ runner.arch }}-${{ steps.python.outputs.python-version }}-${{ + needs.info.outputs.python_cache_key }} + - name: Register Python problem matcher + run: | + echo "::add-matcher::.github/workflows/matchers/python.json" + - name: Register pytest slow test problem matcher + run: | + echo "::add-matcher::.github/workflows/matchers/pytest-slow.json" - name: Install SQL Python libraries run: | . venv/bin/activate uv pip install mysqlclient sqlalchemy_utils - - *compile-english-translations + - name: Compile English translations + run: | + . venv/bin/activate + python3 -m script.translations develop --all - name: Run pytest (partially) timeout-minutes: 20 id: pytest-partial @@ -905,7 +1065,7 @@ jobs: 2>&1 | tee pytest-${{ matrix.python-version }}-${mariadb}.txt - name: Upload pytest output if: success() || failure() && steps.pytest-partial.conclusion == 'failure' - uses: *actions-upload-artifact + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: pytest-${{ github.run_number }}-${{ matrix.python-version }}-${{ steps.pytest-partial.outputs.mariadb }} @@ -913,25 +1073,32 @@ jobs: overwrite: true - name: Upload coverage artifact if: needs.info.outputs.skip_coverage != 'true' - uses: *actions-upload-artifact + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: coverage-${{ matrix.python-version }}-${{ steps.pytest-partial.outputs.mariadb }} path: coverage.xml overwrite: true - - *beautify-test-results + - name: Beautify test results + # For easier identification of parsing errors + if: needs.info.outputs.skip_coverage != 'true' + run: | + xmllint --format "junit.xml" > "junit.xml-tmp" + mv "junit.xml-tmp" "junit.xml" - name: Upload test results artifact if: needs.info.outputs.skip_coverage != 'true' && !cancelled() - uses: *actions-upload-artifact + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: test-results-mariadb-${{ matrix.python-version }}-${{ steps.pytest-partial.outputs.mariadb }} path: junit.xml - - *check-dirty + - name: Check dirty + run: | + ./script/check_dirty pytest-postgres: name: Run ${{ matrix.postgresql-group }} tests Python ${{ matrix.python-version }} - runs-on: *runs-on-ubuntu + runs-on: ubuntu-24.04 services: postgres: image: ${{ matrix.postgresql-group }} @@ -953,10 +1120,18 @@ jobs: strategy: fail-fast: false matrix: - python-version: *matrix-python + python-version: ${{ fromJson(needs.info.outputs.python_versions) }} postgresql-group: ${{ fromJson(needs.info.outputs.postgresql_groups) }} steps: - - *cache-restore-apt + - name: Restore apt cache + uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + with: + path: | + ${{ env.APT_CACHE_DIR }} + ${{ env.APT_LIST_CACHE_DIR }} + fail-on-cache-miss: true + key: >- + ${{ runner.os }}-${{ runner.arch }}-${{ needs.info.outputs.apt_cache_key }} - name: Install additional OS dependencies timeout-minutes: 10 run: | @@ -974,16 +1149,37 @@ jobs: sudo /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh -y sudo apt-get -y install \ postgresql-server-dev-14 - - *checkout - - *setup-python-matrix - - *cache-restore-python-matrix - - *problem-matcher-python - - *problem-matcher-pytest-slow + - name: Check out code from GitHub + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: Set up Python ${{ matrix.python-version }} + id: python + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + with: + python-version: ${{ matrix.python-version }} + check-latest: true + - name: Restore full Python ${{ matrix.python-version }} virtual environment + id: cache-venv + uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + with: + path: venv + fail-on-cache-miss: true + key: >- + ${{ runner.os }}-${{ runner.arch }}-${{ steps.python.outputs.python-version }}-${{ + needs.info.outputs.python_cache_key }} + - name: Register Python problem matcher + run: | + echo "::add-matcher::.github/workflows/matchers/python.json" + - name: Register pytest slow test problem matcher + run: | + echo "::add-matcher::.github/workflows/matchers/pytest-slow.json" - name: Install SQL Python libraries run: | . venv/bin/activate uv pip install psycopg2 sqlalchemy_utils - - *compile-english-translations + - name: Compile English translations + run: | + . venv/bin/activate + python3 -m script.translations develop --all - name: Run pytest (partially) timeout-minutes: 20 id: pytest-partial @@ -1023,7 +1219,7 @@ jobs: 2>&1 | tee pytest-${{ matrix.python-version }}-${postgresql}.txt - name: Upload pytest output if: success() || failure() && steps.pytest-partial.conclusion == 'failure' - uses: *actions-upload-artifact + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: pytest-${{ github.run_number }}-${{ matrix.python-version }}-${{ steps.pytest-partial.outputs.postgresql }} @@ -1031,25 +1227,32 @@ jobs: overwrite: true - name: Upload coverage artifact if: needs.info.outputs.skip_coverage != 'true' - uses: *actions-upload-artifact + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: coverage-${{ matrix.python-version }}-${{ steps.pytest-partial.outputs.postgresql }} path: coverage.xml overwrite: true - - *beautify-test-results + - name: Beautify test results + # For easier identification of parsing errors + if: needs.info.outputs.skip_coverage != 'true' + run: | + xmllint --format "junit.xml" > "junit.xml-tmp" + mv "junit.xml-tmp" "junit.xml" - name: Upload test results artifact if: needs.info.outputs.skip_coverage != 'true' && !cancelled() - uses: *actions-upload-artifact + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: test-results-postgres-${{ matrix.python-version }}-${{ steps.pytest-partial.outputs.postgresql }} path: junit.xml - - *check-dirty + - name: Check dirty + run: | + ./script/check_dirty coverage-full: name: Upload test coverage to Codecov (full suite) - runs-on: *runs-on-ubuntu + runs-on: ubuntu-24.04 needs: - info - pytest-full @@ -1058,9 +1261,10 @@ jobs: timeout-minutes: 10 if: needs.info.outputs.skip_coverage != 'true' steps: - - *checkout + - name: Check out code from GitHub + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Download all coverage artifacts - uses: *actions-download-artifact + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 with: pattern: coverage-* - name: Upload coverage to Codecov @@ -1073,7 +1277,7 @@ jobs: pytest-partial: name: Run tests Python ${{ matrix.python-version }} (${{ matrix.group }}) - runs-on: *runs-on-ubuntu + runs-on: ubuntu-24.04 needs: - info - base @@ -1088,10 +1292,18 @@ jobs: strategy: fail-fast: false matrix: - python-version: *matrix-python - group: *matrix-group + python-version: ${{ fromJson(needs.info.outputs.python_versions) }} + group: ${{ fromJson(needs.info.outputs.test_groups) }} steps: - - *cache-restore-apt + - name: Restore apt cache + uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + with: + path: | + ${{ env.APT_CACHE_DIR }} + ${{ env.APT_LIST_CACHE_DIR }} + fail-on-cache-miss: true + key: >- + ${{ runner.os }}-${{ runner.arch }}-${{ needs.info.outputs.apt_cache_key }} - name: Install additional OS dependencies timeout-minutes: 10 run: | @@ -1106,12 +1318,33 @@ jobs: ffmpeg \ libturbojpeg \ libxml2-utils - - *checkout - - *setup-python-matrix - - *cache-restore-python-matrix - - *problem-matcher-python - - *problem-matcher-pytest-slow - - *compile-english-translations + - name: Check out code from GitHub + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: Set up Python ${{ matrix.python-version }} + id: python + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + with: + python-version: ${{ matrix.python-version }} + check-latest: true + - name: Restore full Python ${{ matrix.python-version }} virtual environment + id: cache-venv + uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + with: + path: venv + fail-on-cache-miss: true + key: >- + ${{ runner.os }}-${{ runner.arch }}-${{ steps.python.outputs.python-version }}-${{ + needs.info.outputs.python_cache_key }} + - name: Register Python problem matcher + run: | + echo "::add-matcher::.github/workflows/matchers/python.json" + - name: Register pytest slow test problem matcher + run: | + echo "::add-matcher::.github/workflows/matchers/pytest-slow.json" + - name: Compile English translations + run: | + . venv/bin/activate + python3 -m script.translations develop --all - name: Run pytest timeout-minutes: 10 id: pytest-partial @@ -1151,39 +1384,47 @@ jobs: 2>&1 | tee pytest-${{ matrix.python-version }}-${{ matrix.group }}.txt - name: Upload pytest output if: success() || failure() && steps.pytest-partial.conclusion == 'failure' - uses: *actions-upload-artifact + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: pytest-${{ github.run_number }}-${{ matrix.python-version }}-${{ matrix.group }} path: pytest-*.txt overwrite: true - name: Upload coverage artifact if: needs.info.outputs.skip_coverage != 'true' - uses: *actions-upload-artifact + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: coverage-${{ matrix.python-version }}-${{ matrix.group }} path: coverage.xml overwrite: true - - *beautify-test-results + - name: Beautify test results + # For easier identification of parsing errors + if: needs.info.outputs.skip_coverage != 'true' + run: | + xmllint --format "junit.xml" > "junit.xml-tmp" + mv "junit.xml-tmp" "junit.xml" - name: Upload test results artifact if: needs.info.outputs.skip_coverage != 'true' && !cancelled() - uses: *actions-upload-artifact + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: test-results-partial-${{ matrix.python-version }}-${{ matrix.group }} path: junit.xml - - *check-dirty + - name: Check dirty + run: | + ./script/check_dirty coverage-partial: name: Upload test coverage to Codecov (partial suite) if: needs.info.outputs.skip_coverage != 'true' - runs-on: *runs-on-ubuntu + runs-on: ubuntu-24.04 timeout-minutes: 10 needs: - info - pytest-partial steps: - - *checkout + - name: Check out code from GitHub + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Download all coverage artifacts - uses: *actions-download-artifact + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 with: pattern: coverage-* - name: Upload coverage to Codecov @@ -1195,7 +1436,7 @@ jobs: upload-test-results: name: Upload test results to Codecov - runs-on: *runs-on-ubuntu + runs-on: ubuntu-24.04 needs: - info - pytest-partial @@ -1212,7 +1453,7 @@ jobs: && needs.info.outputs.skip_coverage != 'true' && !cancelled() steps: - name: Download all coverage artifacts - uses: *actions-download-artifact + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 with: pattern: test-results-* - name: Upload test results to Codecov diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index a7e85354437..1e83a202503 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -29,8 +29,7 @@ jobs: if: github.repository_owner == 'home-assistant' runs-on: ubuntu-latest steps: - - &checkout - name: Checkout the repository + - name: Checkout the repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Python ${{ env.DEFAULT_PYTHON }} @@ -74,7 +73,7 @@ jobs: ) > .env_file - name: Upload env_file - uses: &actions-upload-artifact actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: env_file path: ./.env_file @@ -82,7 +81,7 @@ jobs: overwrite: true - name: Upload requirements_diff - uses: *actions-upload-artifact + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: requirements_diff path: ./requirements_diff.txt @@ -94,7 +93,7 @@ jobs: python -m script.gen_requirements_all ci - name: Upload requirements_all_wheels - uses: *actions-upload-artifact + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: requirements_all_wheels path: ./requirements_all_wheels_*.txt @@ -106,7 +105,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: fail-fast: false - matrix: &matrix-build + matrix: abi: ["cp313", "cp314"] arch: ["amd64", "aarch64"] include: @@ -115,17 +114,16 @@ jobs: - arch: aarch64 os: ubuntu-24.04-arm steps: - - *checkout + - name: Checkout the repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - &download-env-file - name: Download env_file - uses: &actions-download-artifact actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + - name: Download env_file + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 with: name: env_file - - &download-requirements-diff - name: Download requirements_diff - uses: *actions-download-artifact + - name: Download requirements_diff + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 with: name: requirements_diff @@ -136,7 +134,7 @@ jobs: sed -i "/uv/d" requirements_diff.txt - name: Build wheels - uses: &home-assistant-wheels home-assistant/wheels@e5742a69d69f0e274e2689c998900c7d19652c21 # 2025.12.0 + uses: home-assistant/wheels@e5742a69d69f0e274e2689c998900c7d19652c21 # 2025.12.0 with: abi: ${{ matrix.abi }} tag: musllinux_1_2 @@ -156,16 +154,30 @@ jobs: runs-on: ${{ matrix.os }} strategy: fail-fast: false - matrix: *matrix-build + matrix: + abi: ["cp313", "cp314"] + arch: ["amd64", "aarch64"] + include: + - arch: amd64 + os: ubuntu-latest + - arch: aarch64 + os: ubuntu-24.04-arm steps: - - *checkout + - name: Checkout the repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - *download-env-file + - name: Download env_file + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + with: + name: env_file - - *download-requirements-diff + - name: Download requirements_diff + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + with: + name: requirements_diff - name: Download requirements_all_wheels - uses: *actions-download-artifact + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 with: name: requirements_all_wheels @@ -178,7 +190,7 @@ jobs: sed -i "/uv/d" requirements_diff.txt - name: Build wheels - uses: *home-assistant-wheels + uses: home-assistant/wheels@e5742a69d69f0e274e2689c998900c7d19652c21 # 2025.12.0 with: abi: ${{ matrix.abi }} tag: musllinux_1_2