mirror of
https://github.com/esphome/esphome.git
synced 2026-08-22 22:26:21 +00:00
[ci] Replace pre-commit with prek (#18029)
This commit is contained in:
+20
-56
@@ -65,7 +65,7 @@ jobs:
|
|||||||
python -m venv venv
|
python -m venv venv
|
||||||
. venv/bin/activate
|
. venv/bin/activate
|
||||||
python --version
|
python --version
|
||||||
uv pip install -r requirements.txt -r requirements_dev.txt -r requirements_test.txt pre-commit
|
uv pip install -r requirements.txt -r requirements_dev.txt -r requirements_test.txt
|
||||||
uv pip install -e .
|
uv pip install -e .
|
||||||
|
|
||||||
determine-jobs:
|
determine-jobs:
|
||||||
@@ -208,69 +208,34 @@ jobs:
|
|||||||
run: script/ci-suggest-changes
|
run: script/ci-suggest-changes
|
||||||
if: always()
|
if: always()
|
||||||
|
|
||||||
pre-commit-ci-lite:
|
lint-format:
|
||||||
name: pre-commit.ci lite
|
name: Check lint and formatting
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs:
|
needs:
|
||||||
- common
|
|
||||||
- determine-jobs
|
- determine-jobs
|
||||||
if: github.event_name == 'pull_request' && !startsWith(github.base_ref, 'beta') && !startsWith(github.base_ref, 'release') && needs.determine-jobs.outputs.core-ci == 'true'
|
if: github.event_name == 'pull_request' && !startsWith(github.base_ref, 'beta') && !startsWith(github.base_ref, 'release') && needs.determine-jobs.outputs.core-ci == 'true'
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code from GitHub
|
- name: Check out code from GitHub
|
||||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
- name: Restore Python
|
- name: Run prek
|
||||||
uses: ./.github/actions/restore-python
|
uses: j178/prek-action@4e14d07f9231acabce116ccfca13b13dd9755ece # v3.0.0
|
||||||
with:
|
with:
|
||||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
# Keep in sync with requirements_test.txt.
|
||||||
cache-key: ${{ needs.common.outputs.cache-key }}
|
prek-version: "0.4.11"
|
||||||
# Inlined from esphome/pre-commit-action with a restore-only cache
|
# This job only runs on pull requests, so nothing ever populates
|
||||||
# step: the pre-commit-seed-cache job owns saving this cache, so
|
# the cache on dev. Every run would miss and then write a per-pull
|
||||||
# pull request runs never write per-PR copies.
|
# request copy, which is what the old seed-cache job existed to
|
||||||
- name: Restore pre-commit cache
|
# avoid. Building the hooks from scratch takes seconds, so skip it.
|
||||||
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
cache: false
|
||||||
with:
|
|
||||||
path: ~/.cache/pre-commit
|
|
||||||
# Must match the key pre-commit-seed-cache saves
|
|
||||||
# yamllint disable-line rule:line-length
|
|
||||||
key: pre-commit-3|${{ env.pythonLocation }}|${{ hashFiles('.pre-commit-config.yaml') }}
|
|
||||||
- name: Run pre-commit
|
|
||||||
env:
|
env:
|
||||||
SKIP: pylint,ci-custom
|
PREK_SKIP: pylint,ci-custom
|
||||||
run: |
|
# Pushes any fixes the hooks made back to the pull request. This step
|
||||||
python -m pip install pre-commit
|
# must keep its default name: the GitHub App that performs the push
|
||||||
pre-commit run --show-diff-on-failure --color=always --all-files
|
# locates the workflow run by that name.
|
||||||
- uses: pre-commit-ci/lite-action@5d6cc0eb514c891a40562a58a8e71576c5c7fb43 # v1.1.0
|
- uses: pre-commit-ci/lite-action@5d6cc0eb514c891a40562a58a8e71576c5c7fb43 # v1.1.0
|
||||||
if: always()
|
if: always()
|
||||||
|
|
||||||
pre-commit-seed-cache:
|
|
||||||
name: Seed pre-commit cache
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs:
|
|
||||||
- common
|
|
||||||
# Saves a dev-scoped pre-commit cache that pull request runs can
|
|
||||||
# restore, since pre-commit.ci lite itself never runs on dev pushes.
|
|
||||||
if: github.event_name == 'push' && github.ref == 'refs/heads/dev'
|
|
||||||
steps:
|
|
||||||
- name: Check out code from GitHub
|
|
||||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
||||||
- name: Restore Python
|
|
||||||
uses: ./.github/actions/restore-python
|
|
||||||
with:
|
with:
|
||||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
msg: apply automatic formatting fixes
|
||||||
cache-key: ${{ needs.common.outputs.cache-key }}
|
|
||||||
- name: Cache pre-commit environments
|
|
||||||
id: cache-pre-commit
|
|
||||||
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
|
||||||
with:
|
|
||||||
path: ~/.cache/pre-commit
|
|
||||||
# Must match the restore key in pre-commit-ci-lite
|
|
||||||
# yamllint disable-line rule:line-length
|
|
||||||
key: pre-commit-3|${{ env.pythonLocation }}|${{ hashFiles('.pre-commit-config.yaml') }}
|
|
||||||
- name: Install pre-commit hook environments
|
|
||||||
if: steps.cache-pre-commit.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
python -m pip install pre-commit
|
|
||||||
pre-commit install-hooks
|
|
||||||
|
|
||||||
pytest:
|
pytest:
|
||||||
name: Run pytest
|
name: Run pytest
|
||||||
@@ -1456,16 +1421,15 @@ jobs:
|
|||||||
ci-status:
|
ci-status:
|
||||||
name: CI Status
|
name: CI Status
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
# Listed in the same order the jobs are defined above. Two jobs are
|
# Listed in the same order the jobs are defined above. One job is
|
||||||
# deliberately left out: "benchmarks" reports through CodSpeed rather than
|
# deliberately left out: "benchmarks" reports through CodSpeed rather than
|
||||||
# this check, and "pre-commit-seed-cache" only populates a cache on pushes
|
# this check.
|
||||||
# to dev.
|
|
||||||
needs:
|
needs:
|
||||||
- common
|
- common
|
||||||
- determine-jobs
|
- determine-jobs
|
||||||
- ci-custom
|
- ci-custom
|
||||||
- pylint
|
- pylint
|
||||||
- pre-commit-ci-lite
|
- lint-format
|
||||||
- pytest
|
- pytest
|
||||||
- codecov-empty-upload
|
- codecov-empty-upload
|
||||||
- integration-tests
|
- integration-tests
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ jobs:
|
|||||||
- name: Set up uv
|
- name: Set up uv
|
||||||
# An order of magnitude faster than pip on cold boots, with its
|
# An order of magnitude faster than pip on cold boots, with its
|
||||||
# own wheel cache. ``--system`` (below) installs into the
|
# own wheel cache. ``--system`` (below) installs into the
|
||||||
# setup-python interpreter so subsequent ``pre-commit`` /
|
# setup-python interpreter so subsequent ``prek`` /
|
||||||
# ``script/run-in-env.py`` steps find the deps without a
|
# ``script/run-in-env.py`` steps find the deps without a
|
||||||
# ``uv run`` prefix.
|
# ``uv run`` prefix.
|
||||||
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||||
@@ -58,19 +58,19 @@ jobs:
|
|||||||
- name: Install Home Assistant
|
- name: Install Home Assistant
|
||||||
run: |
|
run: |
|
||||||
uv pip install --system -e lib/home-assistant
|
uv pip install --system -e lib/home-assistant
|
||||||
uv pip install --system -r requirements.txt -r requirements_test.txt pre-commit
|
uv pip install --system -r requirements.txt -r requirements_test.txt
|
||||||
|
|
||||||
- name: Sync
|
- name: Sync
|
||||||
run: |
|
run: |
|
||||||
python ./script/sync-device_class.py
|
python ./script/sync-device_class.py
|
||||||
|
|
||||||
- name: Apply pre-commit auto-fixes
|
- name: Apply prek auto-fixes
|
||||||
# First pass: let formatters (ruff, end-of-file-fixer, etc.) modify
|
# First pass: let formatters (ruff, end-of-file-fixer, etc.) modify
|
||||||
# files. pre-commit exits non-zero whenever a hook touches anything,
|
# files. prek exits non-zero whenever a hook touches anything,
|
||||||
# which would otherwise abort the workflow before the auto-fixes
|
# which would otherwise abort the workflow before the auto-fixes
|
||||||
# can flow into the sync PR.
|
# can flow into the sync PR.
|
||||||
#
|
#
|
||||||
# SKIP:
|
# PREK_SKIP:
|
||||||
# - no-commit-to-branch is a local guard against committing on
|
# - no-commit-to-branch is a local guard against committing on
|
||||||
# dev/release/beta; CI runs on dev by definition, and
|
# dev/release/beta; CI runs on dev by definition, and
|
||||||
# peter-evans/create-pull-request creates the branch itself.
|
# peter-evans/create-pull-request creates the branch itself.
|
||||||
@@ -79,18 +79,18 @@ jobs:
|
|||||||
# the runtime deps (HA + requirements*.txt); main CI already
|
# the runtime deps (HA + requirements*.txt); main CI already
|
||||||
# gates pylint on real PRs.
|
# gates pylint on real PRs.
|
||||||
env:
|
env:
|
||||||
SKIP: pylint,no-commit-to-branch
|
PREK_SKIP: pylint,no-commit-to-branch
|
||||||
run: python script/run-in-env.py pre-commit run --all-files || true
|
run: python script/run-in-env.py prek run --all-files || true
|
||||||
|
|
||||||
- name: Verify pre-commit clean
|
- name: Verify prek clean
|
||||||
# Second pass: re-run all hooks against the now-fixed tree.
|
# Second pass: re-run all hooks against the now-fixed tree.
|
||||||
# Auto-fixers exit 0 (nothing to change); any remaining failure
|
# Auto-fixers exit 0 (nothing to change); any remaining failure
|
||||||
# from a check-only hook (flake8 / yamllint / ci-custom) is a
|
# from a check-only hook (flake8 / yamllint / ci-custom) is a
|
||||||
# real issue and fails the workflow loudly. Same SKIP list as
|
# real issue and fails the workflow loudly. Same PREK_SKIP list as
|
||||||
# above for the same reasons.
|
# above for the same reasons.
|
||||||
env:
|
env:
|
||||||
SKIP: pylint,no-commit-to-branch
|
PREK_SKIP: pylint,no-commit-to-branch
|
||||||
run: python script/run-in-env.py pre-commit run --all-files
|
run: python script/run-in-env.py prek run --all-files
|
||||||
|
|
||||||
- name: Commit changes
|
- name: Commit changes
|
||||||
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
|
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
|
||||||
|
|||||||
@@ -412,7 +412,7 @@ This document provides essential context for AI models interacting with this pro
|
|||||||
* **Configuration:**
|
* **Configuration:**
|
||||||
* `pyproject.toml`: Defines the Python project metadata and dependencies.
|
* `pyproject.toml`: Defines the Python project metadata and dependencies.
|
||||||
* `platformio.ini`: Configures the PlatformIO build environments for different microcontrollers.
|
* `platformio.ini`: Configures the PlatformIO build environments for different microcontrollers.
|
||||||
* `.pre-commit-config.yaml`: Configures the pre-commit hooks for linting and formatting.
|
* `.pre-commit-config.yaml`: Configures the lint and format hooks, run by `prek`.
|
||||||
* **CI/CD Pipeline:** Defined in `.github/workflows`.
|
* **CI/CD Pipeline:** Defined in `.github/workflows`.
|
||||||
* **Static Analysis & Development:**
|
* **Static Analysis & Development:**
|
||||||
* `esphome/core/defines.h`: A comprehensive header file containing all `#define` directives that can be added by components using `cg.add_define()` in Python. This file is used exclusively for development, static analysis tools, and CI testing - it is not used during runtime compilation. When developing components that add new defines, they must be added to this file to ensure proper IDE support and static analysis coverage. The file includes feature flags, build configurations, and platform-specific defines that help static analyzers understand the complete codebase without needing to compile for specific platforms.
|
* `esphome/core/defines.h`: A comprehensive header file containing all `#define` directives that can be added by components using `cg.add_define()` in Python. This file is used exclusively for development, static analysis tools, and CI testing - it is not used during runtime compilation. When developing components that add new defines, they must be added to this file to ensure proper IDE support and static analysis coverage. The file includes feature flags, build configurations, and platform-specific defines that help static analyzers understand the complete codebase without needing to compile for specific platforms.
|
||||||
@@ -420,7 +420,7 @@ This document provides essential context for AI models interacting with this pro
|
|||||||
## 6. Development & Testing Workflow
|
## 6. Development & Testing Workflow
|
||||||
|
|
||||||
* **Local Development Environment:** Use the provided Docker container or create a Python virtual environment and install dependencies from `requirements_dev.txt`.
|
* **Local Development Environment:** Use the provided Docker container or create a Python virtual environment and install dependencies from `requirements_dev.txt`.
|
||||||
* **Running Commands:** Use the `script/run-in-env.py` script to execute commands within the project's virtual environment. For example, to run the linter: `python3 script/run-in-env.py pre-commit run`.
|
* **Running Commands:** Use the `script/run-in-env.py` script to execute commands within the project's virtual environment. For example, to run the linter: `python3 script/run-in-env.py prek run`.
|
||||||
* **Testing:**
|
* **Testing:**
|
||||||
* **Python:** Run unit tests with `pytest`.
|
* **Python:** Run unit tests with `pytest`.
|
||||||
* **C++:** Use `clang-tidy` for static analysis.
|
* **C++:** Use `clang-tidy` for static analysis.
|
||||||
@@ -493,7 +493,7 @@ This document provides essential context for AI models interacting with this pro
|
|||||||
1. **Fork & Branch:** Create a new branch based on the `dev` branch (always use `git checkout -b <branch-name> dev` to ensure you're branching from `dev`, not the currently checked out branch).
|
1. **Fork & Branch:** Create a new branch based on the `dev` branch (always use `git checkout -b <branch-name> dev` to ensure you're branching from `dev`, not the currently checked out branch).
|
||||||
2. **Make Changes:** Adhere to all coding conventions and patterns.
|
2. **Make Changes:** Adhere to all coding conventions and patterns.
|
||||||
3. **Test:** Create component tests for all supported platforms and run the full test suite locally.
|
3. **Test:** Create component tests for all supported platforms and run the full test suite locally.
|
||||||
4. **Lint:** Run `pre-commit` to ensure code is compliant.
|
4. **Lint:** Run `prek` to ensure code is compliant.
|
||||||
5. **Commit:** Commit your changes. There is no strict format for commit messages.
|
5. **Commit:** Commit your changes. There is no strict format for commit messages.
|
||||||
6. **Pull Request:** Submit a PR against the `dev` branch. The Pull Request title must start with a `[tag]` prefix. For component work, use the component name (e.g., `[display] Fix bug`, `[abc123] Add new component`); for changes to shared/core code that isn't tied to a single component, use `[core]` (e.g., `[core] Add validator`). Update documentation, examples, and add `CODEOWNERS` entries as needed. Pull requests should always be made using the `.github/PULL_REQUEST_TEMPLATE.md` template - fill out all sections completely without removing any parts of the template.
|
6. **Pull Request:** Submit a PR against the `dev` branch. The Pull Request title must start with a `[tag]` prefix. For component work, use the component name (e.g., `[display] Fix bug`, `[abc123] Add new component`); for changes to shared/core code that isn't tied to a single component, use `[core]` (e.g., `[core] Add validator`). Update documentation, examples, and add `CODEOWNERS` entries as needed. Pull requests should always be made using the `.github/PULL_REQUEST_TEMPLATE.md` template - fill out all sections completely without removing any parts of the template.
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ pylint==4.0.6
|
|||||||
flake8==7.3.0 # also change in .pre-commit-config.yaml when updating
|
flake8==7.3.0 # also change in .pre-commit-config.yaml when updating
|
||||||
ruff==0.16.1 # also change in .pre-commit-config.yaml when updating
|
ruff==0.16.1 # also change in .pre-commit-config.yaml when updating
|
||||||
pyupgrade==3.21.2 # also change in .pre-commit-config.yaml when updating
|
pyupgrade==3.21.2 # also change in .pre-commit-config.yaml when updating
|
||||||
pre-commit
|
prek==0.4.11 # also change in .github/workflows/ci.yml when updating
|
||||||
|
|
||||||
# Unit tests
|
# Unit tests
|
||||||
pytest==9.1.1
|
pytest==9.1.1
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ what files have changed. It outputs JSON with the following structure:
|
|||||||
}
|
}
|
||||||
|
|
||||||
The CI workflow uses this information to:
|
The CI workflow uses this information to:
|
||||||
- Gate the unconditional jobs (ci-custom, pytest, pre-commit-ci-lite) via core_ci;
|
- Gate the unconditional jobs (ci-custom, pytest, lint-format) via core_ci;
|
||||||
false when a pull_request only touches CI-irrelevant meta paths (other workflow
|
false when a pull_request only touches CI-irrelevant meta paths (other workflow
|
||||||
files, .github/actions/build-image/*, .yamllint, .github/dependabot.yml, docker/**)
|
files, .github/actions/build-image/*, .yamllint, .github/dependabot.yml, docker/**)
|
||||||
so workflow-only PRs satisfy the required CI Status check without running the
|
so workflow-only PRs satisfy the required CI Status check without running the
|
||||||
@@ -708,7 +708,7 @@ def should_run_benchmarks(branch: str | None = None) -> bool:
|
|||||||
|
|
||||||
|
|
||||||
# Files / path patterns whose changes alone don't warrant running the
|
# Files / path patterns whose changes alone don't warrant running the
|
||||||
# unconditional CI jobs (`ci-custom`, `pytest`, `pre-commit-ci-lite`).
|
# unconditional CI jobs (`ci-custom`, `pytest`, `lint-format`).
|
||||||
# Single source of truth for what we treat as "CI-irrelevant" on
|
# Single source of truth for what we treat as "CI-irrelevant" on
|
||||||
# pull_request events; ci.yml used to encode this in its own
|
# pull_request events; ci.yml used to encode this in its own
|
||||||
# `pull_request.paths` filter, but that hid the required `CI Status`
|
# `pull_request.paths` filter, but that hid the required `CI Status`
|
||||||
@@ -752,7 +752,7 @@ def _is_ci_irrelevant_path(path: str) -> bool:
|
|||||||
|
|
||||||
|
|
||||||
def should_run_core_ci(branch: str | None = None) -> bool:
|
def should_run_core_ci(branch: str | None = None) -> bool:
|
||||||
"""Determine if the unconditional CI jobs (ci-custom/pytest/pre-commit-ci-lite) should run.
|
"""Determine if the unconditional CI jobs (ci-custom/pytest/lint-format) should run.
|
||||||
|
|
||||||
Returns False only when every changed file is in the CI-irrelevant set
|
Returns False only when every changed file is in the CI-irrelevant set
|
||||||
above (see ``_is_ci_irrelevant_path``). Empty diffs return True so we
|
above (see ``_is_ci_irrelevant_path``). Empty diffs return True so we
|
||||||
@@ -1177,7 +1177,7 @@ def main() -> None:
|
|||||||
|
|
||||||
# Determine what should run
|
# Determine what should run
|
||||||
# core_ci gates the unconditional jobs in ci.yml (ci-custom, pytest,
|
# core_ci gates the unconditional jobs in ci.yml (ci-custom, pytest,
|
||||||
# pre-commit-ci-lite). Non-pull_request events (push to dev/beta/release
|
# lint-format). Non-pull_request events (push to dev/beta/release
|
||||||
# and merge_group) always run them so behavior like venv-cache saves on
|
# and merge_group) always run them so behavior like venv-cache saves on
|
||||||
# push to dev is preserved.
|
# push to dev is preserved.
|
||||||
event_name = os.environ.get("GITHUB_EVENT_NAME", "")
|
event_name = os.environ.get("GITHUB_EVENT_NAME", "")
|
||||||
|
|||||||
+5
-1
@@ -25,7 +25,11 @@ fi
|
|||||||
uv pip install setuptools wheel
|
uv pip install setuptools wheel
|
||||||
uv pip install -e ".[dev,test]" --config-settings editable_mode=compat
|
uv pip install -e ".[dev,test]" --config-settings editable_mode=compat
|
||||||
|
|
||||||
pre-commit install
|
# --overwrite replaces any hook already in place. Without it, prek finds a
|
||||||
|
# previously installed pre-commit hook, moves it aside to
|
||||||
|
# .git/hooks/pre-commit.legacy and keeps calling it, so every commit would
|
||||||
|
# run both tools.
|
||||||
|
prek install --overwrite
|
||||||
|
|
||||||
mkdir -p .temp
|
mkdir -p .temp
|
||||||
|
|
||||||
|
|||||||
+5
-1
@@ -17,7 +17,11 @@ pip3 install -r requirements.txt -r requirements_test.txt -r requirements_dev.tx
|
|||||||
pip3 install setuptools wheel
|
pip3 install setuptools wheel
|
||||||
pip3 install -e ".[dev,test]" --config-settings editable_mode=compat
|
pip3 install -e ".[dev,test]" --config-settings editable_mode=compat
|
||||||
|
|
||||||
pre-commit install
|
rem --overwrite replaces any hook already in place. Without it, prek finds a
|
||||||
|
rem previously installed pre-commit hook, moves it aside to
|
||||||
|
rem .git/hooks/pre-commit.legacy and keeps calling it, so every commit would
|
||||||
|
rem run both tools.
|
||||||
|
prek install --overwrite
|
||||||
|
|
||||||
echo .
|
echo .
|
||||||
echo .
|
echo .
|
||||||
|
|||||||
Reference in New Issue
Block a user