fix(0.32.1): URL sœurs dracodev dérivées de l'environnement de l'agent
CI / test (push) Successful in 2m58s

This commit is contained in:
Spark
2026-10-25 23:49:33 +00:00
parent 4a97e0d0dc
commit 65c467bc90
4 changed files with 237 additions and 16 deletions
+93 -15
View File
@@ -107,6 +107,10 @@ Environment variables:
receiving this app's signed events.
Default: derived from AGENT_URL
(``<AGENT_URL>/api/v1/evenements``).
Son hôte sert aussi de source à la
dérivation d'environnement des URL
sœurs ci-dessous (voir
``_url_soeur_draco``).
KANBANTE_PUBLIC_URL This app's own public base URL
(barre commune self-link, SSO
``return_to``). Default (official)
@@ -119,6 +123,20 @@ Environment variables:
https://tiktak.dracodev.net.
ObsiGate's bar link reuses DRACO_SSO_URL
(the SSO emitter IS ObsiGate).
Résolution d'une URL sœur, dans
l'ordre : 1) la variable explicite
ci-dessus (prioritaire, contrat
inchangé) ; 2) dérivation depuis
l'hôte de l'agent connu par
AGENT_EVENEMENTS_URL — si cet hôte
est ``agent<SUFFIXE>.dracodev.net``
(p. ex. ``agent-dev``), l'URL sœur
devient ``https://<slug><SUFFIXE>.
dracodev.net`` (slugs : og, flowdeck,
tiktak, kanbante) ; hôte hors motif
(autre domaine, LAN, IP) = aucune
dérivation, jamais de lien deviné ;
3) le défaut officiel (prod).
No public dracodev name is hard-coded
outside these defaults: dev/prod differ
only by environment, never by code.
@@ -130,12 +148,14 @@ Environment variables:
"""
import os
import re
from dataclasses import dataclass
from pathlib import Path
from urllib.parse import urlparse
BASE_DIR = Path(__file__).resolve().parent.parent
APP_VERSION = "0.32.0"
APP_VERSION = "0.32.1"
def _env_bool(name: str, default: bool) -> bool:
@@ -171,6 +191,48 @@ def _env_wip_limits(name: str) -> dict[str, int]:
return limits
# ── Dérivation d'environnement des URL sœurs dracodev (0.32.1) ──
# Sur la dev, seul AGENT_EVENEMENTS_URL est posé (hôte
# agent-dev.dracodev.net) : les URL sœurs retombaient donc sur leurs
# défauts prod dans la barre commune. La résolution ci-dessous
# évite de devoir déclarer quatre variables de plus.
_MOTIF_HOTE_AGENT = re.compile(r"agent([a-z0-9-]*)\.dracodev\.net")
def _suffixe_environnement_agent(agent_evenements_url: str) -> str | None:
"""Suffixe d'environnement lu sur l'hôte de l'agent.
Retourne le suffixe (``""`` pour le nom officiel, ``"-dev"``
pour la dev) si l'hôte de ``agent_evenements_url`` est de la
forme ``agent<SUFFIXE>.dracodev.net`` ; ``None`` hors motif
(autre domaine, LAN, IP…) — dans ce cas, aucune dérivation.
"""
try:
hote = urlparse(agent_evenements_url).hostname or ""
except ValueError:
return None
motif = _MOTIF_HOTE_AGENT.fullmatch(hote)
return motif.group(1) if motif else None
def _url_soeur_draco(
nom_env: str, slug: str, defaut: str, suffixe: str | None
) -> str:
"""Résout l'URL publique d'une app sœur de la barre commune.
1) ``nom_env`` explicite — prioritaire, contrat inchangé ;
2) dérivation d'environnement : ``https://<slug><suffixe>.
dracodev.net`` quand l'hôte de l'agent suit le motif ;
3) défaut officiel (prod), comme avant.
"""
explicite = os.getenv(nom_env)
if explicite:
return explicite.rstrip("/")
if suffixe is not None:
return f"https://{slug}{suffixe}.dracodev.net"
return defaut
@dataclass(frozen=True)
class Settings:
gitea_url: str = "https://git.dracodev.net"
@@ -234,6 +296,14 @@ def _env_settings() -> Settings:
agent_url = os.getenv(
"AGENT_URL", "https://agent.dracodev.net"
).rstrip("/")
agent_evenements_url = (
os.getenv("AGENT_EVENEMENTS_URL")
or f"{agent_url}/api/v1/evenements"
).rstrip("/")
# Origine de l'agent telle que l'app la connaît déjà : c'est
# elle qui porte le suffixe d'environnement (-dev…) repris
# par les URL sœurs dépourvues de variable explicite.
suffixe_agent = _suffixe_environnement_agent(agent_evenements_url)
return Settings(
gitea_url=os.getenv("GITEA_URL", "https://git.dracodev.net").rstrip("/"),
gitea_token=os.getenv("GITEA_TOKEN", ""),
@@ -276,22 +346,30 @@ def _env_settings() -> Settings:
draco_secret=os.getenv("DRACO_SESSION_SECRET", ""),
draco_secret_prev=os.getenv("DRACO_SESSION_SECRET_PREV", ""),
sso_machine_key=os.getenv("DRACO_SSO_MACHINE_KEY", ""),
sso_url=os.getenv("DRACO_SSO_URL", "https://og.dracodev.net").rstrip("/"),
public_url=os.getenv(
"KANBANTE_PUBLIC_URL", "https://kanbante.dracodev.net"
).rstrip("/"),
flowdeck_url=os.getenv(
"DRACO_FLOWDECK_URL", "https://flowdeck.dracodev.net"
).rstrip("/"),
tiktak_url=os.getenv(
"DRACO_TIKTAK_URL", "https://tiktak.dracodev.net"
).rstrip("/"),
sso_url=_url_soeur_draco(
"DRACO_SSO_URL", "og", "https://og.dracodev.net", suffixe_agent
),
public_url=_url_soeur_draco(
"KANBANTE_PUBLIC_URL",
"kanbante",
"https://kanbante.dracodev.net",
suffixe_agent,
),
flowdeck_url=_url_soeur_draco(
"DRACO_FLOWDECK_URL",
"flowdeck",
"https://flowdeck.dracodev.net",
suffixe_agent,
),
tiktak_url=_url_soeur_draco(
"DRACO_TIKTAK_URL",
"tiktak",
"https://tiktak.dracodev.net",
suffixe_agent,
),
agent_url=agent_url,
archive_suggest_days=_env_int("KANBANTE_ARCHIVE_SUGGEST_DAYS", 180),
agent_evenements_url=(
os.getenv("AGENT_EVENEMENTS_URL")
or f"{agent_url}/api/v1/evenements"
).rstrip("/"),
agent_evenements_url=agent_evenements_url,
agent_evenements_cle=os.getenv("AGENT_EVENEMENTS_CLE", ""),
)