A reusable GitHub Action that validates the repository structure and manifest.json files for RotorHazard plugins. Validation runs through a shared rule engine and reports stable rule codes in local output and GitHub-friendly annotations.
- β
Schema validation for keys in
manifest.json - β
Plugin repository structure validation
- π Presence of
custom_pluginsfolder - π Presence of single plugin domain folder
- π Presence of
manifest.jsonfile - π Plugin domain folder matches the
domaininmanifest.json
- π Presence of
- β
RotorHazard-specific Python linting
- π Detects private
_racecontextaccess through RHAPI and simple aliases - π³ Uses reusable AST analysis instead of text matching
- π Detects private
- π¨ GitHub Action annotations for validation errors
β οΈ Warning diagnostics that do not fail validation- π³ Docker image for local testing (manual or pre-commit)
- π Validates for example:
- domain format (e.g., lowercase letters, numbers, underscores)
- version semver format (e.g.,
X.Y.Z) - dependencies using the version specifiers format (e.g.,
==X.Y.Z) - documentation_uri URL format
Create a file .github/workflows/validate.yml in your plugin repository with the following content:
name: Validate Plugin Manifest on: push: pull_request: jobs: validate: name: Run RHFest validation runs-on: ubuntu-latest steps: - name: Check out repository uses: actions/checkout@v7 - name: Run RHFest validation uses: RotorHazard/rhfest-action@v3.2.2
Pinning a complete release tag keeps validation reproducible. Moving tags are also available for users who prefer automatic compatible updates:
RotorHazard/rhfest-action@v3.2follows patch releases within v3.2.RotorHazard/rhfest-action@v3follows minor and patch releases within v3.
Moving tags trade strict reproducibility for automatic updates.
To adopt rule families incrementally or suppress a deliberate exception, pass the corresponding Action inputs:
- name: Run selected RHFest validation uses: RotorHazard/rhfest-action@v3.2.2 with: select: "STR,MAN,RH002" ignore: "MAN002"
RHFest is also available as an official Docker-based pre-commit hook. Pin the hook to an exact release for reproducible checks:
repos: - repo: https://github.com/RotorHazard/rhfest-action rev: v3.2.2 hooks: - id: rhfest
Needs Docker installed
RHFest is available as a Docker image, which makes it easy to test locally without installing any dependencies. To test your RotorHazard plugin repository, you can use the following command:
docker run --rm -v "$(pwd)":/repo ghcr.io/rotorhazard/rhfest-action:v3.2.2The moving v3.2 and v3 container tags are also available for users who
prefer automatic compatible updates.
Rule selection flags can be passed directly to the container:
docker run --rm -v "$(pwd)":/repo \
ghcr.io/rotorhazard/rhfest-action:v3.2.2 \
--select STR,MAN,RH002 --ignore MAN002How to setup the development environment.
You need the following tools to get started:
- Clone the repository
- Install all dependencies with UV. This will create a virtual environment and install all dependencies
uv sync
- Setup the pre-commit check, you must run this inside the virtual environment
uv run pre-commit install
- Run the application
uv run python -m rhfest.core
Use --select and --ignore with comma-separated exact codes or complete rule
families. Options may be repeated:
uv run python -m rhfest.core --select STR,MAN --select RH002 --ignore MAN002
Selectors are case-insensitive. ignore is applied after select and therefore
always takes precedence. Unknown codes, unknown families, partial codes, and
empty selectors are configuration errors with exit status 2. When no selector
is configured, RHFest continues to run and report every registered rule.
RHFEST_SELECT and RHFEST_IGNORE provide the equivalent environment-based
configuration. The GitHub Action inputs use the same parser through
INPUT_SELECT and INPUT_IGNORE. Explicit CLI flags override their respective
environment value.
RHFest validates the current directory outside GitHub Actions and Docker. Set
GITHUB_WORKSPACE to validate another path using the same discovery behavior as
the action. A run exits with status 1 when it contains one or more error
diagnostics; warnings alone exit with status 0.
uv run --group dev pytest
The test suite covers the rule engine, repository and Python-source discovery, manifest schema, RHAPI provenance, reporting, and exit status. CI runs it on all supported Python versions.
Every finding is represented as data with a stable code, severity, message, family, and optional repository-relative path, one-based line, and one-based column. Rules return these diagnostics without writing logs themselves. The engine sorts registered rules by phase, order, and code, executes applicable rules, and passes the collected result to one reporter.
The rule families are:
STRxxxβ repository and plugin structureMANxxxβmanifest.jsonloading and validationRHxxxβ RotorHazard-specific Python source analysis
See the rule catalog for the stable code mapping, detailed rule behavior, diagnostic formats, and instructions for adding a rule.
As this repository uses the pre-commit framework, all changes are linted and tested with each commit. You can run all checks and tests manually, using the following command:
uv run pre-commit run --all-files
To manual run only on the staged files, use the following command:
uv run pre-commit run
To build the Docker image locally, run the following command:
docker build -t rhfest-action:latest .To run the Docker image, use the following command:
docker run --rm -v "$(pwd)":/repo rhfest-action:latestThis project was inspired by:
- Manifest validation in HACS
- Manifest validation (Hassfest) in Home Assistant
Distributed under the MIT License. See LICENSE for more information.