0bc734c020
Applies `ruff format` to the accumulated formatting debt on this branch. Formatting-only — no behavioral changes. Required for CI/lint's format gate (`nox -s format -- --check`), which the branch was failing on 288 tracked files that drifted from ruff's canonical style. In-progress WIP files are intentionally excluded so this commit stays a clean formatting-only diff. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
94 lines
3.2 KiB
Python
94 lines
3.2 KiB
Python
"""Controller-owned ForgejoConfig dataclass.
|
|
|
|
Phase 1k+ refinement (item 16): previously ``__main__.py`` reached up
|
|
into ``tools/_mcp_common.ForgejoCfg`` via sys.path injection and
|
|
mutated ``cfg.owner`` / ``cfg.repo`` after construction. That:
|
|
|
|
- inverts the dependency direction (the controller is supposed to be
|
|
the new system; it shouldn't reach into sibling pipeline modules);
|
|
- mutates a frozen-ish config object after construction;
|
|
- ties controller deployments to whatever the legacy ForgejoCfg
|
|
schema happens to be.
|
|
|
|
This module ships a ``ControllerForgejoConfig`` dataclass owning
|
|
exactly the fields ``tools/_claim_runtime`` reads from a cfg:
|
|
``token``, ``request_timeout_s``, ``api_retries``,
|
|
``claim_ttl_seconds``. Plus the controller's own ``owner`` / ``repo``.
|
|
|
|
URL handling lives in ``_claim_runtime`` itself (reads
|
|
``FORGEJO_API_BASE`` env at request time), so it stays out of this
|
|
config.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
from dataclasses import dataclass
|
|
|
|
|
|
@dataclass
|
|
class ControllerForgejoConfig:
|
|
"""Configuration the controller passes to the ``_claim_runtime``
|
|
HTTP helpers (which read .token / .request_timeout_s / .api_retries
|
|
/ .claim_ttl_seconds) and to the Forgejo callback factory (which
|
|
reads .owner / .repo)."""
|
|
|
|
owner: str
|
|
repo: str
|
|
token: str
|
|
request_timeout_s: int = 30
|
|
api_retries: int = 3
|
|
claim_ttl_seconds: int = 600
|
|
|
|
|
|
def _env_int(name: str, default: int) -> int:
|
|
"""Read an int from env; empty/whitespace value falls back to
|
|
``default`` (so an operator who unsets-via-blank doesn't crash
|
|
master startup with a non-actionable ``int('')`` ValueError).
|
|
A non-numeric value still raises — that's an operator
|
|
misconfiguration worth surfacing loudly."""
|
|
raw = os.environ.get(name, "")
|
|
if not raw.strip():
|
|
return default
|
|
try:
|
|
return int(raw)
|
|
except ValueError as exc:
|
|
raise ValueError(
|
|
f"env {name}={raw!r} is not a valid integer; expected an int"
|
|
) from exc
|
|
|
|
|
|
def from_environment(owner: str, repo: str) -> ControllerForgejoConfig:
|
|
"""Build a ControllerForgejoConfig from env vars + the
|
|
deployment-specified owner/repo. Mirrors the env-driven
|
|
construction the legacy ForgejoCfg used (FORGEJO_TOKEN +
|
|
standard CONTROLLER_FORGEJO_* tunables) so operators don't have
|
|
to relearn anything.
|
|
|
|
Empty/whitespace env values for the tunables fall back to the
|
|
documented defaults rather than crashing startup with
|
|
``int('')`` ValueError — operators who clear a var
|
|
(e.g., ``unset CONTROLLER_FORGEJO_REQUEST_TIMEOUT_S`` after
|
|
sourcing /etc/cleveragents/master.env) get the default behaviour
|
|
silently.
|
|
"""
|
|
token = (
|
|
os.environ.get("FORGEJO_TOKEN")
|
|
or os.environ.get("CONTROLLER_FORGEJO_TOKEN")
|
|
or ""
|
|
)
|
|
return ControllerForgejoConfig(
|
|
owner=owner,
|
|
repo=repo,
|
|
token=token,
|
|
request_timeout_s=_env_int(
|
|
"CONTROLLER_FORGEJO_REQUEST_TIMEOUT_S",
|
|
30,
|
|
),
|
|
api_retries=_env_int("CONTROLLER_FORGEJO_API_RETRIES", 3),
|
|
claim_ttl_seconds=_env_int("CONTROLLER_FORGEJO_CLAIM_TTL_S", 600),
|
|
)
|
|
|
|
|
|
__all__ = ["ControllerForgejoConfig", "from_environment"]
|