ci: le contrôle de qualité documentaire — écrit, éprouvé, PAS en service
É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
This commit is contained in:
parent
a2ff20889c
commit
010a7da0f4
63
ci/gitea-workflow.yml.disabled
Normal file
63
ci/gitea-workflow.yml.disabled
Normal file
@ -0,0 +1,63 @@
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# ÉCRIT, PAS EN SERVICE — et l'extension `.disabled` est ce qui le garantit.
|
||||
#
|
||||
# POUR L'ACTIVER, quand la forge répondra et que le retard de commits sera résorbé :
|
||||
#
|
||||
# mkdir -p .gitea/workflows
|
||||
# git mv ci/gitea-workflow.yml.disabled .gitea/workflows/qualite-doc.yml
|
||||
#
|
||||
# Le déposer ailleurs que dans `.gitea/workflows/` ne déclenche rien : c'est
|
||||
# volontaire. Un fichier renommé est un geste ; un fichier au bon endroit est un
|
||||
# service.
|
||||
#
|
||||
# POURQUOI PAS MAINTENANT (2026-08-29). La forge ne répond pas et plus de trente
|
||||
# commits attendent en local dans ce dépôt, plus de soixante côté app. Un job
|
||||
# activé à l'aveugle échouerait à son premier passage — au moment précis où tout
|
||||
# le monde pousse — et le premier réflexe serait de le désactiver. Un garde-fou
|
||||
# désactivé une fois ne se réactive jamais.
|
||||
#
|
||||
# AVANT D'ACTIVER, lancer le contrôle À LA MAIN sur la branche visée :
|
||||
#
|
||||
# ./tools/ci-quality.sh
|
||||
#
|
||||
# Il passait sur l'état du dépôt au 2026-08-29 — index RC=0 (113 règles), doxygen
|
||||
# 0 avertissement. S'il échoue, la cause est dans le dépôt, pas dans le job : le
|
||||
# corriger AVANT l'activation, jamais après. Un job qu'on n'a jamais vu passer
|
||||
# n'est pas un job, c'est une intention.
|
||||
#
|
||||
# CE QU'IL VÉRIFIE — trois choses, un seul endroit, parce qu'elles partagent la
|
||||
# même sortie et la même commande de réparation :
|
||||
# 1. l'index des règles est VRAI (orphelins, domiciles ambigus, numéros retirés
|
||||
# réattribués) ;
|
||||
# 2. la documentation Doxygen est complète (0 avertissement, DoD §5) ;
|
||||
# 3. l'index est REPRODUCTIBLE (deux passes, un seul résultat).
|
||||
#
|
||||
# Ce qu'il ne vérifie PAS : « régénérer et refuser si ça diffère de ce qui est
|
||||
# commité ». `doc-generated/` est dans .gitignore ; il n'y a rien à comparer, et
|
||||
# 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é.
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
name: qualité documentaire
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ feature/beta-rulebased, main ]
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
qualite-doc:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
# doxygen ET graphviz : dépendances de la CIBLE DOC uniquement, jamais du
|
||||
# build du paquet. Sans elles le contrôle 2 ne s'exécute pas — et il le DIT
|
||||
# au lieu de passer en silence, ce qui serait un faux vert.
|
||||
- name: dépendances de la cible doc
|
||||
run: sudo apt-get update && sudo apt-get install -y doxygen graphviz python3
|
||||
|
||||
# Une commande unique, celle qu'un humain lance. Si le job et la machine de
|
||||
# développement divergeaient, le job cesserait d'être reproductible chez soi
|
||||
# — et un contrôle qu'on ne peut pas rejouer localement se contourne.
|
||||
- name: contrôle de qualité documentaire
|
||||
run: ./tools/ci-quality.sh
|
||||
@ -123,6 +123,7 @@ public:
|
||||
//! La généralisation est portée par **ECS-414** (lot de mise en configuration
|
||||
//! du SgReadyAdapter). Déclaré explicitement plutôt qu'hérité d'un défaut vide.
|
||||
//! \brief Lève le verrou de défaut (ECS-414). La consigne réelle est RELUE, pas supposée.
|
||||
//! \return Vrai si un défaut a réellement été levé ; faux s'il n'y en avait pas.
|
||||
bool clearFault() override;
|
||||
|
||||
//! \return Vrai si la charge est en défaut (plus aucune consigne écrite).
|
||||
|
||||
@ -82,6 +82,7 @@ public:
|
||||
//! du SgReadyAdapter). Déclaré explicitement plutôt qu'hérité d'un défaut vide.
|
||||
//! Aucun mécanisme de défaut côté EV : il n'y a jamais rien à lever. Le dire
|
||||
//! explicitement plutôt que de laisser un corps vide (règle 7-c).
|
||||
//! \return Vrai si un défaut a réellement été levé ; faux s'il n'y en avait pas.
|
||||
bool clearFault() override { return false; }
|
||||
|
||||
/*!
|
||||
|
||||
@ -141,6 +141,7 @@ public:
|
||||
* client qui réordonne ses priorités depuis l'app pourrait faire court-cycler son
|
||||
* compresseur — et provoquerait des réécritures de relais inutiles.
|
||||
*
|
||||
* \param label Nouveau libellé d'affichage.
|
||||
* \param priority Nouveau rang de service (ASC, 1 = premier servi).
|
||||
* \param needs Nouveaux besoins déclarés.
|
||||
* \warning NE DOIT jamais toucher au câblage, aux paliers ni aux verrous : ces
|
||||
|
||||
@ -72,6 +72,7 @@ struct RelayStageTable
|
||||
* combinaison retenue à somme égale, que \c levels et l'appariement position par
|
||||
* position capturent.
|
||||
*/
|
||||
//! \param o Table comparée. \return Vrai si les deux tables décrivent le MÊME câblage.
|
||||
bool operator==(const RelayStageTable &o) const
|
||||
{
|
||||
if (levels != o.levels || mapping.size() != o.mapping.size())
|
||||
@ -84,9 +85,24 @@ struct RelayStageTable
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//! \brief Négation de \c operator==. \param o Table comparée. \return Vrai si elles diffèrent.
|
||||
bool operator!=(const RelayStageTable &o) const { return !(*this == o); }
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Adaptateur d'une charge commandée par une COMBINAISON de relais (rév. 3).
|
||||
*
|
||||
* Traduit une enveloppe en watts en un palier, et le palier en contacts à fermer. Toute la
|
||||
* combinatoire vit ici : l'optimiseur ne voit que des watts, jamais un relais ni un index de
|
||||
* palier (ECS-306). Les paliers sont DÉRIVÉS des sous-ensembles de relais (\c deriveStages),
|
||||
* ce qui couvre les topologies non cascadées et les puissances quelconques.
|
||||
*
|
||||
* \invariant Coupure avant fermeture à chaque transition — jamais deux contacts en conflit.
|
||||
* \invariant Les verrous \c minOn / \c minOff sont INTERNES à l'adaptateur, évalués sur le
|
||||
* \c now reçu en paramètre, jamais sur l'horloge.
|
||||
* \invariant Un échec d'écriture pose un défaut COLLANT (ECS-410) : plus aucune commande
|
||||
* n'est émise jusqu'à \c clearFault().
|
||||
*/
|
||||
class RelayRouter : public QObject, public ILoadAdapter
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -119,6 +135,7 @@ public:
|
||||
//! \return currentPowerW = somme des \c currentPower des relais ON (mesuré), sinon nominal commandé.
|
||||
LoadTelemetry telemetry() const override;
|
||||
|
||||
//! \param now Temps de cycle — source unique des verrous (contrat \c ILoadAdapter).
|
||||
//! \return LoadContext §5 (watts uniquement : powerLevels, currentPowerW — aucun relais).
|
||||
LoadContext toLoadContext(const QDateTime &now) const override;
|
||||
|
||||
@ -131,12 +148,13 @@ public:
|
||||
*/
|
||||
LoadAction applyAction(const LoadAction &action, const QDateTime &now) override;
|
||||
|
||||
//! \brief Palier courant (0 = tout coupé).
|
||||
//! \brief Palier courant. \return Index du palier, 0 = tout coupé.
|
||||
int currentStage() const { return m_currentStage; }
|
||||
//! \brief Puissance (W) du palier courant.
|
||||
//! \brief Puissance du palier courant. \return Watts du palier appliqué ; 0 si hors table.
|
||||
double currentSetpointW() const { return m_currentStage < m_levels.size() ? m_levels.at(m_currentStage) : 0.0; }
|
||||
|
||||
//! \brief Met à jour les champs qui ne touchent PAS le matériel (ECS-412).
|
||||
//! \param label Nouveau libellé d'affichage.
|
||||
//! \param priority Nouveau rang de service.
|
||||
//! \param needs Nouveaux besoins déclarés.
|
||||
//! \note Permet à l'arbitre de refléter un changement de priorité SANS détruire
|
||||
@ -159,6 +177,7 @@ public:
|
||||
|
||||
/*!
|
||||
* \brief Lève le verrou de défaut (ECS-410, RPC \c NymeaEnergy.ClearLoadFault).
|
||||
* \return Vrai si un défaut a RÉELLEMENT été levé, faux s'il n'y en avait pas.
|
||||
* \note Le défaut est COLLANT par conception — « cesser toute commande jusqu'à
|
||||
* intervention ». Sa levée est donc un acte délibéré et tracé de l'opérateur, jamais
|
||||
* une expiration. L'état matériel réel étant inconnu après un défaut, il est RELU
|
||||
|
||||
@ -107,6 +107,7 @@ public:
|
||||
* \note L'état réel est RELU depuis les contacts, jamais supposé : après un défaut, le
|
||||
* motif 2 bits peut être valide mais non voulu.
|
||||
*/
|
||||
//! \return Vrai si un défaut a réellement été levé ; faux s'il n'y en avait pas.
|
||||
bool clearFault() override;
|
||||
|
||||
//! \return Vrai si la PAC est en défaut (plus aucune commande émise).
|
||||
|
||||
@ -39,6 +39,15 @@ class EnergyArbitrator : public SmartChargingManager
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
/*!
|
||||
* \brief Construit l'arbitre central. Mêmes dépendances que \c SmartChargingManager amont,
|
||||
* dont il hérite (justification : AGENTS.md, « 3b-iii »).
|
||||
* \param energyManager Gestionnaire d'énergie nymea (compteur racine, notifications).
|
||||
* \param thingManager Registre des Things — résolution des appareils pilotés/mesurés.
|
||||
* \param spotMarketManager Fournisseur de tarifs dynamiques (proxy EV).
|
||||
* \param configuration Réglages persistés (limites de phase, tolérance, réserve).
|
||||
* \param parent Parent QObject.
|
||||
*/
|
||||
explicit EnergyArbitrator(EnergyManager *energyManager, ThingManager *thingManager,
|
||||
SpotMarketManager *spotMarketManager,
|
||||
EnergyManagerConfiguration *configuration,
|
||||
@ -137,6 +146,7 @@ public:
|
||||
* \note Logique injectable (temps en paramètre) — en production appelée par le
|
||||
* handler \c powerBalanceChanged ; en simulation/test appelée directement. Le
|
||||
* déclencheur réel (signal) est câblé sous \c \#ifndef ENERGY_SIMULATION.
|
||||
* \param now Temps de cycle — jamais l'horloge, pour que la logique reste injectable.
|
||||
*/
|
||||
void recordMeterUpdate(const QDateTime &now);
|
||||
|
||||
@ -145,6 +155,7 @@ public:
|
||||
*
|
||||
* Si \c now − \c m_lastMeterUpdate > 90 s et pas déjà dégradé → \c applyDegradedMode().
|
||||
* Appliqué à la TRANSITION uniquement (idempotent ensuite). \p now = temps de cycle.
|
||||
* \param now Temps de cycle — jamais l'horloge, pour que la logique reste injectable.
|
||||
* \note Logique injectable — en production appelée par \c onMeterWatchdogTick() (QTimer
|
||||
* horloge murale, indépendant car le compteur muet fige aussi \c update()) ; en
|
||||
* simulation/test appelée directement avec le temps simulé. Symétrique de
|
||||
@ -205,6 +216,9 @@ public:
|
||||
/*!
|
||||
* \brief [3g-1] Cette borne participe-t-elle au waterfall de surplus ?
|
||||
*
|
||||
* \param ev Borne interrogée ; \c nullptr rend faux.
|
||||
* \return Vrai si la borne entre dans le waterfall de surplus ce cycle.
|
||||
*
|
||||
* **Deux** exclusions, et elles ne disent pas la même chose : le **mode manuel**
|
||||
* (\c ChargingModeNormal) est une INTENTION — l'utilisateur pilote, l'arbitre s'abstient ;
|
||||
* **aucun véhicule branché** (\c pluggedIn) est un CONSTAT — la borne ne peut rien tirer
|
||||
@ -434,7 +448,7 @@ private:
|
||||
* Le rang, le libellé, le domaine \c ev, \c enabled. Aucune charge utile : les limites de
|
||||
* la borne viennent du Thing (voir \c LoadConfig::isEvCharger()).
|
||||
*
|
||||
* \par Rang par défaut — EN QUEUE (\rule{LM-1209})
|
||||
* \par Rang par defaut — EN QUEUE (LM-1209)
|
||||
* `1 + max(rangs existants)`, donc libre par construction et sans bousculer personne. Ce
|
||||
* n'est pas une politique du plugin : le rang est un choix de l'installateur, et une
|
||||
* détection ne réordonne pas ce qu'un humain a décidé. Une borne détectée un mois après la
|
||||
|
||||
@ -206,10 +206,15 @@ public:
|
||||
* non nul : il se **dérive**, et le déclarer en double ouvrirait deux sources d'une même
|
||||
* vérité. `isValid()` refuse donc la combinaison.
|
||||
*/
|
||||
//! \return Plancher de modulation en watts ; 0 = aucun plancher déclaré.
|
||||
uint minPowerW() const { return m_minPowerW; }
|
||||
//! \brief Pose le plancher de modulation. \param v Watts, ou 0 pour aucun plancher.
|
||||
void setMinPowerW(uint v) { m_minPowerW = v; }
|
||||
|
||||
//! \brief Compteur dédié à CETTE charge (§11 / LM-1100). \return ThingId, vide si aucun.
|
||||
//! \note Prioritaire sur la mesure de l'appareil piloté quand il résout (LM-1105).
|
||||
QString meterThingId() const { return m_meterThingId; }
|
||||
//! \brief Rattache un compteur dédié. \param v ThingId, ou vide pour n'en rattacher aucun.
|
||||
void setMeterThingId(const QString &v) { m_meterThingId = v; }
|
||||
|
||||
/*!
|
||||
@ -252,7 +257,9 @@ public:
|
||||
* (température, puissance, heure) sans lequel les seuils éco/confort du §10 ne pourront
|
||||
* jamais être réglés autrement qu'au doigt mouillé.
|
||||
*/
|
||||
//! \return ThingId de la sonde ; vide si aucune n'est rattachée.
|
||||
QString sensorThingId() const { return m_sensorThingId; }
|
||||
//! \brief Rattache une sonde. \param v ThingId, ou vide pour n'en rattacher aucune.
|
||||
void setSensorThingId(const QString &v) { m_sensorThingId = v; }
|
||||
|
||||
//! \return Codes de domaine acceptés, ordre stable. Source unique de l'énumération :
|
||||
|
||||
114
tools/ci-quality.sh
Executable file
114
tools/ci-quality.sh
Executable file
@ -0,0 +1,114 @@
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
# Copyright (C) 2025 - 2026, Patrick Schurig / ETM PowerSync
|
||||
#
|
||||
# Contrôle de qualité documentaire — TROIS vérifications, un seul endroit.
|
||||
#
|
||||
# ./tools/ci-quality.sh
|
||||
#
|
||||
# Elles se posent au même endroit parce qu'elles partagent la même sortie
|
||||
# (`doc-generated/`) et la même commande de réparation. Les séparer ferait trois
|
||||
# jobs qui regénèrent trois fois la même chose.
|
||||
#
|
||||
# 1. L'INDEX DES RÈGLES est-il VRAI ? (tools/gen-rules.py, code de retour)
|
||||
# Casse sur : un identifiant cité et jamais défini ; un identifiant qui n'existe
|
||||
# qu'en ligne de tableau ; un domicile ambigu ; un numéro retiré réattribué.
|
||||
# 2. La DOC DOXYGEN est-elle complète ? (0 avertissement — DoD §5 d'AGENTS.md)
|
||||
# 3. Le tout est-il REPRODUCTIBLE ? (deux passes donnent le même index)
|
||||
#
|
||||
# ── CE QU'ON NE VÉRIFIE PAS, ET POURQUOI ────────────────────────────────────
|
||||
#
|
||||
# « Régénérer et refuser si ça diffère de ce qui est commité » n'a rien à comparer :
|
||||
# `doc-generated/` est dans .gitignore, décision du 2026-08-29 — versionner une page
|
||||
# générée produirait un diff à chaque édition de spec et des conflits sur un fichier
|
||||
# que personne ne relit. Le risque qu'un tel diff attrape — un artefact commité qui
|
||||
# dérive de sa source — n'existe pas quand l'artefact n'est pas commité : il a été
|
||||
# SUPPRIMÉ, pas déplacé. Ce qui reste à garantir est que l'index soit VRAI, et c'est
|
||||
# la vérification 1. La 3 couvre le reste : un générateur non déterministe.
|
||||
#
|
||||
# ── ÉTAT : ÉCRIT, PAS EN SERVICE ────────────────────────────────────────────
|
||||
#
|
||||
# Aucun déclencheur automatique n'est posé. `ci/gitea-workflow.yml.disabled` porte le
|
||||
# workflow prêt à l'emploi et la marche à suivre pour l'activer. La raison est datée :
|
||||
# au 2026-08-29 la forge ne répond pas et plus de trente commits attendent en local.
|
||||
# Un job activé à l'aveugle échouerait à son premier passage — au moment précis où
|
||||
# tout le monde pousse — et le premier réflexe serait de le désactiver. Un garde-fou
|
||||
# désactivé une fois ne se réactive jamais.
|
||||
#
|
||||
# Il PASSE sur l'état du dépôt au 2026-08-29 : index RC=0 (113 règles), doxygen 0
|
||||
# avertissement. Vérifié avant d'être déclaré prêt, parce qu'un job qu'on n'a jamais
|
||||
# vu passer n'est pas un job, c'est une intention.
|
||||
|
||||
set -u
|
||||
|
||||
RACINE="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
cd "$RACINE" || exit 1
|
||||
|
||||
ROUGE=""; VERT=""; GRAS=""; FIN=""
|
||||
if [ -t 1 ]; then ROUGE=$'\e[31m'; VERT=$'\e[32m'; GRAS=$'\e[1m'; FIN=$'\e[0m'; fi
|
||||
|
||||
echec=0
|
||||
titre() { printf '\n%s── %s %s\n' "$GRAS" "$1" "$FIN"; }
|
||||
ko() { printf '%s✗ %s%s\n' "$ROUGE" "$1" "$FIN"; echec=1; }
|
||||
ok() { printf '%s✓ %s%s\n' "$VERT" "$1" "$FIN"; }
|
||||
|
||||
# Toute panne doit dire QUOI LANCER. Un job qui annonce « l'index est périmé » sans
|
||||
# donner la commande se contourne en le désactivant — c'est le chemin de moindre
|
||||
# effort, et il gagne toujours.
|
||||
reparer() { printf ' → réparer : %s\n' "$1"; }
|
||||
|
||||
# --- 1. L'index des règles est-il vrai ? ------------------------------------
|
||||
titre "1/3 · index des règles"
|
||||
if python3 tools/gen-rules.py; then
|
||||
ok "index complet — aucun orphelin, aucun domicile ambigu"
|
||||
else
|
||||
ko "l'index des règles est INCOMPLET (détail ci-dessus)"
|
||||
reparer "définir la règle manquante dans specs/, ou la déclarer dans tools/rules-retired.txt"
|
||||
reparer "puis : python3 tools/gen-rules.py"
|
||||
fi
|
||||
|
||||
# --- 2. La doc est-elle complète ? ------------------------------------------
|
||||
titre "2/3 · documentation Doxygen"
|
||||
if ! command -v doxygen >/dev/null 2>&1 || ! command -v dot >/dev/null 2>&1; then
|
||||
ko "doxygen ou graphviz absent — la vérification n'a PAS eu lieu"
|
||||
reparer "apt install doxygen graphviz"
|
||||
else
|
||||
./tools/gen-doc.sh >/dev/null 2>&1
|
||||
JOURNAL="$RACINE/doc-generated/warnings.txt"
|
||||
# `wc -l` et non `grep -c` : grep -c AFFICHE 0 puis SORT EN 1 quand il ne trouve rien,
|
||||
# si bien qu'un « || echo 0 » empile un second zéro et que le test entier échoue sur un
|
||||
# dépôt SAIN. Une commande de mesure dont l'échec produit une lecture fausse — le motif
|
||||
# de la semaine, appliqué à l'outil (AGENTS.md, « Lire le journal de la box »).
|
||||
N=0
|
||||
[ -f "$JOURNAL" ] && N="$(grep -i "warning" "$JOURNAL" 2>/dev/null | wc -l)"
|
||||
if [ "$N" -eq 0 ]; then
|
||||
ok "0 avertissement"
|
||||
else
|
||||
ko "$N avertissement(s) Doxygen — DoD §5 : toute méthode publique d'etm/ se documente"
|
||||
printf '\n'; sed 's|^.*/energyplugin/| |' "$JOURNAL" | head -20
|
||||
reparer "./tools/gen-doc.sh puis lire doc-generated/warnings.txt"
|
||||
fi
|
||||
fi
|
||||
|
||||
# --- 3. Le générateur est-il déterministe ? ---------------------------------
|
||||
titre "3/3 · reproductibilité de l'index"
|
||||
A="$(mktemp)"; B="$(mktemp)"
|
||||
python3 tools/gen-rules.py >/dev/null 2>&1; cp doc-generated/RULES.md "$A"
|
||||
python3 tools/gen-rules.py >/dev/null 2>&1; cp doc-generated/RULES.md "$B"
|
||||
if diff -q "$A" "$B" >/dev/null; then
|
||||
ok "deux passes, un seul résultat"
|
||||
else
|
||||
ko "l'index n'est PAS reproductible — deux passes ont divergé"
|
||||
printf '\n'; diff "$A" "$B" | head -20
|
||||
reparer "un ordre d'itération dépend d'un QHash ou du système de fichiers : trier"
|
||||
fi
|
||||
rm -f "$A" "$B"
|
||||
|
||||
printf '\n'
|
||||
if [ "$echec" -eq 0 ]; then
|
||||
printf '%s✓ qualité documentaire : tout passe.%s\n' "$VERT" "$FIN"
|
||||
else
|
||||
printf '%s✗ qualité documentaire : au moins une vérification a échoué.%s\n' "$ROUGE" "$FIN"
|
||||
printf ' Tout relancer d'"'"'un coup : ./tools/ci-quality.sh\n'
|
||||
fi
|
||||
exit "$echec"
|
||||
@ -85,7 +85,9 @@ if [ -n "$LOGFILE" ] && [ -f "$RACINE/$LOGFILE" ]; then
|
||||
else
|
||||
JOURNAL_EFFECTIF="$JOURNAL"
|
||||
fi
|
||||
AVERTISSEMENTS="$(grep -c -i "warning" "$JOURNAL_EFFECTIF" 2>/dev/null || echo 0)"
|
||||
# `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)"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user