Contributing to 1komma5-ha¶
Thanks for taking the time to look into contributing — this is a hobby project, but every clean PR or well-described bug report makes it better.
Before opening an issue or PR¶
- For questions, setup help, automation ideas: please use GitHub Discussions or the Home Assistant Community Forum instead of an issue.
- For bug reports and feature requests: open an issue. The repo has templates for both — please fill the requested fields (HA version, integration version, hardware, logs).
- Search existing issues and pull requests first to avoid duplicates.
What's in scope, what isn't¶
This is an unofficial integration built on top of an undocumented, reverse-engineered API. That has consequences:
- In scope: anything the
onekommafivePython library already exposes (live overview, prices, EV charger, EMS, optimization events, weather). - Out of scope: features that would require backend changes by 1KOMMA5° (we don't have control over the API), and features that need data fields the API doesn't return.
- Hardware-specific oddities: I only have one system to test against. PRs that add hardware-specific handling are welcome but should default to behaving correctly for systems that don't have that hardware.
If you're unsure whether your idea fits, open a Discussion before writing code.
Local development setup¶
Requires Python 3.13 (matches the Home Assistant runtime) and git.
git clone https://github.com/mrebbert/1komma5-ha
cd 1komma5-ha
# Create a virtual environment for tooling and run the tests
python3.13 -m venv .venv
.venv/bin/pip install -e ".[test]" ruff pre-commit
# Activate pre-commit hooks for automatic ruff lint/format on every commit
.venv/bin/pre-commit install
# Run the unit tests (Tier 1 — pure helpers only, no HA install needed)
.venv/bin/pytest
The .venv/ directory is gitignored — it stays local.
Running the linters and formatter¶
ruff is the single source of truth for lint and format; pre-commit runs it automatically. To run manually:
.venv/bin/pre-commit run --all-files # Recommended (matches CI exactly)
.venv/bin/ruff check custom_components/ tests/
.venv/bin/ruff format custom_components/ tests/
Why pre-commit run over plain ruff? The pre-commit config pins a specific ruff version; CI uses the same. Calling ruff from a fresh pip install may format slightly differently and create churn.
Ignoring reformat commits in git blame¶
Pure formatting commits (e.g. the 2026-09-26 line-length sweep from 100 to 88) live in .git-blame-ignore-revs so authorship on individual lines stays traceable to the substantive change. GitHub honours the file automatically. To pick it up in local git blame, once per clone:
Testing¶
Tier 1 tests cover the pure helpers in custom_components/onekommafive/helpers.py (price slot lookup, forecast building, optimization aggregation, cheapest/most-expensive-window search, trapezoidal integration, active-event lookup). They run in milliseconds and don't require Home Assistant to be installed.
.venv/bin/pytest # all tests
.venv/bin/pytest tests/test_helpers.py::TestGetCurrentPrice -v # one class
.venv/bin/pytest --cov=custom_components/onekommafive --cov-report=term-missing
Tier 2 tests use a real Home Assistant instance via pytest-homeassistant-custom-component. They live under tests/integration/ and exercise the config flow, coordinators and services with the onekommafive library mocked. The dependency group is heavier (HA itself plus a numpy / sqlalchemy stack), so it is opt-in:
If you change a pure helper or add one, please add tests under tests/test_helpers.py. For platform changes (sensor classes, coordinators, config flow), add tests under tests/integration/. If you change behaviour that's already covered, don't loosen existing tests just to make a change pass.
Pull request workflow¶
- Branch from
main:git checkout -b feat/some-short-name(orfix/...,docs/...,chore/...). - Keep PRs small. One concern per PR — easier to review and revert if needed.
- Run the test suite and pre-commit locally before pushing.
- Update the docs if you change user-visible behaviour:
README.md,dashboard/README.md, translations undercustom_components/onekommafive/strings.jsonandtranslations/. - Add a CHANGELOG entry under
## [Unreleased](Keep-a-Changelog format). Don't bump the version inmanifest.json— that happens at release time. - Open the PR against
main. The repo runs three checks automatically:Validate(HACS + hassfest),Tests(pytest + ruff),CodeQL(security and code-quality). All three should pass.
Translations¶
The integration ships German (strings.json and translations/de.json) and English (translations/en.json). When you add a new entity, service or config-flow string:
- Add the new key to
strings.json(German is the primary file). - Mirror the key in
translations/de.jsonandtranslations/en.json. - The translation parity test in
tests/test_translations.pywill fail if any locale is missing keys — run.venv/bin/pytest tests/test_translations.pyto verify.
Releases¶
Releases are cut by the maintainer. There's no obligation for contributors to bump versions or tag — just leave the PR with [Unreleased] notes and the maintainer will roll them into the next release.
Release cadence (maintainer reference)¶
The repo uses a two-branch model to keep HACS-user release noise low:
main— hot branch. Every commit lands here; CI runs Validate + Tests + CodeQL on push. No tags from main under normal circumstances.release/next— release branch. Tags and GitHub Releases originate here only.
A scheduled workflow (.github/workflows/cadence.yml) runs every Sunday 20:00 UTC (Monday morning EU time for HACS users). It:
- Checks whether
mainis ahead ofrelease/next. If not, logsnothing to releaseand exits. - Reads
versionfromcustom_components/onekommafive/manifest.json. - If a tag
vX.Y.Zfor that version already exists, the cadence logs a warning and skips —mainhas commits butmanifest.jsonwas not bumped, so there's no new release to cut. - If
release-notes/vX.Y.Z.mdis missing, the workflow fails loudly so notes don't accidentally ship empty. - Otherwise: fast-forwards
release/nextfrommain, builds the zip, creates the GitHub Release with the curated notes file as body and the zip attached.
To get changes into the next cadence release, on main before Sunday 20:00 UTC:
- Bump
versionincustom_components/onekommafive/manifest.json. - Rotate the CHANGELOG: move the
## [Unreleased]block to## [X.Y.Z] - YYYY-MM-DD. - Add
release-notes/vX.Y.Z.mdwith the curated release body. - Commit + push.
The workflow can also be triggered manually via Actions → Release cadence → "Run workflow" (e.g. for testing).
Hotfix lane (bypasses the cadence)¶
When something is broken and waiting for Sunday isn't acceptable:
- Push the fix to
mainas usual. - Manually tag
vX.Y.ZonmainHEAD:git tag vX.Y.Z && git push --tags. - Manually create the GitHub Release in the UI pointing at that tag —
.github/workflows/release.ymlfires on therelease: publishedevent and attaches the zip. - The next Sunday cadence run fast-forwards
release/nextpast the hotfix tag, no conflict.
Code style notes¶
- The integration uses Python 3.12+ syntax (
typealiases, PEP 695 generics,datetime.UTC). - All API calls go through
hass.async_add_executor_job— theonekommafivelibrary is synchronous (requestsunderneath). - Keep the pure helpers in
helpers.pyactually pure — no HA imports, no I/O. They are the only easily-testable surface. - New sensor entities should follow the description-based pattern already in use (see
sensor_descriptions.py,sensor_entities.py, ornumber.py:OneKomma5EVNumberDescription).
License¶
By contributing you agree that your contribution will be licensed under the MIT License of this repository.