Set-OPS-Public/roles/serveur_forge_site/templates/sonde-genome-servi.sh.j2
Daniel Allaire d7717a4f98 serveur_ops : les depots prives se lisent en SSH, ou arrivent en colis
Mesure sur le terrain : chaque runner lit son depot en SSH avec sa cle de deploiement,
et la forge lui refuse les autres, alors meme que les depots sont publics. Le role ne
clone plus en HTTPS que les depots publics ; les depots instance, tenant et hebergeur
passent en SSH, cle d'hote epinglee, commande SSH posee dans leur config git. Avant
l'armement, le controleur les apporte en git bundle. La cle d'hote de la forge est
declaree au plan du site et offerte par la fiche. genome_etat et genome_pousser lisent
l'API authentifies ; la sonde genome-servi compte les publics ; forge_amorcer cree
prives les depots des ecosystemes et du site. make forge-etancheite mesure le tout.

Les depots restent publics.

95 preuves.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 20:33:38 -04:00

91 lines
3.8 KiB
Django/Jinja

#!/bin/bash
# GENERE par Set-OPS (role serveur_forge_site). Ne pas editer a la main.
#
# SONDE « genome-servi » — cette forge a-t-elle encore un genome a servir ?
#
# PAS UNE ENVELOPPE DE GREFFON. `check_http` dirait « 443 repond » — c'est deja ce que
# fait la sonde `forge` de `serveur_forgejo`. Ce qu'on mesure ici n'a pas d'equivalent
# standard : le CONTENU que cette forge est censee porter pour tous les locataires du site.
#
# SANS AUCUN JUSTIFICATIF. Cette route repond en anonyme (mesure du 2026-09-14) : la
# sonde n'a besoin d'aucun jeton, donc aucun secret ne dort sur disque pour elle. Elle ne
# voit que ce que voit un visiteur — ce qui suffit exactement.
#
# `/api/v1/orgs/<org>/repos` ET PAS `/api/v1/repos/search?owner=<org>`. La premiere
# ecriture de cette sonde utilisait la recherche, et l'epreuve du 2026-09-14 l'a mise en
# defaut : avec `owner=organisation-qui-nexiste-pas`, elle rendait quand meme les six
# depots de la forge et sortait VERTE. Le parametre etait simplement ignore. La sonde
# n'aurait donc jamais mesure le genome — seulement « cette forge a des depots ».
# La route par organisation, elle, rend 404 pour une organisation absente.
set -uo pipefail
ORG='{{ serveur_forge_site_organisation }}'
PORT={{ serveur_forge_site_port }}
MINIMUM={{ serveur_forge_site_sonde_depots_minimum }}
reponse=$(curl -sk --max-time 15 -w '\n%{http_code}' \
"https://127.0.0.1:${PORT}/api/v1/orgs/${ORG}/repos?limit=100" 2>/dev/null)
code=${reponse##*$'\n'}
corps=${reponse%$'\n'*}
case "${code}" in
200) : ;;
404)
echo "L'organisation « ${ORG} » n'existe pas sur cette forge : le genome du site n'a plus de proprietaire."
exit 2
;;
# « 000 » EST LE CODE DE CURL QUAND IL N'Y A PAS EU DE REPONSE DU TOUT — connexion
# refusee, delai depasse, TLS rompu. Ce n'est pas un code HTTP, et le confondre avec
# une erreur du serveur ferait dire « la forge rend 000 » la ou il faut dire « la forge
# ne repond pas ». La branche vide, elle, ne peut pas se produire : `-w` ecrit toujours
# un code.
000)
echo "L'API de la forge ne repond pas sur ${PORT} — le genome est injoignable pour tous les locataires du site."
exit 2
;;
*)
echo "L'API de la forge rend HTTP ${code} pour « ${ORG} » — le genome n'est pas servi."
exit 2
;;
esac
# `empty` EST UN CHAMP DE L'API, pas une deduction. Forgejo sait qu'un depot n'a aucun
# commit et le dit. On ne devine rien, on lit.
lecture=$(printf '%s' "${corps}" | python3 -c '
import json, sys
try:
depots = json.load(sys.stdin)
except Exception:
print("ILLISIBLE"); raise SystemExit(0)
if not isinstance(depots, list):
print("ILLISIBLE"); raise SystemExit(0)
vides = sorted(r["full_name"] for r in depots if r.get("empty"))
# LE « | » N EST PAS DECORATIF : sans separateur toujours present, une liste
# vide ferait rendre a `${lecture#*|}` le NOMBRE lui-meme, et la sonde
# annoncerait « 6 » comme nom de depot vide.
print(len(depots), "|" + ",".join(vides))
' 2>/dev/null)
if [[ "${lecture}" == "ILLISIBLE" || -z "${lecture}" ]]; then
echo "L'API de la forge repond, mais sa reponse est illisible — la forge sert-elle encore Forgejo ?"
exit 2
fi
nombre=${lecture%% *}
vides=${lecture#*|}
if (( nombre < MINIMUM )); then
echo "La forge du genome ne sert que ${nombre} depot(s) public(s) pour « ${ORG} » (minimum ${MINIMUM}) : un ecosysteme neuf n'a rien a cloner."
exit 2
fi
# UN DEPOT VIDE NE FAIT PAS ECHOUER UN CLONE — il rend un arbre sans fichiers, et le
# deploiement qui suit se fait sur un moteur absent. C'est la panne la plus couteuse ici,
# parce qu'elle ne ressemble a rien.
if [[ -n "${vides}" ]]; then
echo "Depot(s) VIDE(s) dans le genome du site : ${vides}. Un clone y rendrait un arbre sans fichiers, sans echouer."
exit 2
fi
echo "Genome du site : ${nombre} depots servis sous « ${ORG} », aucun vide."
exit 0