fix(config): resolve dotenv via workspace marker and prefer .mam.env over legacy .env
This commit is contained in:
@@ -33,37 +33,81 @@ import paho.mqtt.client as mqtt
|
|||||||
|
|
||||||
logger = logging.getLogger("delegate_job.mqtt_common")
|
logger = logging.getLogger("delegate_job.mqtt_common")
|
||||||
|
|
||||||
def _load_dotenv(workspace_dir: str = None) -> None:
|
_warned_deprecated_env = False
|
||||||
"""Load .env file from workspace if it exists and env var not already set.
|
_warned_coexistence_env = False
|
||||||
|
|
||||||
|
def _load_dotenv(workspace_dir: Optional[str] = None) -> None:
|
||||||
|
"""Load .mam.env (or .env fallback) from workspace if it exists.
|
||||||
|
|
||||||
This ensures Python scripts get the same env vars as the shell wrapper
|
Only sets vars that are not already in os.environ
|
||||||
scripts that source .env. Only sets vars that are not already in os.environ
|
(i.e. OS env takes precedence over env files).
|
||||||
(i.e. OS env takes precedence over .env file).
|
|
||||||
"""
|
"""
|
||||||
import os
|
global _warned_deprecated_env, _warned_coexistence_env
|
||||||
|
|
||||||
|
# 1. Check explicit MAM_ENV_FILE override
|
||||||
|
explicit_file = os.environ.get("MAM_ENV_FILE")
|
||||||
|
if explicit_file:
|
||||||
|
if os.path.isfile(explicit_file):
|
||||||
|
_parse_env_file(explicit_file)
|
||||||
|
return
|
||||||
|
|
||||||
|
# 2. Resolve workspace directory with boundary marker check (.agents or .git)
|
||||||
if workspace_dir is None:
|
if workspace_dir is None:
|
||||||
# Walk up from this script to find workspace root
|
curr = os.path.dirname(os.path.abspath(__file__))
|
||||||
d = os.path.dirname(os.path.abspath(__file__))
|
resolved_root = None
|
||||||
for _ in range(5):
|
while curr and curr != os.path.dirname(curr):
|
||||||
if os.path.isfile(os.path.join(d, ".env")):
|
if os.path.isdir(os.path.join(curr, ".agents")) or os.path.exists(os.path.join(curr, ".git")):
|
||||||
|
resolved_root = curr
|
||||||
break
|
break
|
||||||
d = os.path.dirname(d)
|
curr = os.path.dirname(curr)
|
||||||
|
if not resolved_root:
|
||||||
|
return
|
||||||
|
d = resolved_root
|
||||||
else:
|
else:
|
||||||
d = workspace_dir
|
d = workspace_dir
|
||||||
env_path = os.path.join(d, ".env")
|
|
||||||
if not os.path.isfile(env_path):
|
mam_env_path = os.path.join(d, ".mam.env")
|
||||||
return
|
legacy_env_path = os.path.join(d, ".env")
|
||||||
with open(env_path, "r") as f:
|
|
||||||
for line in f:
|
has_mam = os.path.isfile(mam_env_path)
|
||||||
line = line.strip()
|
has_legacy = os.path.isfile(legacy_env_path)
|
||||||
if not line or line.startswith("#"):
|
|
||||||
continue
|
if has_mam and has_legacy:
|
||||||
if "=" in line:
|
if not _warned_coexistence_env:
|
||||||
key, _, val = line.partition("=")
|
logger.warning(
|
||||||
key = key.strip()
|
"Both '%s' and '%s' exist. Loading '%s'. "
|
||||||
val = val.strip().strip('"').strip("'")
|
"Consider removing or migrating '%s'.",
|
||||||
if key and key not in os.environ:
|
mam_env_path, legacy_env_path, mam_env_path, legacy_env_path
|
||||||
os.environ[key] = val
|
)
|
||||||
|
_warned_coexistence_env = True
|
||||||
|
_parse_env_file(mam_env_path)
|
||||||
|
elif has_mam:
|
||||||
|
_parse_env_file(mam_env_path)
|
||||||
|
elif has_legacy:
|
||||||
|
if not _warned_deprecated_env:
|
||||||
|
logger.warning(
|
||||||
|
"Loading deprecated config file '%s'. "
|
||||||
|
"Please migrate to '.mam.env'.",
|
||||||
|
legacy_env_path
|
||||||
|
)
|
||||||
|
_warned_deprecated_env = True
|
||||||
|
_parse_env_file(legacy_env_path)
|
||||||
|
|
||||||
|
def _parse_env_file(path: str) -> None:
|
||||||
|
try:
|
||||||
|
with open(path, "r", encoding="utf-8") as f:
|
||||||
|
for line in f:
|
||||||
|
line = line.strip()
|
||||||
|
if not line or line.startswith("#"):
|
||||||
|
continue
|
||||||
|
if "=" in line:
|
||||||
|
key, _, val = line.partition("=")
|
||||||
|
key = key.strip()
|
||||||
|
val = val.strip().strip('"').strip("'")
|
||||||
|
if key and key not in os.environ:
|
||||||
|
os.environ[key] = val
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning("Failed to parse env file %s: %s", path, e)
|
||||||
|
|
||||||
_load_dotenv()
|
_load_dotenv()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user