mirror of
https://github.com/Xe138/AI-Trader.git
synced 2026-04-01 17:17:24 -04:00
feat: add deployment mode configuration utilities
This commit is contained in:
96
tests/unit/test_deployment_config.py
Normal file
96
tests/unit/test_deployment_config.py
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
import os
|
||||||
|
import pytest
|
||||||
|
from tools.deployment_config import (
|
||||||
|
get_deployment_mode,
|
||||||
|
is_dev_mode,
|
||||||
|
is_prod_mode,
|
||||||
|
get_data_path,
|
||||||
|
get_db_path,
|
||||||
|
should_preserve_dev_data,
|
||||||
|
log_api_key_warning,
|
||||||
|
get_deployment_mode_dict
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_deployment_mode_default():
|
||||||
|
"""Test default deployment mode is PROD"""
|
||||||
|
# Clear env to test default
|
||||||
|
os.environ.pop("DEPLOYMENT_MODE", None)
|
||||||
|
assert get_deployment_mode() == "PROD"
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_deployment_mode_dev():
|
||||||
|
"""Test DEV mode detection"""
|
||||||
|
os.environ["DEPLOYMENT_MODE"] = "DEV"
|
||||||
|
assert get_deployment_mode() == "DEV"
|
||||||
|
assert is_dev_mode() == True
|
||||||
|
assert is_prod_mode() == False
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_deployment_mode_prod():
|
||||||
|
"""Test PROD mode detection"""
|
||||||
|
os.environ["DEPLOYMENT_MODE"] = "PROD"
|
||||||
|
assert get_deployment_mode() == "PROD"
|
||||||
|
assert is_dev_mode() == False
|
||||||
|
assert is_prod_mode() == True
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_data_path_prod():
|
||||||
|
"""Test production data path"""
|
||||||
|
os.environ["DEPLOYMENT_MODE"] = "PROD"
|
||||||
|
assert get_data_path("./data/agent_data") == "./data/agent_data"
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_data_path_dev():
|
||||||
|
"""Test dev data path substitution"""
|
||||||
|
os.environ["DEPLOYMENT_MODE"] = "DEV"
|
||||||
|
assert get_data_path("./data/agent_data") == "./data/dev_agent_data"
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_db_path_prod():
|
||||||
|
"""Test production database path"""
|
||||||
|
os.environ["DEPLOYMENT_MODE"] = "PROD"
|
||||||
|
assert get_db_path("data/trading.db") == "data/trading.db"
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_db_path_dev():
|
||||||
|
"""Test dev database path substitution"""
|
||||||
|
os.environ["DEPLOYMENT_MODE"] = "DEV"
|
||||||
|
assert get_db_path("data/trading.db") == "data/trading_dev.db"
|
||||||
|
assert get_db_path("data/jobs.db") == "data/jobs_dev.db"
|
||||||
|
|
||||||
|
|
||||||
|
def test_should_preserve_dev_data_default():
|
||||||
|
"""Test default preserve flag is False"""
|
||||||
|
os.environ.pop("PRESERVE_DEV_DATA", None)
|
||||||
|
assert should_preserve_dev_data() == False
|
||||||
|
|
||||||
|
|
||||||
|
def test_should_preserve_dev_data_true():
|
||||||
|
"""Test preserve flag can be enabled"""
|
||||||
|
os.environ["PRESERVE_DEV_DATA"] = "true"
|
||||||
|
assert should_preserve_dev_data() == True
|
||||||
|
|
||||||
|
|
||||||
|
def test_log_api_key_warning_in_dev(capsys):
|
||||||
|
"""Test warning logged when API keys present in DEV mode"""
|
||||||
|
os.environ["DEPLOYMENT_MODE"] = "DEV"
|
||||||
|
os.environ["OPENAI_API_KEY"] = "sk-test123"
|
||||||
|
|
||||||
|
log_api_key_warning()
|
||||||
|
|
||||||
|
captured = capsys.readouterr()
|
||||||
|
assert "⚠️ WARNING: Production API keys detected in DEV mode" in captured.out
|
||||||
|
assert "OPENAI_API_KEY" in captured.out
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_deployment_mode_dict():
|
||||||
|
"""Test deployment mode dictionary generation"""
|
||||||
|
os.environ["DEPLOYMENT_MODE"] = "DEV"
|
||||||
|
os.environ["PRESERVE_DEV_DATA"] = "true"
|
||||||
|
|
||||||
|
result = get_deployment_mode_dict()
|
||||||
|
|
||||||
|
assert result["deployment_mode"] == "DEV"
|
||||||
|
assert result["is_dev_mode"] == True
|
||||||
|
assert result["preserve_dev_data"] == True
|
||||||
133
tools/deployment_config.py
Normal file
133
tools/deployment_config.py
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
"""
|
||||||
|
Deployment mode configuration utilities
|
||||||
|
|
||||||
|
Handles PROD vs DEV mode differentiation including:
|
||||||
|
- Data path isolation
|
||||||
|
- Database path isolation
|
||||||
|
- API key validation warnings
|
||||||
|
- Deployment mode detection
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
|
||||||
|
def get_deployment_mode() -> str:
|
||||||
|
"""
|
||||||
|
Get current deployment mode
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
"PROD" or "DEV" (defaults to PROD if not set)
|
||||||
|
"""
|
||||||
|
mode = os.getenv("DEPLOYMENT_MODE", "PROD").upper()
|
||||||
|
if mode not in ["PROD", "DEV"]:
|
||||||
|
print(f"⚠️ Invalid DEPLOYMENT_MODE '{mode}', defaulting to PROD")
|
||||||
|
return "PROD"
|
||||||
|
return mode
|
||||||
|
|
||||||
|
|
||||||
|
def is_dev_mode() -> bool:
|
||||||
|
"""Check if running in DEV mode"""
|
||||||
|
return get_deployment_mode() == "DEV"
|
||||||
|
|
||||||
|
|
||||||
|
def is_prod_mode() -> bool:
|
||||||
|
"""Check if running in PROD mode"""
|
||||||
|
return get_deployment_mode() == "PROD"
|
||||||
|
|
||||||
|
|
||||||
|
def get_data_path(base_path: str) -> str:
|
||||||
|
"""
|
||||||
|
Get data path based on deployment mode
|
||||||
|
|
||||||
|
Args:
|
||||||
|
base_path: Base data path (e.g., "./data/agent_data")
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Modified path for DEV mode or original for PROD
|
||||||
|
|
||||||
|
Example:
|
||||||
|
PROD: "./data/agent_data" -> "./data/agent_data"
|
||||||
|
DEV: "./data/agent_data" -> "./data/dev_agent_data"
|
||||||
|
"""
|
||||||
|
if is_dev_mode():
|
||||||
|
# Replace agent_data with dev_agent_data
|
||||||
|
return base_path.replace("agent_data", "dev_agent_data")
|
||||||
|
return base_path
|
||||||
|
|
||||||
|
|
||||||
|
def get_db_path(base_db_path: str) -> str:
|
||||||
|
"""
|
||||||
|
Get database path based on deployment mode
|
||||||
|
|
||||||
|
Args:
|
||||||
|
base_db_path: Base database path (e.g., "data/trading.db")
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Modified path for DEV mode or original for PROD
|
||||||
|
|
||||||
|
Example:
|
||||||
|
PROD: "data/trading.db" -> "data/trading.db"
|
||||||
|
DEV: "data/trading.db" -> "data/trading_dev.db"
|
||||||
|
"""
|
||||||
|
if is_dev_mode():
|
||||||
|
# Insert _dev before .db extension
|
||||||
|
if base_db_path.endswith(".db"):
|
||||||
|
return base_db_path[:-3] + "_dev.db"
|
||||||
|
return base_db_path + "_dev"
|
||||||
|
return base_db_path
|
||||||
|
|
||||||
|
|
||||||
|
def should_preserve_dev_data() -> bool:
|
||||||
|
"""
|
||||||
|
Check if dev data should be preserved between runs
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
True if PRESERVE_DEV_DATA=true, False otherwise
|
||||||
|
"""
|
||||||
|
preserve = os.getenv("PRESERVE_DEV_DATA", "false").lower()
|
||||||
|
return preserve in ["true", "1", "yes"]
|
||||||
|
|
||||||
|
|
||||||
|
def log_api_key_warning() -> None:
|
||||||
|
"""
|
||||||
|
Log warning if production API keys are detected in DEV mode
|
||||||
|
|
||||||
|
Checks for common API key environment variables and warns if found.
|
||||||
|
"""
|
||||||
|
if not is_dev_mode():
|
||||||
|
return
|
||||||
|
|
||||||
|
# List of API key environment variables to check
|
||||||
|
api_key_vars = [
|
||||||
|
"OPENAI_API_KEY",
|
||||||
|
"ANTHROPIC_API_KEY",
|
||||||
|
"ALPHAADVANTAGE_API_KEY",
|
||||||
|
"JINA_API_KEY"
|
||||||
|
]
|
||||||
|
|
||||||
|
detected_keys = []
|
||||||
|
for var in api_key_vars:
|
||||||
|
value = os.getenv(var)
|
||||||
|
if value and value != "" and "your_" not in value.lower():
|
||||||
|
detected_keys.append(var)
|
||||||
|
|
||||||
|
if detected_keys:
|
||||||
|
print("⚠️ WARNING: Production API keys detected in DEV mode")
|
||||||
|
print(f" Detected: {', '.join(detected_keys)}")
|
||||||
|
print(" These keys will NOT be used - mock AI responses will be returned")
|
||||||
|
print(" This is expected if you're testing dev mode with existing .env file")
|
||||||
|
|
||||||
|
|
||||||
|
def get_deployment_mode_dict() -> dict:
|
||||||
|
"""
|
||||||
|
Get deployment mode information as dictionary (for API responses)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Dictionary with deployment mode metadata
|
||||||
|
"""
|
||||||
|
return {
|
||||||
|
"deployment_mode": get_deployment_mode(),
|
||||||
|
"is_dev_mode": is_dev_mode(),
|
||||||
|
"preserve_dev_data": should_preserve_dev_data() if is_dev_mode() else None
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user