Deliver BAT-003: daemon .env loading (REQ-010, minor-change)

DaemonConfig.from_env() now best-effort loads a .env file (find_dotenv
usecwd, load_dotenv override=False) so operators can manage daemon env
vars via .env, with real OS env taking precedence. Add python-dotenv
dependency, gitignore .env, ship .env.example, and add config tests
(load / OS-env precedence / absence regression / missing-DSN guard).

Verification: 78 passed, ruff clean, .env ignored + .env.example tracked,
and a .env-only DaemonConfig smoke. Processed via the minor-change fast
path: REQ-010 (Configuration) -> Implemented, BAT-003 (batch-lite,
no design) -> release-candidate.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-04 14:56:42 +09:00
co-authored by Claude Opus 4.8
parent a4e263c8e7
commit 575ba9f513
13 changed files with 346 additions and 5 deletions
View File
+50
View File
@@ -0,0 +1,50 @@
"""DaemonConfig .env loading tests (REQ-010)."""
from __future__ import annotations
import pytest
from trex_core.runtime.config import DaemonConfig
_KEYS = ("TREX_POSTGRESQL_DSN", "TREX_TOTAL_SLOTS", "TREX_API_HOST", "TREX_API_PORT")
@pytest.fixture(autouse=True)
def _clean_env(monkeypatch):
for k in _KEYS:
monkeypatch.delenv(k, raising=False)
def test_loads_values_from_dotenv(tmp_path, monkeypatch):
"""AC-1: .env in CWD is loaded when the OS env var is unset."""
(tmp_path / ".env").write_text(
"TREX_POSTGRESQL_DSN=dbname=from_dotenv\nTREX_TOTAL_SLOTS=7\n"
)
monkeypatch.chdir(tmp_path)
cfg = DaemonConfig.from_env()
assert cfg.dsn == "dbname=from_dotenv"
assert cfg.total_slots == 7
def test_os_env_takes_precedence_over_dotenv(tmp_path, monkeypatch):
"""AC-2: real OS env wins over .env (override=False)."""
(tmp_path / ".env").write_text("TREX_POSTGRESQL_DSN=dbname=from_dotenv\n")
monkeypatch.chdir(tmp_path)
monkeypatch.setenv("TREX_POSTGRESQL_DSN", "dbname=from_os_env")
cfg = DaemonConfig.from_env()
assert cfg.dsn == "dbname=from_os_env"
def test_no_dotenv_uses_os_env_only(tmp_path, monkeypatch):
"""AC-3: with no .env, behaviour is unchanged (os.environ only)."""
monkeypatch.chdir(tmp_path) # empty dir, no .env
monkeypatch.setenv("TREX_POSTGRESQL_DSN", "dbname=os_only")
cfg = DaemonConfig.from_env()
assert cfg.dsn == "dbname=os_only"
assert cfg.total_slots == 10 # default
def test_missing_dsn_raises(tmp_path, monkeypatch):
"""No .env and no env var -> required DSN error (regression guard)."""
monkeypatch.chdir(tmp_path)
with pytest.raises(RuntimeError):
DaemonConfig.from_env()