feat(lib): helper ini_set idempotent pour merge de fichiers INI #18

Closed
opened 2026-07-30 15:43:04 +00:00 by Damien · 0 comments
Owner

Contexte

openbao/install.sh applique le pattern « écrire la config seulement si elle est absente » :

if [[ ! -f "${BAO_CONFIG_DIR}/config.hcl" ]]; then
  cat > ... <<EOF
else
  log_info "Existing config preserved."
fi

Ce pattern est correct pour OpenBao (config figée après init), mais il entre en collision avec la règle d'idempotence du dépôt : rejouer le script doit appliquer les configurations manquantes. Appliqué tel quel à l'app.ini de Gitea, une instance déjà installée ne recevrait jamais les nouvelles clés [security] ajoutées par une version ultérieure du script.

Il faut donc un merge clé par clé, pas un tout-ou-rien au niveau du fichier.

Fonction à ajouter

Dans lib/common.sh :

ini_set <fichier> <section> <clé> <valeur>

Sémantique attendue :

Cas Comportement
Fichier absent Le créer
Section absente L'ajouter en fin de fichier
Clé absente dans la section L'insérer dans la section
Clé présente avec la bonne valeur No-op
Clé présente avec une autre valeur La remplacer en place
Autres sections / clés Jamais touchées

Contraintes

  • Bash + outils POSIX de base uniquement (awk / sed), pas de dépendance type crudini — cohérent avec « self-contained, no frameworks ».
  • Ne doit pas réordonner les sections ni écraser les commentaires existants.
  • Doit gérer les clés dupliquées entre sections différentes (ENABLED existe dans [metrics] et [actions]) — le scope est la section, jamais le fichier entier.
  • Écriture atomique (fichier temporaire + mv) pour ne pas corrompre l'app.ini si le script est interrompu.
  • Tolérer l'espacement variable autour du = en lecture ; normaliser en CLE = valeur en écriture.

Documentation dans l'en-tête de lib/common.sh

Le bloc de commentaires en tête de fichier documente un contrat explicite : detect_latest_alpine_template(), enable_tty1_autologin() et refresh_os_packages() sont Alpine-only et une future variante Debian doit avoir sa propre fonction.

ini_set() est le premier helper OS-agnostique du fichier. Il faut l'écrire noir sur blanc dans l'en-tête, sinon quelqu'un la dupliquera par symétrie avec les autres.

Fichier touché

  • lib/common.sh

Critères d'acceptation

  • Les 6 cas du tableau ci-dessus passent sur un app.ini de test
  • Deux appels successifs identiques laissent le fichier strictement inchangé (diff vide) — c'est le test d'idempotence
  • ini_set sur [metrics] ENABLED ne modifie pas [actions] ENABLED
  • Les commentaires et lignes vides du fichier d'origine sont préservés
  • L'en-tête de lib/common.sh mentionne le caractère OS-agnostique de la fonction
  • shellcheck lib/common.sh sans nouvelle alerte

Dépendances

Aucune. Bloque #19 (le script Gitea consomme cette fonction).

## Contexte `openbao/install.sh` applique le pattern « écrire la config seulement si elle est absente » : ```bash if [[ ! -f "${BAO_CONFIG_DIR}/config.hcl" ]]; then cat > ... <<EOF else log_info "Existing config preserved." fi ``` Ce pattern est correct pour OpenBao (config figée après init), mais il entre en collision avec la règle d'idempotence du dépôt : **rejouer le script doit appliquer les configurations manquantes**. Appliqué tel quel à l'`app.ini` de Gitea, une instance déjà installée ne recevrait jamais les nouvelles clés `[security]` ajoutées par une version ultérieure du script. Il faut donc un merge clé par clé, pas un tout-ou-rien au niveau du fichier. ## Fonction à ajouter Dans `lib/common.sh` : ```bash ini_set <fichier> <section> <clé> <valeur> ``` Sémantique attendue : | Cas | Comportement | |---|---| | Fichier absent | Le créer | | Section absente | L'ajouter en fin de fichier | | Clé absente dans la section | L'insérer dans la section | | Clé présente avec la bonne valeur | No-op | | Clé présente avec une autre valeur | La remplacer **en place** | | Autres sections / clés | Jamais touchées | ## Contraintes - **Bash + outils POSIX de base uniquement** (`awk` / `sed`), pas de dépendance type `crudini` — cohérent avec « self-contained, no frameworks ». - Ne doit pas réordonner les sections ni écraser les commentaires existants. - Doit gérer les clés dupliquées entre sections différentes (`ENABLED` existe dans `[metrics]` **et** `[actions]`) — le scope est la section, jamais le fichier entier. - Écriture atomique (fichier temporaire + `mv`) pour ne pas corrompre l'`app.ini` si le script est interrompu. - Tolérer l'espacement variable autour du `=` en lecture ; normaliser en `CLE = valeur` en écriture. ## Documentation dans l'en-tête de `lib/common.sh` Le bloc de commentaires en tête de fichier documente un contrat explicite : `detect_latest_alpine_template()`, `enable_tty1_autologin()` et `refresh_os_packages()` sont **Alpine-only** et une future variante Debian doit avoir sa propre fonction. `ini_set()` est le premier helper **OS-agnostique** du fichier. Il faut l'écrire noir sur blanc dans l'en-tête, sinon quelqu'un la dupliquera par symétrie avec les autres. ## Fichier touché - `lib/common.sh` ## Critères d'acceptation - [ ] Les 6 cas du tableau ci-dessus passent sur un `app.ini` de test - [ ] Deux appels successifs identiques laissent le fichier **strictement inchangé** (`diff` vide) — c'est le test d'idempotence - [ ] `ini_set` sur `[metrics] ENABLED` ne modifie pas `[actions] ENABLED` - [ ] Les commentaires et lignes vides du fichier d'origine sont préservés - [ ] L'en-tête de `lib/common.sh` mentionne le caractère OS-agnostique de la fonction - [ ] `shellcheck lib/common.sh` sans nouvelle alerte ## Dépendances Aucune. **Bloque #19** (le script Gitea consomme cette fonction).
Damien added this to the gitea-lxc-migration milestone 2026-07-30 15:43:04 +00:00
Damien added a new dependency 2026-07-30 19:08:31 +00:00
Damien removed a dependency 2026-07-30 19:10:23 +00:00
Damien added a new dependency 2026-07-30 19:10:45 +00:00
Damien added reference feat/lib-ini-set 2026-08-01 08:23:44 +00:00
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Reference: Damien/infra-scripts#18