The GitHub mirror is gone, so the HACS packaging and the GitHub-only CI no longer have anything to run against.
Removed
hacs.json
.github/workflows/validate.yml — both jobs (hassfest, hacs/action) were gated on github.server_url == 'https://github.com' and are GitHub-hosted actions, so neither can run on the Gitea runner.
Added
.gitea/workflows/ci.yml — lint (ruff check + format check) and validate (byte-compile + metadata check)
scripts/validate_integration.py — covers the part of hassfest that matters for a manually installed custom component: every JSON file parses, manifest.json has the required keys with a valid iot_class/integration_type/codeowners, domain matches the directory, and each translations/*.json mirrors strings.json key for key
ruff.toml — broad rule set tracking HA core conventions. Ruff is pinned in CI because its default rule set and formatter output move between releases.
Docs
README documents manual installation only; HACS badge, prerequisite and install steps are gone. Added a Development section with the local CI commands.
manifest.json documentation/issue_tracker point at the Gitea repo; codeowner updated.
NOTICE is unchanged — it is upstream attribution.
docs/plans/*.md left alone as dated historical records.
Two real defects surfaced by the linter
climate.async_set_hvac_mode raised HomeAssistantError for an unsupported mode from inside a try that catches Exception, so the message came back double-wrapped as Failed to set HVAC mode: Unsupported HVAC mode: .... Validation is now hoisted above the try.
config_flow.async_step_reauth_confirm swallowed unexpected exceptions into a bare unknown error with no log, unlike the equivalent user step. It now logs via _LOGGER.exception.
Everything else is mechanical: import ordering, docstrings on public methods, ClassVar on mutable class attributes, contextlib.suppress, and asyncio.TimeoutError -> TimeoutError (an alias since 3.11). The smoke test reads the new DknCloudNaClient.socket_connected property instead of reaching into _socket.
Verification
ruff check, ruff format --check, compileall and validate_integration.py all pass locally. The workflow itself has not been exercised against the runner yet — if Install ruff fails, the runner image lacks Python/venv and the fix is a container: image: python:3.12-slim.
The GitHub mirror is gone, so the HACS packaging and the GitHub-only CI no longer have anything to run against.
## Removed
- `hacs.json`
- `.github/workflows/validate.yml` — both jobs (`hassfest`, `hacs/action`) were gated on `github.server_url == 'https://github.com'` and are GitHub-hosted actions, so neither can run on the Gitea runner.
## Added
- `.gitea/workflows/ci.yml` — `lint` (ruff check + format check) and `validate` (byte-compile + metadata check)
- `scripts/validate_integration.py` — covers the part of hassfest that matters for a manually installed custom component: every JSON file parses, `manifest.json` has the required keys with a valid `iot_class`/`integration_type`/`codeowners`, domain matches the directory, and each `translations/*.json` mirrors `strings.json` key for key
- `ruff.toml` — broad rule set tracking HA core conventions. Ruff is pinned in CI because its default rule set and formatter output move between releases.
## Docs
- README documents manual installation only; HACS badge, prerequisite and install steps are gone. Added a Development section with the local CI commands.
- `manifest.json` documentation/issue_tracker point at the Gitea repo; codeowner updated.
- `NOTICE` is unchanged — it is upstream attribution.
- `docs/plans/*.md` left alone as dated historical records.
## Two real defects surfaced by the linter
1. `climate.async_set_hvac_mode` raised `HomeAssistantError` for an unsupported mode from inside a `try` that catches `Exception`, so the message came back double-wrapped as `Failed to set HVAC mode: Unsupported HVAC mode: ...`. Validation is now hoisted above the `try`.
2. `config_flow.async_step_reauth_confirm` swallowed unexpected exceptions into a bare `unknown` error with no log, unlike the equivalent user step. It now logs via `_LOGGER.exception`.
Everything else is mechanical: import ordering, docstrings on public methods, `ClassVar` on mutable class attributes, `contextlib.suppress`, and `asyncio.TimeoutError` -> `TimeoutError` (an alias since 3.11). The smoke test reads the new `DknCloudNaClient.socket_connected` property instead of reaching into `_socket`.
## Verification
`ruff check`, `ruff format --check`, `compileall` and `validate_integration.py` all pass locally. The workflow itself has not been exercised against the runner yet — if `Install ruff` fails, the runner image lacks Python/venv and the fix is a `container: image: python:3.12-slim`.
The GitHub mirror is gone, so the HACS packaging and the GitHub-only CI
no longer have anything to run against.
Remove hacs.json and the .github/ workflow. Both of its jobs (hassfest
and hacs/action) were gated on `github.server_url == 'https://github.com'`
and are GitHub-hosted actions, so neither can run on the Gitea runner.
Replace them with .gitea/workflows/ci.yml:
- lint: ruff check + ruff format --check, version pinned because ruff's
default rule set and formatter output move between releases
- validate: byte-compile, then scripts/validate_integration.py, which
covers the part of hassfest that matters for a manually installed
custom component (manifest keys, domain/directory agreement, and
translations matching strings.json key for key)
README now documents manual installation only, and points at the local
CI commands. manifest.json documentation and issue_tracker point at the
Gitea repo; NOTICE keeps its upstream attribution.
Adopting ruff surfaced two real defects, fixed here:
- climate.async_set_hvac_mode raised HomeAssistantError for an
unsupported mode from inside a try that catches Exception, so the
message was re-wrapped as "Failed to set HVAC mode: Unsupported HVAC
mode: ...". The validation is now hoisted above the try.
- config_flow.async_step_reauth_confirm swallowed unexpected exceptions
into a bare "unknown" error with no log, unlike the user step. It now
logs via _LOGGER.exception.
Remaining changes are mechanical: import ordering, docstrings on public
methods, ClassVar on mutable class attributes, contextlib.suppress, and
asyncio.TimeoutError -> TimeoutError (an alias since 3.11). The smoke
test now reads the new DknCloudNaClient.socket_connected property rather
than reaching into _socket.
Co-authored-by: anthropic/claude-opus-5
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
The GitHub mirror is gone, so the HACS packaging and the GitHub-only CI no longer have anything to run against.
Removed
hacs.json.github/workflows/validate.yml— both jobs (hassfest,hacs/action) were gated ongithub.server_url == 'https://github.com'and are GitHub-hosted actions, so neither can run on the Gitea runner.Added
.gitea/workflows/ci.yml—lint(ruff check + format check) andvalidate(byte-compile + metadata check)scripts/validate_integration.py— covers the part of hassfest that matters for a manually installed custom component: every JSON file parses,manifest.jsonhas the required keys with a validiot_class/integration_type/codeowners, domain matches the directory, and eachtranslations/*.jsonmirrorsstrings.jsonkey for keyruff.toml— broad rule set tracking HA core conventions. Ruff is pinned in CI because its default rule set and formatter output move between releases.Docs
manifest.jsondocumentation/issue_tracker point at the Gitea repo; codeowner updated.NOTICEis unchanged — it is upstream attribution.docs/plans/*.mdleft alone as dated historical records.Two real defects surfaced by the linter
climate.async_set_hvac_moderaisedHomeAssistantErrorfor an unsupported mode from inside atrythat catchesException, so the message came back double-wrapped asFailed to set HVAC mode: Unsupported HVAC mode: .... Validation is now hoisted above thetry.config_flow.async_step_reauth_confirmswallowed unexpected exceptions into a bareunknownerror with no log, unlike the equivalent user step. It now logs via_LOGGER.exception.Everything else is mechanical: import ordering, docstrings on public methods,
ClassVaron mutable class attributes,contextlib.suppress, andasyncio.TimeoutError->TimeoutError(an alias since 3.11). The smoke test reads the newDknCloudNaClient.socket_connectedproperty instead of reaching into_socket.Verification
ruff check,ruff format --check,compileallandvalidate_integration.pyall pass locally. The workflow itself has not been exercised against the runner yet — ifInstall rufffails, the runner image lacks Python/venv and the fix is acontainer: image: python:3.12-slim.