Skip to main content

Quality checklist

Everything below is enforced by CI on every pull request to the core repository. Running the same commands locally before you push saves review round-trips.

1. Linting and formatting (prek hooks)

CI runs the repository's prek hooks; the configured hooks include:

  • ruffruff-check (lint, with autofix) and ruff-format (formatting)
  • codespell — spelling
  • yamllint — YAML files
  • prettier — JSON/YAML/Markdown formatting (including manifest.json)
  • check-json, executable shebang checks, and branch protection hooks
  • Local hooks for mypy, pylint, gen_requirements_all, and the apexfest validators

Run the hooks locally on your changes before committing.

2. Static typing and linting

CI runs these across the codebase (partially, scoped to changed integrations, on most PRs):

mypy apexos/components/<domain>
pylint --ignore-missing-annotations=y apexos/components/<domain>
pylint tests/components/<domain>

Note that tests are pylint-checked too.

3. Integration validators (apexfest)

The manifest and integration validator must pass:

python -m script.apexfest --requirements --action validate

It validates (among other things) the manifest schema and key order, codeowners, config-flow registration, dependencies, translations/strings, services, icons, discovery matchers, metadata, mypy config, and the quality-scale rules file. See the manifest reference for the schema it applies.

4. Requirements bookkeeping

If you touched a manifest's requirements, regenerate the aggregated files and commit the result — CI fails if they are out of date:

python -m script.gen_requirements_all

Requirement versions must be pinned (package==1.2.3), and CI audits the licenses of all requirements.

5. Tests

CI runs pytest with strict flags; translations are compiled first because entity naming depends on them:

python3 -m script.translations develop --all
python3 -b -X dev -m pytest tests/components/<domain>

Checklist:

  • Tests live in tests/components/<domain>/.
  • Config flows require dedicated tests (test_config_flow.py — the scaffolder generates a starting point).
  • Coverage is collected and reported per PR; new code is expected to be covered. Config flow test coverage is a bronze-tier quality rule, i.e. effectively mandatory for new integrations.

6. The quality scale

Scaled integrations declare a tier in the manifest (bronze, silver, gold, platinum) and track individual rules in quality_scale.yaml (each rule is todo, done, or exempt with a reason). The scaffolder generates the file with every rule set to todo. The tiers:

Bronze (baseline for new integrations): action-setup, appropriate-polling, brands, common-modules, config-flow, config-flow-test-coverage, dependency-transparency, docs rules (docs-actions, docs-conditions, docs-high-level-description, docs-installation-instructions, docs-removal-instructions, docs-triggers), entity-event-setup, entity-unique-id, has-entity-name, runtime-data, test-before-configure, test-before-setup, unique-config-entry.

Silver: action-exceptions, config-entry-unloading, docs-configuration-parameters, docs-installation-parameters, entity-unavailable, integration-owner, log-when-unavailable, parallel-updates, reauthentication-flow, test-coverage.

Gold: devices, diagnostics, discovery, discovery-update-info, more docs rules (docs-data-update, docs-examples, docs-known-limitations, docs-supported-devices, docs-supported-functions, docs-troubleshooting, docs-use-cases), dynamic-devices, entity-category, entity-device-class, entity-disabled-by-default, entity-translations, exception-translations, icon-translations, reconfiguration-flow, repair-issues, stale-devices.

Platinum: async-dependency, inject-websession, strict-typing.

Remember: silver and above require a code owner in the manifest.

7. Practical pre-push sequence

# 1. lint + format via the prek hooks (ruff, codespell, prettier, ...)
# 2. validators
python -m script.apexfest --integration-path apexos/components/<domain>
# 3. requirements files, if the manifest changed
python -m script.gen_requirements_all
# 4. translations, if strings.json changed
python3 -m script.translations develop --integration <domain>
# 5. typing + lint
mypy apexos/components/<domain>
pylint --ignore-missing-annotations=y apexos/components/<domain>
# 6. tests
python3 -b -X dev -m pytest tests/components/<domain>