From a9e01158247329876b530dd4d4caaee70bb4bd6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=A8=B8=EB=8B=88=ED=8E=98=EB=8B=88?= Date: Fri, 20 Mar 2026 14:55:02 +0900 Subject: [PATCH] feat: add config module with pydantic-settings --- .env.example | 35 ++++++++++++++++++++++++ agent/config.py | 65 ++++++++++++++++++++++++++++++++++++++++++++ tests/test_config.py | 39 ++++++++++++++++++++++++++ 3 files changed, 139 insertions(+) create mode 100644 .env.example create mode 100644 agent/config.py create mode 100644 tests/test_config.py diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..6de45d7 --- /dev/null +++ b/.env.example @@ -0,0 +1,35 @@ +# .env.example +# LLM +ANTHROPIC_API_KEY=sk-ant-... + +# Gitea +GITEA_URL=http://gitea:3000 +GITEA_EXTERNAL_URL=https://ayuriel.duckdns.org +GITEA_TOKEN= +GITEA_WEBHOOK_SECRET= + +# Discord +DISCORD_TOKEN= +DISCORD_CHANNEL_ID= +DISCORD_BOT_USER_ID= + +# LangGraph +LANGGRAPH_URL=http://langgraph-server:8123 + +# Agent +AUTONOMY_LEVEL=conservative +DEFAULT_REPO_OWNER=quant +DEFAULT_REPO_NAME=galaxis-po +AGENT_API_KEY= + +# Sandbox +SANDBOX_IMAGE=galaxis-sandbox:latest +SANDBOX_MEM_LIMIT=4g +SANDBOX_CPU_COUNT=2 +SANDBOX_TIMEOUT=600 + +# Database +TEST_DATABASE_URL=postgresql://user:pass@postgres:5432/galaxis_test + +# Encryption +FERNET_KEY= diff --git a/agent/config.py b/agent/config.py new file mode 100644 index 0000000..8be8dcb --- /dev/null +++ b/agent/config.py @@ -0,0 +1,65 @@ +from pydantic_settings import BaseSettings + + +class Settings(BaseSettings): + # LLM + ANTHROPIC_API_KEY: str + + # Gitea + GITEA_URL: str = "http://gitea:3000" + GITEA_EXTERNAL_URL: str = "https://ayuriel.duckdns.org" + GITEA_TOKEN: str + GITEA_WEBHOOK_SECRET: str + + # Discord + DISCORD_TOKEN: str + DISCORD_CHANNEL_ID: str = "" + DISCORD_BOT_USER_ID: str = "" + + # LangGraph + LANGGRAPH_URL: str = "http://langgraph-server:8123" + + # Agent + AUTONOMY_LEVEL: str = "conservative" + DEFAULT_REPO_OWNER: str = "quant" + DEFAULT_REPO_NAME: str = "galaxis-po" + AGENT_API_KEY: str = "" + + # Sandbox + SANDBOX_IMAGE: str = "galaxis-sandbox:latest" + SANDBOX_MEM_LIMIT: str = "4g" + SANDBOX_CPU_COUNT: int = 2 + SANDBOX_TIMEOUT: int = 600 + SANDBOX_PIDS_LIMIT: int = 256 + + # Database + TEST_DATABASE_URL: str = "" + + # Encryption + FERNET_KEY: str = "" + + # Path access control + WRITABLE_PATHS: list[str] = [ + "backend/app/", + "backend/tests/", + "frontend/src/", + "backend/alembic/versions/", + "docs/", + ] + BLOCKED_PATHS: list[str] = [ + ".env", + "docker-compose.prod.yml", + "quant.md", + ] + + # Auto merge + AUTO_MERGE: bool = False + REQUIRE_TESTS: bool = True + REQUIRE_E2E: bool = False + MAX_FILES_CHANGED: int = 10 + + # Cost limits + DAILY_COST_LIMIT_USD: float = 10.0 + PER_TASK_COST_LIMIT_USD: float = 3.0 + + model_config = {"env_file": ".env", "extra": "ignore"} diff --git a/tests/test_config.py b/tests/test_config.py new file mode 100644 index 0000000..83127ef --- /dev/null +++ b/tests/test_config.py @@ -0,0 +1,39 @@ +import pytest +from agent.config import Settings + + +@pytest.fixture +def test_settings(monkeypatch): + """테스트용 환경변수로 Settings 인스턴스 생성""" + monkeypatch.setenv("ANTHROPIC_API_KEY", "test-key") + monkeypatch.setenv("GITEA_TOKEN", "test-token") + monkeypatch.setenv("GITEA_WEBHOOK_SECRET", "test-secret") + monkeypatch.setenv("DISCORD_TOKEN", "test-token") + monkeypatch.setenv("FERNET_KEY", "dGVzdGtleXRlc3RrZXl0ZXN0a2V5dGVzdGtleXg=") + return Settings() + + +def test_config_loads_defaults(test_settings): + assert test_settings.GITEA_URL == "http://gitea:3000" + assert test_settings.AUTONOMY_LEVEL == "conservative" + assert test_settings.SANDBOX_TIMEOUT == 600 + assert test_settings.DEFAULT_REPO_OWNER == "quant" + assert test_settings.DEFAULT_REPO_NAME == "galaxis-po" + assert test_settings.SANDBOX_MEM_LIMIT == "4g" + assert test_settings.SANDBOX_CPU_COUNT == 2 + + +def test_config_autonomy_levels(test_settings): + assert test_settings.AUTONOMY_LEVEL in ("conservative", "autonomous") + + +def test_writable_paths_include_backend(test_settings): + assert "backend/app/" in test_settings.WRITABLE_PATHS + assert "backend/tests/" in test_settings.WRITABLE_PATHS + assert "backend/alembic/versions/" in test_settings.WRITABLE_PATHS + + +def test_blocked_paths_include_protected_files(test_settings): + assert ".env" in test_settings.BLOCKED_PATHS + assert "quant.md" in test_settings.BLOCKED_PATHS + assert "docker-compose.prod.yml" in test_settings.BLOCKED_PATHS