Refactor environment and configuration management

- Updated the project structure to store configuration files (.env, models.yaml, extensions.yaml) in the project root instead of the user's home directory.
- Enhanced the setup process to automatically copy example files to the project root on first run.
- Implemented a migration function to transfer legacy configuration files from the user's home directory to the new project structure.
- Revised documentation to reflect changes in file locations and setup instructions.
- Improved code readability and maintainability by refactoring path management functions.
This commit is contained in:
Leonid Pershin
2026-08-21 03:20:18 +03:00
parent c2ca39a4a7
commit 343f741baa
22 changed files with 202 additions and 90 deletions
+15 -10
View File
@@ -1,4 +1,4 @@
"""Load ~/.gpu-rent/.env. No secrets in git."""
"""Load <project>/.env. No secrets in git."""
from __future__ import annotations
@@ -10,10 +10,13 @@ from dotenv import load_dotenv
from gpu_rent.errors import ConfigError
from gpu_rent.paths import (
app_root,
default_ssh_key_path,
detect_app_root,
env_path,
home_dir,
extensions_manifest_path,
migrate_legacy_if_needed,
models_manifest_path,
runtime_dir,
)
@@ -96,12 +99,14 @@ def _required(name: str) -> str:
def load_config(*, require_auth: bool = True) -> Config:
home_dir().mkdir(parents=True, exist_ok=True)
root = app_root()
runtime_dir().mkdir(parents=True, exist_ok=True)
migrate_legacy_if_needed()
env_file = env_path()
if env_file.is_file():
load_dotenv(env_file, override=False)
app_root = detect_app_root()
missing: list[str] = []
required = (
"OS_AUTH_URL",
@@ -119,7 +124,7 @@ def load_config(*, require_auth: bool = True) -> Config:
if require_auth and missing:
raise ConfigError(
"В ~/.gpu-rent/.env не хватает: "
f"В {env_file} не хватает: "
+ ", ".join(missing)
+ ". Как заполнить: docs/setup.md (сервисный пользователь, не X-Token)."
)
@@ -128,16 +133,16 @@ def load_config(*, require_auth: bool = True) -> Config:
ssh_key = Path(key_override).expanduser() if key_override else default_ssh_key_path()
models_manifest = Path(
(os.environ.get("MODELS_MANIFEST") or "").strip() or (home_dir() / "models.yaml")
(os.environ.get("MODELS_MANIFEST") or "").strip() or str(models_manifest_path())
).expanduser()
extensions_manifest = Path(
(os.environ.get("EXTENSIONS_MANIFEST") or "").strip()
or (home_dir() / "extensions.yaml")
or str(extensions_manifest_path())
).expanduser()
def _dir(env_name: str, folder: str) -> Path:
raw = (os.environ.get(env_name) or "").strip()
return Path(raw).expanduser() if raw else (app_root / folder)
return Path(raw).expanduser() if raw else (root / folder)
return Config(
os_auth_url=values["OS_AUTH_URL"] or "https://cloud.api.selcloud.ru/identity/v3",
@@ -162,7 +167,7 @@ def load_config(*, require_auth: bool = True) -> Config:
local_wildcards_dir=_dir("LOCAL_WILDCARDS_DIR", "Wildcards"),
local_workflows_dir=_dir("LOCAL_WORKFLOWS_DIR", "CustomWorkflows"),
local_output_dir=_dir("LOCAL_OUTPUT_DIR", "Output"),
app_root=app_root,
app_root=root,
autocomplete_enabled=_as_bool(os.environ.get("AUTOCOMPLETE_ENABLED"), True),
autocomplete_github_repo=(
os.environ.get("AUTOCOMPLETE_GITHUB_REPO") or "DominikDoom/a1111-sd-webui-tagcomplete"