Files
kanbante/app/config.py
T
Spark d267df01fa fix(backend): consolidation 0.2.0 — config, DB_PATH, async, pagination, auth, synchro bidirectionnelle
- config.py: réglages centralisés par variables d'environnement
- models: KANBANTE_DB_PATH enfin honorée (C1), migrations idempotentes
  (position, notes.updated_at, nettoyage colonnes inconnues — I4),
  ordre des cartes persisté (M5), réconciliation avec Gitea
- gitea_client: httpx asynchrone, pagination complète (I2, plafond
  serveur de 50), uid résolu via /user, en-tête Authorization seulement
  si jeton, cache court, create_issue / set_issue_state, .env racine
- main: lifespan au lieu de on_event (M4), Basic Auth optionnelle +
  CSRF double-submit (C2), write-back done<->fermé (C3), classification
  par fenêtre glissante + drapeau archived (I1), erreurs Gitea en 502
  propre (I5), /api/readiness réel, PR exclues du board (M6),
  codes HTTP explicites et limite de taille des notes (M7)
2026-10-11 09:31:48 -04:00

88 lines
3.0 KiB
Python

"""
Centralised settings for Kanbante.
Every setting is read from the environment at call time (no import-time
freezing), so tests and operators can change them without code edits.
Environment variables:
GITEA_URL Base URL of the Gitea instance.
GITEA_TOKEN Gitea API token (read/write issues).
KANBANTE_DB_PATH Path of the local SQLite database.
KANBANTE_AUTH_USER Basic-auth username (with _PASSWORD: enables auth).
KANBANTE_AUTH_PASSWORD Basic-auth password.
KANBANTE_REQUIRE_AUTH "1" = refuse to serve if auth is not configured.
KANBANTE_ACTIVE_WINDOW_DAYS A non-archived repo updated within this many
days counts as "active" (default 365).
KANBANTE_CACHE_TTL Seconds to cache Gitea list responses (default 30).
KANBANTE_MAX_NOTE_CHARS Maximum size of a project note (default 20000).
KANBANTE_SYNC_GITEA "1" (default) = moving a card to/from "done"
closes / reopens the Gitea issue.
"""
import os
from dataclasses import dataclass
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
APP_VERSION = "0.2.0"
def _env_bool(name: str, default: bool) -> bool:
raw = os.getenv(name)
if raw is None:
return default
return raw.strip().lower() in ("1", "true", "yes", "on")
def _env_int(name: str, default: int) -> int:
raw = os.getenv(name)
try:
return int(raw) if raw is not None else default
except ValueError:
return default
def _env_float(name: str, default: float) -> float:
raw = os.getenv(name)
try:
return float(raw) if raw is not None else default
except ValueError:
return default
@dataclass(frozen=True)
class Settings:
gitea_url: str = "https://git.dracodev.net"
gitea_token: str = ""
db_path: str = "~/.kanbante/kanbante.db"
auth_user: str = ""
auth_password: str = ""
require_auth: bool = False
active_window_days: int = 365
cache_ttl: float = 30.0
max_note_chars: int = 20_000
sync_gitea: bool = True
@property
def auth_enabled(self) -> bool:
return bool(self.auth_user and self.auth_password)
def get_settings() -> Settings:
"""Build settings from the current environment."""
return Settings(
gitea_url=os.getenv("GITEA_URL", "https://git.dracodev.net").rstrip("/"),
gitea_token=os.getenv("GITEA_TOKEN", ""),
db_path=os.getenv(
"KANBANTE_DB_PATH", os.path.expanduser("~/.kanbante/kanbante.db")
),
auth_user=os.getenv("KANBANTE_AUTH_USER", ""),
auth_password=os.getenv("KANBANTE_AUTH_PASSWORD", ""),
require_auth=_env_bool("KANBANTE_REQUIRE_AUTH", False),
active_window_days=_env_int("KANBANTE_ACTIVE_WINDOW_DAYS", 365),
cache_ttl=_env_float("KANBANTE_CACHE_TTL", 30.0),
max_note_chars=_env_int("KANBANTE_MAX_NOTE_CHARS", 20_000),
sync_gitea=_env_bool("KANBANTE_SYNC_GITEA", True),
)