Skip to content
Open
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 21 additions & 11 deletions src/docbuild/cli/cmd_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
from ..config.app import replace_placeholders
from ..config.load import handle_config
from ..models.config_model.app import AppConfig
from ..models.config_model.env import EnvConfig

from ..constants import (
APP_CONFIG_BASENAMES,
APP_NAME,
Expand Down Expand Up @@ -159,12 +161,12 @@ def cli(
logging_config = context.appconfig.logging.model_dump(by_alias=True, exclude_none=True)
setup_logging(cliverbosity=verbose, user_config={'logging': logging_config})

# --- PHASE 2: Load Environment Config and Acquire Lock ---
# --- PHASE 2: Load Environment Config, Validate, and Acquire Lock ---

# Load Environment Config (still returns raw dict)
# 1. Load raw Environment Config
(
context.envconfigfiles,
context.envconfig,
raw_envconfig, # Renaming context.envconfig to raw_envconfig locally
context.envconfig_from_defaults,
) = handle_config(
env_config,
Expand All @@ -174,10 +176,23 @@ def cli(
DEFAULT_ENV_CONFIG,
)

env_config_path = context.envconfigfiles[0] if context.envconfigfiles else None
# Explicitly cast the raw_envconfig type to silence Pylance
raw_envconfig = cast(dict[str, Any], raw_envconfig)

# Explicitly cast the context.envconfig type to silence Pylance
context.envconfig = cast(dict[str, Any], context.envconfig)
# 2. VALIDATE the raw environment config dictionary using Pydantic
try:
# Pydantic validation handles placeholder replacement via @model_validator
# The result is the validated Pydantic object, stored in context.envconfig
context.envconfig = EnvConfig.from_dict(raw_envconfig)
except (ValueError, ValidationError) as e:
log.error(
"Environment configuration failed validation: "
"Error in config file(s): %s %s",
context.envconfigfiles, e
)
ctx.exit(1)

env_config_path = context.envconfigfiles[0] if context.envconfigfiles else None

# --- CONCURRENCY CONTROL: Use explicit __enter__ and cleanup registration ---
if env_config_path:
Expand All @@ -203,11 +218,6 @@ def cli(
# expected by __exit__, satisfying the click.call_on_close requirement.
ctx.call_on_close(lambda: ctx.obj.env_lock.__exit__(None, None, None))

# Final config processing must happen outside the lock acquisition check
context.envconfig = replace_placeholders(
context.envconfig,
)

# Add subcommand
cli.add_command(build)
cli.add_command(c14n)
Expand Down
27 changes: 1 addition & 26 deletions src/docbuild/config/load.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,32 +10,7 @@
from .merge import deep_merge


def process_envconfig(envconfigfile: str | Path | None) -> tuple[Path, dict[str, Any]]:
"""Process the env config.

Note: This function now returns the raw dictionary. Validation and
placeholder replacement should be done by the caller using a Pydantic model
(e.g., EnvConfig).

:param envconfigfile: Path to the env TOML config file.
:return: Tuple of the env config file path and the config object (raw dict).
:raise ValueError: If neither envconfigfile nor role is provided.
"""
if envconfigfile:
envconfigfile = Path(envconfigfile)

# If we don't have a envconfigfile, we need to find the default one.
# We will look for the default env config file in the current directory.
elif (rfile := Path(DEFAULT_ENV_CONFIG_FILENAME)).exists():
envconfigfile = rfile

else:
raise ValueError(
'Could not find default ENV configuration file.',
)

rawconfig = load_single_config(envconfigfile)
return envconfigfile, rawconfig
# --- REMOVED THE OBSOLETE `process_envconfig` FUNCTION ---


def load_single_config(configfile: str | Path) -> dict[str, Any]:
Expand Down
5 changes: 5 additions & 0 deletions src/docbuild/models/config_model/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"""Config model package for the docbuild application."""


from .env import EnvConfig
from .app import AppConfig
Loading
Loading