#!/usr/bin/env python3 """L'adresse du wiki de la forge QUI PORTE MON GENOME. CHAQUE RUNNER PUBLIE POUR SA FORGE (decide le 2026-09-14). La premiere idee etait qu'un controleur pousse vers plusieurs forges, avec un temoin portant une liste. Elle CENTRALISAIT : un seul poste aurait eu besoin d'un acces sur chaque forge, et le temoin serait devenu un fait global que personne ne detient. Le modele retenu suit la ligne du reste du systeme — les voutes, les runners, les sauvegardes : **chacun sert les siens**. Le runner du site publie sur la forge du site ; celui d'un locataire sur la forge de ce locataire. Un employe de TechnoLibre lit la forge de TechnoLibre, pas celle de son hebergeur. DEUX NOTIONS A NE PAS CONFONDRE, et c'est ce qui a rendu le sujet trouble : la forge AMONT (`serveur_ops_forge_amont`) ou je LIS le genome MA forge (derivee ici) ou je SERS les miens Le runner d'un locataire lit sur la forge du SITE et sert sur la SIENNE. Les deux adresses different, et le wiki appartient a la seconde. LE WIKI SUIT LE GENOME (decide le 2026-09-14). Un locataire ne porte PAS le moteur : il le lit sur la forge de son hebergeur, comme il y prend ses paquets et son gabarit. Lui faire publier la documentation du moteur sur SA forge reviendrait a l'en rendre depositaire — donc a lui imposer l'organisation, les depots, le miroir a tenir synchrone et la preuve qu'il ne derive pas. Pour un service qu'il ne rend a personne. LE SIGNAL EST DEJA AU PLAN : `serveur_ops_forge_externe: true` dit « je lis mon genome ailleurs ». Un ecosysteme qui le declare ne publie pas — il consulte, la ou le genome vit. CE QUI RESTE VRAI D'UNE FORGE DE LOCATAIRE : elle peut exister, et servir LE CODE DE SES GENS — depots, tickets, revues. C'est l'offre « Atelier ». Ce n'est simplement pas l'endroit ou vit le moteur. CE QUI N'EST PAS DERIVABLE, ET C'EST DIT PLUTOT QUE DEVINE : le poste du mainteneur n'est le runner d'aucun ecosysteme. Il publie vers le domicile PUBLIC du projet, qui n'est la forge d'aucun plan. La, `WIKI_REMOTE` reste explicite — et il l'emporte toujours. """ from __future__ import annotations import sys from pathlib import Path RACINE = Path(__file__).resolve().parents[1] sys.path.insert(0, str(RACINE / "scripts")) def ma_forge() -> tuple[str | None, str]: """(url du wiki, explication). `None` quand rien n'est derivable.""" try: from inventory_rules import charger_applications, instance_courante except Exception as e: return None, f"moteur illisible ({e.__class__.__name__})" inst = instance_courante() if not inst: return None, "aucune instance montee" # `charger_applications` VEUT UN CHEMIN, pas rien. L'appeler sans argument levait un # `TypeError` que le `except` transformait en « plan illisible » — un message poli pour # une faute de programmation. Le voila nomme. try: apps = (charger_applications(Path(inst) / "plan" / "applications.yml") or {}).get("applications") or {} except (OSError, ValueError) as e: return None, f"plan illisible ({e.__class__.__name__})" # UN ECOSYSTEME QUI LIT SON GENOME AILLEURS NE LE PUBLIE PAS. Le wiki suit le genome : # il vit la ou le moteur vit, et un locataire n'est pas son depositaire. gv = Path(inst) / "inventories" / "principal" / "group_vars" / "serveur_ops.yml" if gv.is_file(): try: import yaml d = yaml.safe_load(gv.read_text(encoding="utf-8")) or {} except (OSError, yaml.YAMLError): d = {} if d.get("serveur_ops_forge_externe"): amont = d.get("serveur_ops_forge_amont") or "sa forge amont" return None, (f"{Path(inst).resolve().name} lit son genome sur {amont} — " "le wiki s'y consulte, il ne s'y republie pas d'ici") # LE NOM DU SERVICE, PAS CELUI DE LA MACHINE. Un FQDN expose survit au demenagement du # service ; `forge-01` non. C'est la meme regle que partout ailleurs dans ce depot. for nom, app in (apps.items() if isinstance(apps, dict) else []): if str((app or {}).get("groupe")) != "serveur_forgejo": continue exposes = (app or {}).get("expose") or [] if not exposes: return None, "`serveur_forgejo` est au plan mais n'expose aucun nom" fqdn = str(exposes[0]) depot = RACINE.name.lower() return (f"ssh://git@{fqdn}/genome/{depot}.wiki.git", f"forge de l'ecosysteme monte ({Path(inst).resolve().name}), exposee en {fqdn}") return None, f"{Path(inst).resolve().name} ne declare aucun `serveur_forgejo`" if __name__ == "__main__": url, pourquoi = ma_forge() if url: print(url) print(f"note : {pourquoi}", file=sys.stderr) raise SystemExit(0) print(f"note : pas de forge derivable — {pourquoi}", file=sys.stderr) raise SystemExit(1)