Files
fgl-aircon/docs/RELEASE_HA.md
T
petr.polezhaev f9d917c66d ha(packaging): musllinux-wheel для HA OS и статический C++-рантайм
- _corebuild.musl_platform_tag(): на musl (Alpine/HA OS) bdist_wheel
  выпускает py3-none-musllinux_X_Y_<arch> вместо linux_<arch> — иначе pip
  ставит glibc-сборку и dlopen падает на ld-linux-x86-64.so.2
- shared-библиотека линкуется со -static-libstdc++ -static-libgcc (gcc):
  NEEDED только libm/libc (проверено readelf), меньше зависимостей у HA OS
- Gitea Actions: job build-musllinux (container python:3.12-alpine) собирает
  и публикует musl-wheel; build-glibc — как раньше; общий
  scripts/publish-gitea-pypi.sh с пропуском уже загруженных файлов
- тесты musl_platform_tag; RELEASE_HA §1.1-1.4 (выбор wheel, переустановка
  на HA OS, ручная сборка musllinux без container:); README troubleshooting
2026-09-29 16:20:21 +03:00

180 lines
9.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Релиз и установка HA-интеграции
## 1. Внутренняя сборка и установка (Gitea, текущий режим)
Внутренний репозиторий — Gitea (`git.ratigorsk-12.ru`), поэтому:
* HACS к Gitea **не подключается** (только публичный GitHub) — для
внутреннего использования интеграция ставится копированием
`custom_components/fglair/` в `<config>/custom_components/`;
* зависимость `pyfglair` публикуется в **PyPI-реестр пакетов Gitea** и
ставится оттуда.
### 1.1. Сборка и публикация wheel (Gitea Actions, ручной запуск)
Workflow: `.gitea/workflows/publish-pyfglair.yaml` (workflow объявляет
`permissions: contents: read, packages: write`).
Авторизация — любой из вариантов:
* **Встроенный job-токен** (Gitea ≥ 1.27, где `packages` поддержан у
features): ничего настраивать не нужно, workflow возьмёт
`${{ secrets.GITEA_TOKEN }}`;
* **Personal access token** со scope `write:package` (для версий, где
публикация пакетов job-токеном ещё не реализована — см. HACS-док Gitea
«Package repository authorization»): положите его в секрет
`PYPI_TOKEN`, при необходимости задайте `PYPI_USER` (имя пользователя к
PAT; иначе — актор запуска). **Имена секретов не могут начинаться с
`GITEA_`** — префикс зарезервирован Gitea.
Запуск: Actions → **Publish pyfglair** → Run workflow (вход
`bundled_mbedtls`: `1` — встроить mbedtls, `0` — системный
`libmbedtls-dev`). Собираются **два** wheel одной версии:
* `py3-none-linux_x86_64` — glibc (HA Supervised/Core на Debian/Ubuntu);
* `py3-none-musllinux_1_2_x86_64` — musl (**HA OS**, Alpine-контейнер);
job `build-musllinux` выполняется в `container: python:3.12-alpine`
(нужен `container:` у runner'а; иначе см. §1.4).
Артефакты появятся в
`https://git.ratigorsk-12.ru/api/packages/<owner>/pypi/simple/pyfglair/`
(`<owner>` — владелец репозитория, напр. `esphome`). C++-рантайм в .so
встроен (`-static-libstdc++ -static-libgcc`), поэтому wheel зависит только
от libc/libm соответствующей платформы.
Workflow собирает `wheel` + `sdist`, прогоняет smoke-тест установки
(запускается из `/tmp` с `python -P`, чтобы не подхватить исходники
`pyfglair/` вместо wheel) и публикует через `twine upload`. Twine 7 не
поддерживает `--skip-existing` для не-PyPI репозиториев, поэтому workflow
сам проверяет simple-индекс Gitea и пропускает загрузку, если версия уже
опубликована. Для новой версии поднимите `version` в `pyproject.toml`.
### 1.2. Установка pyfglair в Home Assistant
Выбор wheel pip делает сам по платформе: на HA OS (Alpine/musl) — из
musllinux, на HA Supervised/Core (Debian/glibc) — из linux-сборки.
Пакет обязателен (cffi-биндинги). Варианты:
* **Вручную в окружение HA** (проще всего для теста; HA увидит
установленный дистрибутив и не будет вызывать pip для `pyfglair>=1.0.0`):
```sh
# в контейнере/venv Home Assistant (Advanced SSH & Web Terminal, docker exec и т.п.)
pip install --index-url https://<user>:<token>@git.ratigorsk-12.ru/api/packages/<owner>/pypi/simple \
--no-deps pyfglair
```
* **Через индекс pip в окружении HA** (`pip.conf`/`PIP_EXTRA_INDEX_URL`):
тогда HA сам поставит `pyfglair` из манифеста. Учтите риск dependency
confusion при `--extra-index-url` — для внутреннего стенда допустимо.
Если при добавлении интеграции HA пишет «Invalid handler specified» —
пакет `pyfglair` не установлен (или компонент не перезапущен). Смотрите
`grep -iE "fglair|pyfglair" /config/home-assistant.log`: при
`ModuleNotFoundError: No module named 'pyfglair'` установите пакет в
окружение HA (`docker exec homeassistant python -m pip install ...`) и
полностью перезапустите HA.
* **Публичный PyPI** — см. §2 (для распространения вне сети).
### 1.3. Если HA уже установил glibc-wheel на HA OS
Симптом: `OSError: cannot load library ... Error loading shared library
ld-linux-x86-64.so.2: No such file or directory`. Переустановите пакет с
musllinux-сборкой:
```sh
docker exec homeassistant python -m pip uninstall -y pyfglair
docker exec homeassistant python -m pip install --no-deps --index-url \
https://<user>:<token>@git.ratigorsk-12.ru/api/packages/<owner>/pypi/simple \
pyfglair
docker exec homeassistant python -c "import pyfglair; print(pyfglair.__version__)"
docker restart homeassistant
```
### 1.4. Ручная сборка musllinux (если runner без `container:`)
```sh
docker run --rm -v "$PWD":/src -w /src python:3.12-alpine sh -c '
apk add --no-cache git cmake ninja g++ make curl libstdc++-dev &&
pip install build &&
python -m build --wheel'
# dist/pyfglair-<ver>-py3-none-musllinux_1_2_x86_64.whl
pip install twine
python -m twine upload --repository-url \
https://git.ratigorsk-12.ru/api/packages/<owner>/pypi \
-u <user> -p <token> dist/*musllinux*.whl
```
### 1.5. Обновление интеграции
`custom_components/fglair/` обновляется из Gitea (git pull / копирование),
затем перезапуск HA. `pyfglair` — переустановкой из пакетов Gitea.
## 2. Публикация pyfglair на PyPI (если понадобится публично)
PyPI (warehouse) принимает только `manylinux*`/`musllinux*` теги, поэтому
локальный `py3-none-linux_x86_64` нужно чинить auditwheel'ом в контейнере
со старой glibc:
```sh
pip install build auditwheel twine
# для каждой архитектуры (linux x86_64/aarch64) в manylinux-контейнере:
python -m build --wheel
auditwheel repair dist/pyfglair-*.whl --plat manylinux2014_x86_64 -w dist/manylinux/
rm -f dist/pyfglair-*-linux_*.whl
python -m build --sdist
twine upload dist/manylinux/* dist/*.tar.gz
```
Проверки: `scripts/py-ci.sh`, `scripts/ci.sh`, `readelf -d` по `.so`
(нет внешней `libmbedcrypto`), установка wheel в чистый venv.
## 3. GitHub-зеркало и Custom Repositories (HACS)
HACS устанавливает интеграции только с публичных **GitHub**-репозиториев
(GitLab/Gitea не поддерживаются:
https://hacs.xyz/docs/faq/other_git_providers/). Публикация в
default-репозиторий HACS не требуется — достаточно Custom Repositories, но
хостинг обязан быть GitHub.
```sh
git remote add github git@github.com:<owner>/fgl-aircon.git
git push --mirror github
```
После зеркала:
* заполнить на GitHub Description, Topics (`home-assistant`, `hacs`,
`fujitsu`, `air-conditioner`), включить Issues (проверяет HACS Action);
* проверить `codeowners` в manifest (`@petr.polezhaev`; для GitHub нужен
реальный GitHub-логин);
* обновить `version` манифеста под тег; заменить заглушки
`screenshots/step-N.png` и `brand/*.png` реальными ассетами;
* создать тег (semver) — HACS покажет версию.
Готовые файлы HACS: `hacs.json`, `info.md`, `LICENSE` (MIT),
`custom_components/fglair/brand/` (icon/icon@2x/logo + dark-варианты),
workflows `.github/workflows/{validate-hacs,hassfest}.yaml`.
## 4. Приёмка на живом стенде
* `tests/acceptance/test_esphome_ha.py quick` — матрица изменений (HA;
с `--esphome-host` шаги «режим/уставка» идут через ESPHome, проверка — по
состоянию в HA), возврат к исходному.
* `long --hours 24 --interval 3600 --report acceptance.csv`.
* Сценарии: 503 (два слота), key_error + Repair, offline/восстановление,
два устройства, options flow (копирование/смена ключа), reconfigure.
## 5. Ограничения стенда
* Реального железа/облака в CI нет: протокол проверен mock-модулем,
облако — мок-сервером; приёмочный скрипт имеет self-test на моке HA REST.
* Суточный soak, re-key и облачный вход — только на приборе/аккаунте.
* Gitea Actions: встроенный `GITEA_TOKEN` не публикует пакеты (нужен PAT);
`actions/checkout`/`setup-python` тянутся с github.com (для изолированного
инстанса используйте абсолютные URL зеркал).