275 lines
12 KiB
Markdown
275 lines
12 KiB
Markdown
# Instructions après mise à jour ou rollback AppDaemon
|
|
|
|
Préparé le 8 novembre 2026 pour cette installation `/conf`.
|
|
À suivre par Codex après installation de **4.5.14**, ou retour en **4.5.10**.
|
|
Ce document prépare l'intervention : sa rédaction n'a appliqué aucun patch ni redémarré le service.
|
|
|
|
## 1. Identifier l'installation avant toute modification
|
|
|
|
Lire ce document et `docs/appdaemon-local-changes.md`. Conserver les modifications
|
|
applicatives existantes, les configurations YAML et les exclusions de dossiers.
|
|
Ne pas restaurer les anciennes instrumentations des utility loops : elles ont été
|
|
retirées volontairement et archivées dans `tools/archive/`.
|
|
|
|
Exécuter dans le conteneur, avec le Python réellement utilisé par AppDaemon :
|
|
|
|
```sh
|
|
python3 - <<'PY'
|
|
import inspect, sys
|
|
from importlib.metadata import version
|
|
import appdaemon
|
|
from appdaemon.utils import deep_compare
|
|
print('Python :', sys.executable)
|
|
print('Version :', version('appdaemon'))
|
|
print('Paquet :', appdaemon.__file__)
|
|
print('deep_compare :', inspect.getsourcefile(deep_compare))
|
|
print(inspect.getsource(deep_compare))
|
|
PY
|
|
```
|
|
|
|
Si le processus utilise un autre environnement, employer son interpréteur pour
|
|
les inspections, modifications et tests. Ne pas déduire la version du seul tag
|
|
Docker. Vérifier aussi l'Entrypoint/Cmd du conteneur et le script effectivement
|
|
exécuté ; une image personnalisée peut différer de l'image officielle.
|
|
Pour une autre version que 4.5.10 ou 4.5.14, refaire la comparaison avec ses sources.
|
|
|
|
Avant chaque édition, sauvegarder le fichier original dans un dossier daté sous
|
|
`/conf/tools/backups/appdaemon-<version>-<date>/`, en notant son chemin absolu,
|
|
sa version et son empreinte SHA-256. Ne pas écraser une sauvegarde précédente.
|
|
N'appliquer chaque changement qu'une fois ; si déjà présent, le vérifier.
|
|
Ne jamais remplacer un fichier 4.5.14 par une sauvegarde 4.5.10.
|
|
|
|
## 2. Tableau des changements
|
|
|
|
| Élément | 4.5.10 (rollback) | 4.5.14 |
|
|
|---|---|---|
|
|
| Timestamp de rafraîchissement HASS | Appliquer le patch `plugin.name` | Déjà intégré ; vérifier seulement |
|
|
| Comparaison des clés dans `deep_compare` | Appliquer dans `utils.py` | Appliquer dans `utils/misc.py` |
|
|
| Optimisation des logs ordinaires | Conserver le raccourci de `LoggerInterface` | Optimisation intégrée au core ; conserver le wrapper existant si compatible |
|
|
| Archivage au démarrage Docker | Ajouter l'appel dans `dockerStart.sh` | Ajouter l'appel dans `/start.sh` pour l'image officielle |
|
|
|
|
## 3. Patch HASS : 4.5.10 seulement
|
|
|
|
Dans le paquet installé, fichier `plugin_management.py`, méthode
|
|
`update_plugin_state()`, remplacer uniquement cet appel dans le `finally` :
|
|
|
|
```diff
|
|
- await self.refresh_update_time(plugin)
|
|
+ await self.refresh_update_time(plugin.name)
|
|
```
|
|
|
|
Cela évite de redemander l'état complet de Home Assistant chaque seconde après
|
|
expiration du délai de rafraîchissement (10 minutes par défaut).
|
|
Le correctif est intégré depuis 4.5.12 et confirmé dans le tag 4.5.14.
|
|
En 4.5.14, contrôler la ligne, sans ajouter un second patch.
|
|
|
|
Référence locale : `APPDAEMON_BANDWIDTH_BUG_FIX.md`.
|
|
|
|
## 4. Patch deep_compare : les deux versions
|
|
|
|
Localiser le fichier avec `inspect.getsourcefile(deep_compare)` :
|
|
|
|
- 4.5.10 : `appdaemon/utils.py`.
|
|
- 4.5.14 : `appdaemon/utils/misc.py` (le module a été réorganisé).
|
|
|
|
Dans `deep_compare()`, ajouter immédiatement après `data = data or {}` :
|
|
|
|
```python
|
|
if check.keys() != data.keys():
|
|
return False
|
|
```
|
|
|
|
Conserver tout le reste de la fonction propre à la version installée.
|
|
En particulier, garder `current = data.get(k)` en 4.5.14.
|
|
Le début de fonction doit donc ressembler à ceci :
|
|
|
|
```python
|
|
def deep_compare(check: dict, data: dict) -> bool:
|
|
"""Compares 2 nested dictionaries of values"""
|
|
data = data or {}
|
|
|
|
if check.keys() != data.keys():
|
|
return False
|
|
|
|
# Suite existante, différente selon la version : ne pas la remplacer.
|
|
```
|
|
|
|
La 4.5.14 évite le KeyError à l'ajout d'une clé, mais ne détecte toujours pas
|
|
certaines suppressions : la fonction officielle renvoie `True` pour
|
|
`deep_compare({}, {'input_selection': {}})`. Le patch corrige aussi les
|
|
suppressions imbriquées et distingue une clé absente d'une valeur `None`.
|
|
|
|
Vérifier dans un nouveau processus Python après modification :
|
|
|
|
```sh
|
|
python3 - <<'PY'
|
|
from appdaemon.utils import deep_compare
|
|
assert deep_compare({'input_selection': {}}, {}) is False
|
|
assert deep_compare({}, {'input_selection': {}}) is False
|
|
assert deep_compare({'x': {'a': 1}}, {'x': {}}) is False
|
|
assert deep_compare({'x': {}}, {'x': {'a': 1}}) is False
|
|
assert deep_compare({'x': None}, {}) is False
|
|
assert deep_compare({'x': [1, 2]}, {'x': [1, 2]}) is True
|
|
assert deep_compare({'x': [1, 2]}, {'x': [2, 1]}) is False
|
|
assert deep_compare({'x': {'a': 1}}, {'x': {'a': 1}}) is True
|
|
assert deep_compare({'x': {}}, {'x': None}) is False
|
|
assert deep_compare({}, None) is True
|
|
assert deep_compare({'input_selection': {}}, None) is False
|
|
print('OK : 11 vérifications deep_compare')
|
|
PY
|
|
```
|
|
|
|
Référence locale : `APPDAEMON_RELOAD_BUG_FIX.md`. Ses anciens chemins de
|
|
sauvegarde `.bak` ne sont plus actifs ; utiliser la sauvegarde de cette intervention.
|
|
|
|
## 5. LoggerInterface : conserver les fonctionnalités locales
|
|
|
|
Fichier persistant : `apps/ad_toolbox/logger_interface.py`, méthode `_write_log()`.
|
|
|
|
En **4.5.10**, conserver le raccourci existant : pour un message texte sans
|
|
`__module__`, `__line__` ou `__function__`, et avec les méthodes standard ADAPI,
|
|
appeler `api._log()` sans passer par l'inspection de pile. Garder le repli vers
|
|
`api.log()` pour les substitutions et les méthodes personnalisées. Préserver les
|
|
options d'encodage, le routage des logs et les groupes de messages.
|
|
Ne pas ajouter un autre patch dans `adapi.py` : il était volontairement revenu
|
|
au code officiel 4.5.10.
|
|
|
|
En **4.5.14**, `_sub_stack()` contient déjà le raccourci évitant `inspect.stack()`
|
|
sans marqueurs. Aucun patch core de logging n'est nécessaire. Conserver le
|
|
wrapper applicatif et ses fonctionnalités ; la suppression du raccourci local
|
|
redondant est facultative, pas un prérequis de migration. Tester sa compatibilité.
|
|
|
|
Tests existants :
|
|
|
|
```sh
|
|
python3 -m unittest discover -s /conf/apps/ad_toolbox/unit_tests -p 'test_logger_interface_fast_path.py' -v
|
|
python3 -m unittest discover -s /conf/apps/ad_toolbox/unit_tests -p 'test_logger_interface_grouping.py' -v
|
|
```
|
|
|
|
**Adaptation de test nécessaire en 4.5.14 :**
|
|
`test_direct_log_is_not_modified` attend actuellement `stack.assert_called_once()`
|
|
pour `api.log('Direct log')`. Cette attente correspond à 4.5.10. Pour 4.5.14,
|
|
attendre `stack.assert_not_called()`. Si le test doit couvrir les deux versions,
|
|
choisir explicitement l'attente selon la version installée, en conservant
|
|
l'assertion d'identité de `_sub_stack`. Ne pas modifier le core pour satisfaire
|
|
l'ancienne attente. Vérifier que les tests d'intégration ne sont pas ignorés
|
|
faute d'import AppDaemon.
|
|
|
|
## 6. Patch dockerStart / start.sh : les deux versions
|
|
|
|
### Comportement local à préserver
|
|
|
|
Avant le lancement d'AppDaemon, appeler une seule fois :
|
|
|
|
```sh
|
|
sh "$CONF/archiveLogs.sh"
|
|
```
|
|
|
|
Ce script persistant archive les anciens `*.log*` et `memory_usage.csv` dans
|
|
`/conf/logs/archive/<horodatage>/`, puis lance le suivi mémoire en arrière-plan.
|
|
Conserver le contenu actuel de `/conf/archiveLogs.sh`.
|
|
Ne pas lancer le script manuellement pendant qu'AppDaemon écrit ses logs pour
|
|
le « tester » : il déplacerait les fichiers ouverts. Ne pas lancer le script
|
|
de démarrage complet dans le conteneur déjà actif : cela lancerait un second AppDaemon.
|
|
|
|
### 4.5.10
|
|
|
|
Le script observé est `/usr/src/app/dockerStart.sh`.
|
|
`/conf/dockerStart.sh` est un **lien symbolique** vers ce fichier, pas une copie
|
|
persistante du patch. Après recréation du conteneur, la cible peut être remplacée.
|
|
Ajouter l'appel après les installations de dépendances, juste avant le lancement :
|
|
|
|
```sh
|
|
sh "$CONF/archiveLogs.sh"
|
|
|
|
# Lets run it!
|
|
exec python3 -m appdaemon -c $CONF "$@"
|
|
```
|
|
|
|
### 4.5.14 : changement de point d'entrée confirmé dans le tag officiel
|
|
|
|
Le Dockerfile copie `scripts/start.sh` vers **`/start.sh`** et définit
|
|
`ENTRYPOINT ["/start.sh"]`. Il n'utilise plus `dockerStart.sh`.
|
|
Dans cette image, patcher `/start.sh`, pas l'ancien lien `/conf/dockerStart.sh`.
|
|
Ajouter le même appel après l'installation des dépendances et avant l'exec :
|
|
|
|
```sh
|
|
sh "$CONF/archiveLogs.sh"
|
|
|
|
# Lets run it!
|
|
exec uv run --frozen appdaemon -c $CONF "$@"
|
|
```
|
|
|
|
Conserver le lancement `uv`, les installations via `uv pip`, le `PYTHONPATH`
|
|
et le répertoire de configuration exemple `/opt/conf` propres à cette version.
|
|
Ne pas recopier l'ancien script 4.5.10 par-dessus `/start.sh`.
|
|
Si l'image déployée possède un autre point d'entrée, transposer cet appel dans
|
|
le script réellement utilisé et noter le chemin dans le compte rendu.
|
|
L'ancien lien peut rester inutilisé ; ne pas le prendre comme preuve du patch.
|
|
|
|
### Vérification sans exécution
|
|
|
|
```sh
|
|
sh -n /conf/archiveLogs.sh
|
|
# Choisir le script réellement utilisé :
|
|
sh -n /usr/src/app/dockerStart.sh # 4.5.10
|
|
# OU
|
|
sh -n /start.sh # 4.5.14 officielle
|
|
```
|
|
|
|
Inspecter le script : exactement un appel actif à `archiveLogs.sh`, avant l'exec.
|
|
Ces modifications hors `/conf` sont perdues lors d'une recréation du conteneur,
|
|
comme les patchs Python. Les réappliquer à chaque nouvelle image, ou les intégrer
|
|
explicitement à une image dérivée si cela fait partie de l'intervention demandée.
|
|
|
|
## 7. Redémarrage et validation finale
|
|
|
|
Après application et vérifications, redémarrer le conteneur selon le mécanisme
|
|
habituel de cette installation, dans le périmètre de l'intervention demandée.
|
|
Un simple rechargement d'app ne remplace pas les fonctions core déjà importées
|
|
et ne réexécute pas le script de démarrage.
|
|
|
|
Vérifier après redémarrage :
|
|
|
|
1. Version réellement lancée et absence d'erreurs de démarrage/import.
|
|
2. Patch `deep_compare` toujours présent et 11 vérifications réussies dans le
|
|
même environnement que le service (une installation de dépendances au boot
|
|
pourrait avoir remplacé le paquet).
|
|
3. Message `[archiveLogs]`, archive créée si des anciens logs existaient,
|
|
nouveau `memory_usage.csv`, un seul processus `archiveLogs.sh --watch-memory`.
|
|
Vérifier l'ajout de mesures à l'intervalle configuré (300 secondes par défaut).
|
|
Avec `uv`, le PID 1 peut être uv : si les colonnes RSS AppDaemon sont vides,
|
|
vérifier le processus réel ; les métriques du conteneur restent distinctes.
|
|
4. Connexion Home Assistant et absence de rafraîchissements complets chaque
|
|
seconde après le délai de refresh configuré (10 minutes par défaut).
|
|
5. Tests du logger réussis avec l'attente adaptée à la version.
|
|
6. Si un essai de reload réel est nécessaire, utiliser une app de test isolée
|
|
sans action domotique ; vérifier ajout/suppression d'une clé imbriquée et
|
|
nettoyer l'essai. Ne pas modifier chauffage/volets pour ce test.
|
|
|
|
Mettre à jour `docs/appdaemon-local-changes.md` avec la version, les fichiers
|
|
réellement modifiés, les sauvegardes, résultats et statut du redémarrage.
|
|
Séparer les vérifications exécutées de celles restant à observer ; ne pas
|
|
annoncer une validation du service sur la seule base des tests unitaires.
|
|
|
|
## 8. Rollback vers 4.5.10
|
|
|
|
Revenir à l'image 4.5.10 prévue par le déploiement, puis reprendre les sections
|
|
1 à 7 pour **4.5.10** : patch HASS + clés `deep_compare` + raccourci applicatif
|
|
logger + appel d'archivage dans le vrai `dockerStart.sh`.
|
|
Les fichiers `/conf` et le sous-module `apps/ad_toolbox` doivent être conservés.
|
|
Si le test du logger a été rendu compatible avec les deux versions, le conserver.
|
|
Ne pas restaurer de fichiers core 4.5.14 dans 4.5.10, ni les anciennes sondes de
|
|
diagnostic archivées. Vérifier à nouveau après le redémarrage du rollback.
|
|
|
|
## Sources de référence
|
|
|
|
- Inventaire : [appdaemon-local-changes.md](appdaemon-local-changes.md).
|
|
- Diff core local 4.5.10 : [appdaemon-core-4.5.10.diff](appdaemon-core-4.5.10.diff).
|
|
- [4.5.14 : plugin_management.py](https://github.com/AppDaemon/appdaemon/blob/4.5.14/appdaemon/plugin_management.py).
|
|
- [4.5.14 : utils/misc.py](https://github.com/AppDaemon/appdaemon/blob/4.5.14/appdaemon/utils/misc.py).
|
|
- [4.5.14 : adapi.py](https://github.com/AppDaemon/appdaemon/blob/4.5.14/appdaemon/adapi.py).
|
|
- [4.5.14 : Dockerfile](https://github.com/AppDaemon/appdaemon/blob/4.5.14/Dockerfile).
|
|
- [4.5.14 : scripts/start.sh](https://github.com/AppDaemon/appdaemon/blob/4.5.14/scripts/start.sh).
|
|
- [4.5.10 : dockerStart.sh](https://github.com/AppDaemon/appdaemon/blob/4.5.10/dockerStart.sh).
|