2121from pathlib import Path
2222from typing import NamedTuple
2323
24+ from pydantic import field_validator
25+ from pydantic_settings import BaseSettings , SettingsConfigDict
2426from ruamel .yaml import YAML
2527
2628# Allowed characters for version strings: alphanumeric, dots, hyphens, plus, underscores
2931
3032OGX_GIT_REPO = "https://github.com/opendatahub-io/ogx.git"
3133
32-
3334STRIPPED_PROVIDER_TYPES = {
3435 "inline::sentence-transformers" ,
3536 "inline::milvus" ,
4849)
4950
5051
51- def _validate_version (version : str ) -> str :
52- """Validate a version string contains only safe characters.
52+ class BuildConfig (BaseSettings ):
53+ model_config = SettingsConfigDict (
54+ env_file = Path (__file__ ).parent / "build.env" ,
55+ )
5356
54- Raises ValueError if the version contains shell metacharacters or
55- other unexpected characters that could lead to injection.
56- """
57- if not version or not _VERSION_PATTERN .match (version ):
58- raise ValueError (
59- f"Invalid version format: { version !r} . "
60- "Only alphanumeric characters, dots, hyphens, plus signs, underscores, and slashes are allowed."
61- )
62- return version
57+ ogx_version : str
58+ ogx_install_from_source : bool = False
59+ rhai_index_url : str | None = None
60+
61+ @field_validator ("ogx_version" )
62+ @classmethod
63+ def check_version (cls , v : str ) -> str :
64+ if not v or not _VERSION_PATTERN .match (v ):
65+ raise ValueError (
66+ f"Invalid version format: { v !r} . "
67+ "Only alphanumeric characters, dots, hyphens, plus signs, "
68+ "underscores, and slashes are allowed."
69+ )
70+ return v
6371
6472
6573def _resolve_ref_to_sha (repo_url : str , ref : str ) -> str :
@@ -88,18 +96,6 @@ def _resolve_ref_to_sha(repo_url: str, ref: str) -> str:
8896 return sha
8997
9098
91- def _load_env (path : Path ) -> dict [str , str ]:
92- """Load key=value pairs from an env file."""
93- env = {}
94- with open (path ) as f :
95- for line in f :
96- line = line .strip ()
97- if line and not line .startswith ("#" ) and "=" in line :
98- key , value = line .split ("=" , 1 )
99- env [key .strip ()] = value .strip ()
100- return env
101-
102-
10399class OgxRequirements (NamedTuple ):
104100 ogx_api : str
105101 ogx : str
@@ -120,18 +116,15 @@ class LockfileConfig(NamedTuple):
120116 index_config : IndexConfig
121117
122118
123- def _get_ogx_requirements () -> OgxRequirements :
124- """Resolve ogx package specifiers from build.env and environment.
119+ def _get_ogx_requirements (
120+ version : str , install_from_source : bool
121+ ) -> OgxRequirements :
122+ """Resolve ogx package specifiers.
125123
126124 When installing from source, the git tag is resolved to an immutable
127125 commit SHA via git ls-remote.
128126 """
129- env = _load_env (Path (__file__ ).parent / "build.env" )
130-
131- version = os .getenv ("OGX_VERSION" ) or env ["OGX_VERSION" ]
132- _validate_version (version )
133-
134- if env .get ("OGX_INSTALL_FROM_SOURCE" , "" ).lower () == "true" :
127+ if install_from_source :
135128 sha = _resolve_ref_to_sha (OGX_GIT_REPO , version )
136129 return OgxRequirements (
137130 ogx_api = f"ogx-api @ git+{ OGX_GIT_REPO } @{ sha } #subdirectory=src/ogx_api" ,
@@ -379,7 +372,7 @@ def _write_temp_requirements(lines: list[str]) -> Path:
379372
380373
381374def _get_lockfile_targets (
382- install_from_source : bool , rhai_index_url : str
375+ install_from_source : bool , rhai_index_url : str | None
383376) -> dict [LockfileType , LockfileConfig ]:
384377 """Determine which lock files to generate based on build configuration."""
385378 targets = {}
@@ -462,18 +455,20 @@ def generate_containerfile(version: str):
462455
463456
464457def main ():
465- env = _load_env (Path (__file__ ).parent / "build.env" )
466- install_from_source = env .get ("OGX_INSTALL_FROM_SOURCE" , "" ).lower () == "true"
467- rhai_index_url = os .getenv ("RHAI_INDEX_URL" ) or env .get ("RHAI_INDEX_URL" , "" )
458+ config = BuildConfig ()
468459
469- ogx_reqs = _get_ogx_requirements ()
460+ ogx_reqs = _get_ogx_requirements (
461+ config .ogx_version , config .ogx_install_from_source
462+ )
470463
471464 assert_command_installed ("uv" )
472465
473466 print ("Generating stripped config.yaml..." )
474467 generate_stripped_config ()
475468
476- targets = _get_lockfile_targets (install_from_source , rhai_index_url )
469+ targets = _get_lockfile_targets (
470+ config .ogx_install_from_source , config .rhai_index_url
471+ )
477472
478473 for name , target in targets .items ():
479474 print (f"Generating { target .output_path } ..." )
@@ -507,10 +502,8 @@ def main():
507502 finally :
508503 os .unlink (tmp_path )
509504
510- version = _validate_version (os .getenv ("OGX_VERSION" ) or env ["OGX_VERSION" ])
511-
512505 print ("Generating Containerfile..." )
513- generate_containerfile (version )
506+ generate_containerfile (config . ogx_version )
514507
515508 print ("Done!" )
516509
0 commit comments