#!/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//repos` ET PAS `/api/v1/repos/search?owner=`. 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 porte que ${nombre} depot(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