314dc03b0d
Moves the orchestrator into bot_bottle/orchestrator/ so one install gets everything. Entry point is now `python -m bot_bottle.orchestrator run`. - Add bot_bottle/orchestrator/ with all 14 modules (verbatim move; internal imports were already relative, so no changes inside orchestrator modules) - Rewrite bootstrap.py: remove the lazy bot_bottle import guard, use direct relative imports from ..contrib.* - Add bot_bottle/contrib/forge/base.py: ScopedForge (read-anywhere / write-scoped) - Add bot_bottle/contrib/gitea/client.py: GiteaClient + GiteaForge (urllib.request only) - Add bot_bottle/contrib/gitea/forge_state.py: ForgeState + SqliteForgeStateStore - Add tests/unit/orchestrator/ (82 tests: 63 migrated + 19 new for contrib modules) Closes #321
53 lines
1.8 KiB
Python
53 lines
1.8 KiB
Python
"""Configuration, loaded from the environment (stdlib `os` only).
|
|
|
|
Everything the orchestrator needs to run is an env var so a deploy is a
|
|
process with an environment, no config file to manage. `FORGE_*` names
|
|
match the bot-bottle forge-native PRD.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
from dataclasses import dataclass
|
|
from pathlib import Path
|
|
|
|
# The label that marks an issue as agent-targeted: `bot-bottle:<agent>`.
|
|
LABEL_PREFIX = "bot-bottle:"
|
|
# Optional bottle override: `bot-bottle-bottle:<name>`.
|
|
BOTTLE_LABEL_PREFIX = "bot-bottle-bottle:"
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class Config:
|
|
"""Resolved orchestrator configuration."""
|
|
|
|
forge_org: str
|
|
gitea_api: str
|
|
watchdog_timeout_secs: int
|
|
webhook_host: str
|
|
webhook_port: int
|
|
bot_bottle_cli: str
|
|
queue_dir: Path
|
|
sidecar_socket: Path
|
|
db_path: Path | None
|
|
|
|
@staticmethod
|
|
def from_env(env: dict[str, str] | None = None) -> "Config":
|
|
e = os.environ if env is None else env
|
|
home = Path(e.get("HOME", str(Path.home())))
|
|
default_root = home / ".bot-bottle"
|
|
db = e.get("FORGE_DB_PATH")
|
|
return Config(
|
|
forge_org=e.get("FORGE_ORG", "bot-bottle"),
|
|
gitea_api=e.get("FORGE_GITEA_API", ""),
|
|
watchdog_timeout_secs=int(e.get("FORGE_WATCHDOG_TIMEOUT", "1800")),
|
|
webhook_host=e.get("FORGE_WEBHOOK_HOST", "127.0.0.1"),
|
|
webhook_port=int(e.get("FORGE_WEBHOOK_PORT", "8477")),
|
|
bot_bottle_cli=e.get("BOT_BOTTLE_CLI", "cli.py"),
|
|
queue_dir=Path(e.get("FORGE_QUEUE_DIR", str(default_root / "forge-queue"))),
|
|
sidecar_socket=Path(
|
|
e.get("FORGE_SIDECAR_SOCKET", str(default_root / "forge-sidecar.sock"))
|
|
),
|
|
db_path=Path(db) if db else None,
|
|
)
|