[DTP-Worker] Sprint 8 · buffer L75 · Fix "vert trompeur" : les 6 gates ci/*.sh passaient exit 0 VERT hors d'un arbre git (cd "$(git rev-parse …)" → cd "" no-op succès → git ls-files vide → 0 fichier contrôlé). Helper partagé ci/lib.sh::cd_repo_root échoue bruyamment (exit 3). INV-B (check_ci_integrity) durci : un ci/*.sh est câblé s'il est lancé par un job OU sourcé par un gate (prouve que lib.sh n'est pas mort).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -19,14 +19,18 @@
|
||||
# (un job manuel = gardé par `if: … workflow_dispatch …`, ex. e2e-baseline,
|
||||
# légitimement hors du gate push/PR car il exige un serveur live).
|
||||
# → aucun job oublié du gate (MISSING) ni référence fantôme (DANGLING).
|
||||
# [INV-B] Chaque script `ci/*.sh` du dépôt est lancé par exactement un job
|
||||
# (`run: bash ci/<script>`), et ce job figure dans `gate.needs`.
|
||||
# → un nouveau gate statique non câblé, ou décâblé, casse le check.
|
||||
# [INV-B] Chaque script `ci/*.sh` du dépôt est CÂBLÉ : soit lancé par un job
|
||||
# (`run: bash ci/<script>`) dont le nom figure dans `gate.needs`, soit
|
||||
# SOURCÉ par ≥1 gate script (lib partagée, ex. ci/lib.sh — jamais un
|
||||
# job propre). → un nouveau gate statique non câblé/décâblé, ou une lib
|
||||
# morte (sourcée par personne), casse le check.
|
||||
#
|
||||
# Dépendances : bash, git, awk, grep, sort. Aucun réseau (CLAUDE.md #2).
|
||||
# ============================================================================
|
||||
set -uo pipefail
|
||||
cd "$(git rev-parse --show-toplevel)"
|
||||
# shellcheck source=ci/lib.sh
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/lib.sh" || exit 3
|
||||
cd_repo_root # racine du dépôt, ou ROUGE honnête si hors arbre git (cf. lib.sh)
|
||||
|
||||
CI=".gitea/workflows/ci.yml"
|
||||
FAIL=0
|
||||
@@ -105,14 +109,31 @@ if [[ -z "$missing$dangling$manual_in_gate" ]]; then
|
||||
fi
|
||||
|
||||
# --- INV-B : tout ci/*.sh est câblé à un job, lui-même dans le gate ----------
|
||||
echo "== INV-B · chaque gate statique ci/*.sh est lancé par un job du gate =="
|
||||
echo "== INV-B · chaque ci/*.sh est câblé (lancé par un job du gate, ou lib sourcée) =="
|
||||
|
||||
# Jobs référençant chaque script (via SCRIPT_REFS).
|
||||
while IFS= read -r script; do
|
||||
[[ -z "$script" ]] && continue
|
||||
jobs_for="$(printf '%s\n' "$SCRIPT_REFS" | awk -v s="$script" '$2==s {print $1}' | sort -u)"
|
||||
if [[ -z "$jobs_for" ]]; then
|
||||
report "$script — présent dans le dépôt mais lancé par AUCUN job CI (gate mort)"
|
||||
# Pas lancé par un job → soit une LIB sourcée (ex. ci/lib.sh), soit un gate
|
||||
# mort. Une lib est légitime SSI ≥1 gate script (lui-même lancé par un job)
|
||||
# la source. On grepe les gate scripts sur disque pour une ligne
|
||||
# `source …/<base>` ou `. …/<base>` (jamais un commentaire : ancrée en début
|
||||
# de ligne, `#` exclu). Sinon → vraiment mort.
|
||||
base="$(basename "$script")"; base_re="${base//./\\.}"
|
||||
sourced_by=""
|
||||
while IFS= read -r gs; do
|
||||
[[ -z "$gs" || "$gs" == "$script" || ! -f "$gs" ]] && continue
|
||||
if grep -Eq "^[[:space:]]*(source|\.)[[:space:]]+[^#]*${base_re}([[:space:]\"'\`]|\$)" "$gs"; then
|
||||
sourced_by="$sourced_by $gs"
|
||||
fi
|
||||
done < <(printf '%s\n' "$SCRIPT_REFS" | awk '{print $2}' | sort -u)
|
||||
if [[ -n "$sourced_by" ]]; then
|
||||
ok "$script — lib sourcée par [$(echo $sourced_by | tr ' ' ',')] · non exécutée en propre (hors gate.needs, OK)"
|
||||
else
|
||||
report "$script — présent dans le dépôt mais lancé/sourcé par AUCUN job CI (gate mort)"
|
||||
fi
|
||||
continue
|
||||
fi
|
||||
# Chaque job qui lance ce script doit alimenter le gate.
|
||||
|
||||
Reference in New Issue
Block a user