Étape 4 du chantier de documentation. tools/ci-quality.sh porte les trois
vérifications qui se posent au même endroit — elles partagent la même sortie
(doc-generated/) et la même commande de réparation, les séparer ferait trois jobs
qui régénèrent trois fois la même chose :
1. l'index des règles est VRAI (code de retour de gen-rules.py) ;
2. la doc Doxygen est complète — 0 avertissement, DoD §5 ;
3. l'index est REPRODUCTIBLE : deux passes, un seul résultat.
PAS EN SERVICE, et l'extension le garantit : ci/gitea-workflow.yml.disabled ne
déclenche rien tant qu'il n'est pas déplacé dans .gitea/workflows/. La raison est
datée dans le fichier — forge muette, plus de trente commits en attente ici et
plus de soixante côté app ; un job activé à l'aveugle échouerait au moment précis
où tout le monde pousse, et le premier réflexe serait de le désactiver.
CHAQUE ÉCHEC DONNE LA COMMANDE À LANCER. Un job qui annonce « l'index est
périmé » sans dire quoi faire se contourne en le désactivant : c'est le chemin de
moindre effort, et il gagne toujours.
VÉRIFIÉ AVANT D'ÊTRE DÉCLARÉ PRÊT, et ça ne passait pas du premier coup.
— Les 26 avertissements Doxygen de ce matin sont CORRIGÉS, pas contournés par un
cliquet sur un compte de référence : c'était de la dette DoD-5 (retours et
paramètres non documentés dans relayrouter.h, energyarbitrator.h, loadconfig.h,
les trois clearFault(), ILoadAdapter::updateSoftConfig), plus deux que j'avais
introduits — un \rule{} dans un titre \par, et un \param energyLogs qui ne
correspond à aucun argument. Le seuil est donc ZÉRO, le seul qui ne rote pas.
— Et le script lui-même échouait sur un dépôt SAIN : `grep -c ... || echo 0`
affiche 0 PUIS sort en 1 quand il ne trouve rien, si bien que le « || » empile
un second zéro et que le test entier casse. Corrigé ici et dans gen-doc.sh, qui
portait le même piège. Une commande de mesure dont l'échec produit une lecture
fausse — le motif de la semaine, appliqué à l'outil.
CE QUI N'EST PAS VÉRIFIÉ, et pourquoi : « régénérer et refuser si ça diffère de
ce qui est commité » n'a rien à comparer, doc-generated/ étant dans .gitignore.
Le risque qu'un tel diff attraperait — un artefact commité qui dérive de sa
source — a été SUPPRIMÉ en ne le commitant pas, pas déplacé. Ce qui reste à
garantir est que l'index soit vrai (contrôle 1) et déterministe (contrôle 3).
État au 2026-08-29 : ./tools/ci-quality.sh → RC=0, 113 règles, 0 avertissement.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015F7G5VeaPVSMeVNjiGj36p
112 lines
4.7 KiB
Bash
Executable File
112 lines
4.7 KiB
Bash
Executable File
#!/bin/bash
|
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
# Copyright (C) 2025 - 2026, Patrick Schurig / ETM PowerSync
|
|
#
|
|
# Génération reproductible de la documentation — UNE seule commande, le Doxyfile
|
|
# du dépôt, épinglé.
|
|
#
|
|
# ./tools/gen-doc.sh
|
|
#
|
|
# Pourquoi une commande unique plutôt qu'un « doxygen » lancé à la main : le
|
|
# nombre d'avertissements NE VEUT RIEN DIRE hors de sa configuration exacte. Le
|
|
# piège a déjà été rencontré — 163 avertissements sans générateur de sortie
|
|
# contre 113 avec HTML+XML, sur le même arbre. Un chiffre de référence ne se
|
|
# compare qu'à un chiffre produit de la même façon ; ce script est cette façon.
|
|
#
|
|
# DÉPENDANCES — de la CIBLE DOC uniquement, jamais du build du paquet :
|
|
# apt install doxygen graphviz
|
|
# Le conteneur build-cross-arm64 n'a rien à faire de Graphviz : il compile, il
|
|
# ne dessine pas.
|
|
|
|
set -u
|
|
|
|
RACINE="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
DOXYFILE="$RACINE/Doxyfile"
|
|
SORTIE="$RACINE/doc-generated"
|
|
VERSION_ATTENDUE="1.9.8"
|
|
|
|
cd "$RACINE" || exit 1
|
|
|
|
manquant=0
|
|
for outil in doxygen dot; do
|
|
if ! command -v "$outil" >/dev/null 2>&1; then
|
|
echo "MANQUANT : $outil" >&2
|
|
manquant=1
|
|
fi
|
|
done
|
|
if [ "$manquant" -ne 0 ]; then
|
|
echo "" >&2
|
|
echo "Dépendances de la cible doc : apt install doxygen graphviz" >&2
|
|
exit 127
|
|
fi
|
|
|
|
# L'INDEX DES RÈGLES d'abord : le Doxyfile le prend en entrée, et ses ancres {#LM-1105}
|
|
# sont ce qui rend \rule{} résoluble. Un index absent produirait des \ref cassés en masse,
|
|
# donc un compte d'avertissements incomparable — exactement ce que ce script existe pour
|
|
# empêcher.
|
|
#
|
|
# Son code de retour ne STOPPE pas la génération : un index incomplet reste utile à lire,
|
|
# et refuser de produire la doc parce qu'une règle manque punirait le mauvais geste. Il est
|
|
# répercuté à la fin, pour que l'appelant — un humain ou la CI — le voie.
|
|
VERSION_REELLE="$(doxygen --version | cut -d' ' -f1)"
|
|
if [ "$VERSION_REELLE" != "$VERSION_ATTENDUE" ]; then
|
|
# Avertissement et non erreur : la génération reste utile, mais le compte
|
|
# d'avertissements n'est plus comparable au chiffre de référence.
|
|
echo "ATTENTION : doxygen $VERSION_REELLE, référence établie sous $VERSION_ATTENDUE." >&2
|
|
echo " Les graphes restent valables ; le COMPTE d'avertissements," >&2
|
|
echo " lui, n'est pas comparable d'une version à l'autre." >&2
|
|
fi
|
|
|
|
rm -rf "$SORTIE"
|
|
|
|
# L'INDEX DES RÈGLES, et il se produit APRÈS le nettoyage — il vit DANS $SORTIE, donc le
|
|
# générer avant reviendrait à l'effacer aussitôt. Doxygen le prend en entrée : ses ancres
|
|
# {#LM-1105} sont ce qui rend \rule{} résoluble, et un index absent produirait des \ref
|
|
# cassés en masse, donc un compte d'avertissements incomparable — exactement ce que ce
|
|
# script existe pour empêcher.
|
|
#
|
|
# Son code de retour ne STOPPE pas la génération : un index incomplet reste utile à lire, et
|
|
# refuser de produire la doc parce qu'une règle manque punirait le mauvais geste. Il est
|
|
# répercuté à la fin, pour que l'appelant — humain ou CI — le voie.
|
|
echo "→ index des règles"
|
|
python3 "$RACINE/tools/gen-rules.py"
|
|
RC_REGLES=$?
|
|
JOURNAL="$(mktemp)"
|
|
trap 'rm -f "$JOURNAL"' EXIT
|
|
|
|
doxygen "$DOXYFILE" 2>"$JOURNAL"
|
|
code=$?
|
|
|
|
# Le Doxyfile écrit déjà ses avertissements dans WARN_LOGFILE ; on compte ici ce
|
|
# qui est réellement remonté, quelle que soit la destination.
|
|
LOGFILE="$(sed -n 's/^WARN_LOGFILE *= *//p' "$DOXYFILE" | tr -d ' ')"
|
|
if [ -n "$LOGFILE" ] && [ -f "$RACINE/$LOGFILE" ]; then
|
|
JOURNAL_EFFECTIF="$RACINE/$LOGFILE"
|
|
else
|
|
JOURNAL_EFFECTIF="$JOURNAL"
|
|
fi
|
|
# `wc -l`, jamais `grep -c ... || echo 0` : grep -c affiche 0 PUIS sort en 1 quand il ne
|
|
# trouve rien, et le « || » empile alors un second zéro dans la variable.
|
|
AVERTISSEMENTS="$(grep -i "warning" "$JOURNAL_EFFECTIF" 2>/dev/null | wc -l)"
|
|
|
|
echo ""
|
|
echo " doxygen $VERSION_REELLE (référence $VERSION_ATTENDUE)"
|
|
echo " graphviz $(dot -V 2>&1 | sed 's/^dot - graphviz version //; s/ .*//')"
|
|
echo " configuration $DOXYFILE"
|
|
echo " sortie $SORTIE (html/ + xml/)"
|
|
echo " avertissements $AVERTISSEMENTS"
|
|
echo ""
|
|
echo " Rappel : ce compte n'est comparable qu'à un compte produit par CE script."
|
|
echo " Rappel : le graphe d'héritage est tronqué par construction — la classe de"
|
|
echo " base amont SmartChargingManager est hors INPUT. Voir l'en-tête du"
|
|
echo " Doxyfile ; ne pas « réparer » en élargissant le périmètre."
|
|
|
|
if [ "$RC_REGLES" -ne 0 ]; then
|
|
echo ""
|
|
echo " ⚠ L'INDEX DES RÈGLES est incomplet — voir la sortie d'erreur ci-dessus."
|
|
echo " La documentation est produite quand même ; le code de retour, lui, le dit."
|
|
[ "$code" -eq 0 ] && code="$RC_REGLES"
|
|
fi
|
|
|
|
exit $code
|