Files
Enclume/enclume/gitea.py
T
hcornet b063d59525
build / Garde-fou (pull_request) Failing after 7s
build / Images Harbor (catalog-sync, Dockerfile.catalog-sync) (pull_request) Skipped
build / Images Harbor (web, Dockerfile) (pull_request) Skipped
build / Garde-fou (push) Failing after 8s
build / Images Harbor (catalog-sync, Dockerfile.catalog-sync) (push) Skipped
build / Images Harbor (web, Dockerfile) (push) Skipped
Partage par lien, comptes Authentik, soumission et moderation de packs, prerequis des sondes ; corrige le lien casse vers le script de l'editeur
2026-09-10 16:28:26 +02:00

100 lines
3.5 KiB
Python

"""Publication d'un pack accepte, sous forme de pull request Gitea.
Choix volontaire : la moderation n'ecrit jamais directement sur la branche
principale. Elle ouvre une demande, que tu relis dans Gitea avant de fusionner.
Git reste la source de verite du catalogue, et une acceptation par erreur dans
l'interface reste rattrapable en un clic.
"""
from __future__ import annotations
import base64
import json
import re
import urllib.error
import urllib.request
from .config import Config
TIMEOUT = 15
class ErreurGitea(RuntimeError):
pass
def _appel(methode: str, chemin: str, corps: dict | None = None) -> dict:
url = f"{Config.GITEA_URL}/api/v1{chemin}"
donnees = json.dumps(corps).encode("utf-8") if corps is not None else None
requete = urllib.request.Request(url, data=donnees, method=methode)
requete.add_header("Authorization", f"token {Config.GITEA_TOKEN}")
requete.add_header("Content-Type", "application/json")
requete.add_header("Accept", "application/json")
try:
with urllib.request.urlopen(requete, timeout=TIMEOUT) as reponse:
charge = reponse.read().decode("utf-8")
return json.loads(charge) if charge else {}
except urllib.error.HTTPError as erreur:
detail = erreur.read().decode("utf-8", "replace")[:500]
raise ErreurGitea(f"{methode} {chemin} : HTTP {erreur.code} — {detail}") from erreur
except urllib.error.URLError as erreur:
raise ErreurGitea(f"{methode} {chemin} : {erreur.reason}") from erreur
def _nom_de_branche(pack_id: str, soumission_id: int) -> str:
base = re.sub(r"[^a-z0-9-]+", "-", pack_id.lower()).strip("-") or "pack"
return f"pack/{base}-{soumission_id}"
def ouvrir_demande(soumission, auteur: str) -> str:
"""Cree la branche, y depose le pack, ouvre la pull request. Rend son URL."""
if not Config.gitea_actif():
raise ErreurGitea("publication Gitea non configuree")
proprietaire = Config.GITEA_PROPRIETAIRE
depot = Config.GITEA_DEPOT
branche = _nom_de_branche(soumission.pack_id, soumission.id)
chemin = f"{Config.GITEA_SOUS_DOSSIER}/{soumission.categorie}/{soumission.pack_id}.yml"
# Un seul appel cree la branche et le fichier : new_branch part de branch.
_appel(
"POST",
f"/repos/{proprietaire}/{depot}/contents/{chemin}",
{
"content": base64.b64encode(soumission.contenu.encode("utf-8")).decode("ascii"),
"message": f"Ajout du pack {soumission.pack_id} ({soumission.categorie})",
"branch": Config.GITEA_BRANCHE,
"new_branch": branche,
},
)
corps = [
f"Pack **{soumission.nom or soumission.pack_id}** propose depuis Enclume.",
"",
f"- identifiant : `{soumission.pack_id}`",
f"- categorie : `{soumission.categorie}`",
f"- auteur : {auteur}",
f"- soumission : #{soumission.id}",
]
if soumission.message:
corps += ["", "Message de l'auteur :", "", f"> {soumission.message.strip()}"]
corps += [
"",
"---",
"Contribution externe : relire la ligne de commande, les macros et les "
"eventuels prerequis avant de fusionner.",
]
demande = _appel(
"POST",
f"/repos/{proprietaire}/{depot}/pulls",
{
"head": branche,
"base": Config.GITEA_BRANCHE,
"title": f"Pack {soumission.pack_id}",
"body": "\n".join(corps),
},
)
return str(demande.get("html_url") or "")