Skip to content

Commit bca65e6

Browse files
nathan-weinbergElbehery
authored andcommitted
feat: add auto-generated CI documentation pre-commit hook (#2890)
Our CI is entirely undocumented, this commit adds a README.md file with a table of the current CI and what is does --------- Signed-off-by: Nathan Weinberg <[email protected]>
1 parent e12524a commit bca65e6

File tree

93 files changed

+494
-477
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

93 files changed

+494
-477
lines changed

.pre-commit-config.yaml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,24 @@ repos:
145145
pass_filenames: false
146146
require_serial: true
147147
files: ^.github/workflows/.*$
148+
- id: check-log-usage
149+
name: Check for proper log usage (use llama_stack.log instead)
150+
entry: bash
151+
language: system
152+
types: [python]
153+
pass_filenames: true
154+
args:
155+
- -c
156+
- |
157+
matches=$(grep -EnH '^[^#]*\b(import logging|from logging\b)' "$@" | grep -v '# allow-direct-logging' || true)
158+
if [ -n "$matches" ]; then
159+
# GitHub Actions annotation format
160+
while IFS=: read -r file line_num rest; do
161+
echo "::error file=$file,line=$line_num::Do not use 'import logging' or 'from logging import' in $file. Use the custom log instead: from llama_stack.log import get_logger; logger = get_logger(). If direct logging is truly needed, add: # allow-direct-logging"
162+
done <<< "$matches"
163+
exit 1
164+
fi
165+
exit 0
148166
149167
ci:
150168
autofix_commit_msg: 🎨 [pre-commit.ci] Auto format from pre-commit.com hooks

llama_stack/cli/stack/run.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
REPO_ROOT = Path(__file__).parent.parent.parent.parent
1717

18-
logger = get_logger(name=__name__, category="server")
18+
log = get_logger(name=__name__, category="server")
1919

2020

2121
class StackRun(Subcommand):
@@ -126,7 +126,7 @@ def _run_stack_run_cmd(self, args: argparse.Namespace) -> None:
126126
self.parser.error("Config file is required for venv environment")
127127

128128
if config_file:
129-
logger.info(f"Using run configuration: {config_file}")
129+
log.info(f"Using run configuration: {config_file}")
130130

131131
try:
132132
config_dict = yaml.safe_load(config_file.read_text())
@@ -145,7 +145,7 @@ def _run_stack_run_cmd(self, args: argparse.Namespace) -> None:
145145
# If neither image type nor image name is provided, assume the server should be run directly
146146
# using the current environment packages.
147147
if not image_type and not image_name:
148-
logger.info("No image type or image name provided. Assuming environment packages.")
148+
log.info("No image type or image name provided. Assuming environment packages.")
149149
from llama_stack.core.server.server import main as server_main
150150

151151
# Build the server args from the current args passed to the CLI
@@ -185,11 +185,11 @@ def _run_stack_run_cmd(self, args: argparse.Namespace) -> None:
185185
run_command(run_args)
186186

187187
def _start_ui_development_server(self, stack_server_port: int):
188-
logger.info("Attempting to start UI development server...")
188+
log.info("Attempting to start UI development server...")
189189
# Check if npm is available
190190
npm_check = subprocess.run(["npm", "--version"], capture_output=True, text=True, check=False)
191191
if npm_check.returncode != 0:
192-
logger.warning(
192+
log.warning(
193193
f"'npm' command not found or not executable. UI development server will not be started. Error: {npm_check.stderr}"
194194
)
195195
return
@@ -214,13 +214,13 @@ def _start_ui_development_server(self, stack_server_port: int):
214214
stderr=stderr_log_file,
215215
env={**os.environ, "NEXT_PUBLIC_LLAMA_STACK_BASE_URL": f"http://localhost:{stack_server_port}"},
216216
)
217-
logger.info(f"UI development server process started in {ui_dir} with PID {process.pid}.")
218-
logger.info(f"Logs: stdout -> {ui_stdout_log_path}, stderr -> {ui_stderr_log_path}")
219-
logger.info(f"UI will be available at http://localhost:{os.getenv('LLAMA_STACK_UI_PORT', 8322)}")
217+
log.info(f"UI development server process started in {ui_dir} with PID {process.pid}.")
218+
log.info(f"Logs: stdout -> {ui_stdout_log_path}, stderr -> {ui_stderr_log_path}")
219+
log.info(f"UI will be available at http://localhost:{os.getenv('LLAMA_STACK_UI_PORT', 8322)}")
220220

221221
except FileNotFoundError:
222-
logger.error(
222+
log.error(
223223
"Failed to start UI development server: 'npm' command not found. Make sure npm is installed and in your PATH."
224224
)
225225
except Exception as e:
226-
logger.error(f"Failed to start UI development server in {ui_dir}: {e}")
226+
log.error(f"Failed to start UI development server in {ui_dir}: {e}")

llama_stack/cli/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
from llama_stack.log import get_logger
1010

11-
logger = get_logger(name=__name__, category="cli")
11+
log = get_logger(name=__name__, category="cli")
1212

1313

1414
# TODO: this can probably just be inlined now?

llama_stack/core/build.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
# the root directory of this source tree.
66

77
import importlib.resources
8-
import logging
98
import sys
109

1110
from pydantic import BaseModel
@@ -17,10 +16,9 @@
1716
from llama_stack.core.utils.exec import run_command
1817
from llama_stack.core.utils.image_types import LlamaStackImageType
1918
from llama_stack.distributions.template import DistributionTemplate
19+
from llama_stack.log import get_logger
2020
from llama_stack.providers.datatypes import Api
2121

22-
log = logging.getLogger(__name__)
23-
2422
# These are the dependencies needed by the distribution server.
2523
# `llama-stack` is automatically installed by the installation script.
2624
SERVER_DEPENDENCIES = [
@@ -33,6 +31,8 @@
3331
"opentelemetry-exporter-otlp-proto-http",
3432
]
3533

34+
log = get_logger(name=__name__, category="core")
35+
3636

3737
class ApiInput(BaseModel):
3838
api: Api

llama_stack/core/configure.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
#
44
# This source code is licensed under the terms described in the LICENSE file in
55
# the root directory of this source tree.
6-
import logging
76
import textwrap
87
from typing import Any
98

@@ -21,9 +20,10 @@
2120
from llama_stack.core.utils.config_dirs import EXTERNAL_PROVIDERS_DIR
2221
from llama_stack.core.utils.dynamic import instantiate_class_type
2322
from llama_stack.core.utils.prompt_for_config import prompt_for_config
23+
from llama_stack.log import get_logger
2424
from llama_stack.providers.datatypes import Api, ProviderSpec
2525

26-
logger = logging.getLogger(__name__)
26+
log = get_logger(name=__name__, category="core")
2727

2828

2929
def configure_single_provider(registry: dict[str, ProviderSpec], provider: Provider) -> Provider:
@@ -49,7 +49,7 @@ def configure_api_providers(config: StackRunConfig, build_spec: DistributionSpec
4949
is_nux = len(config.providers) == 0
5050

5151
if is_nux:
52-
logger.info(
52+
log.info(
5353
textwrap.dedent(
5454
"""
5555
Llama Stack is composed of several APIs working together. For each API served by the Stack,
@@ -75,12 +75,12 @@ def configure_api_providers(config: StackRunConfig, build_spec: DistributionSpec
7575

7676
existing_providers = config.providers.get(api_str, [])
7777
if existing_providers:
78-
logger.info(f"Re-configuring existing providers for API `{api_str}`...")
78+
log.info(f"Re-configuring existing providers for API `{api_str}`...")
7979
updated_providers = []
8080
for p in existing_providers:
81-
logger.info(f"> Configuring provider `({p.provider_type})`")
81+
log.info(f"> Configuring provider `({p.provider_type})`")
8282
updated_providers.append(configure_single_provider(provider_registry[api], p))
83-
logger.info("")
83+
log.info("")
8484
else:
8585
# we are newly configuring this API
8686
plist = build_spec.providers.get(api_str, [])
@@ -89,17 +89,17 @@ def configure_api_providers(config: StackRunConfig, build_spec: DistributionSpec
8989
if not plist:
9090
raise ValueError(f"No provider configured for API {api_str}?")
9191

92-
logger.info(f"Configuring API `{api_str}`...")
92+
log.info(f"Configuring API `{api_str}`...")
9393
updated_providers = []
9494
for i, provider in enumerate(plist):
9595
if i >= 1:
9696
others = ", ".join(p.provider_type for p in plist[i:])
97-
logger.info(
97+
log.info(
9898
f"Not configuring other providers ({others}) interactively. Please edit the resulting YAML directly.\n"
9999
)
100100
break
101101

102-
logger.info(f"> Configuring provider `({provider.provider_type})`")
102+
log.info(f"> Configuring provider `({provider.provider_type})`")
103103
pid = provider.provider_type.split("::")[-1]
104104
updated_providers.append(
105105
configure_single_provider(
@@ -111,7 +111,7 @@ def configure_api_providers(config: StackRunConfig, build_spec: DistributionSpec
111111
),
112112
)
113113
)
114-
logger.info("")
114+
log.info("")
115115

116116
config.providers[api_str] = updated_providers
117117

@@ -169,7 +169,7 @@ def parse_and_maybe_upgrade_config(config_dict: dict[str, Any]) -> StackRunConfi
169169
return StackRunConfig(**cast_image_name_to_string(processed_config_dict))
170170

171171
if "routing_table" in config_dict:
172-
logger.info("Upgrading config...")
172+
log.info("Upgrading config...")
173173
config_dict = upgrade_from_routing_table(config_dict)
174174

175175
config_dict["version"] = LLAMA_STACK_RUN_CONFIG_VERSION

llama_stack/core/distribution.py

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
remote_provider_spec,
2424
)
2525

26-
logger = get_logger(name=__name__, category="core")
26+
log = get_logger(name=__name__, category="core")
2727

2828

2929
def stack_apis() -> list[Api]:
@@ -141,18 +141,18 @@ def get_provider_registry(config=None) -> dict[Api, dict[str, ProviderSpec]]:
141141
registry: dict[Api, dict[str, ProviderSpec]] = {}
142142
for api in providable_apis():
143143
name = api.name.lower()
144-
logger.debug(f"Importing module {name}")
144+
log.debug(f"Importing module {name}")
145145
try:
146146
module = importlib.import_module(f"llama_stack.providers.registry.{name}")
147147
registry[api] = {a.provider_type: a for a in module.available_providers()}
148148
except ImportError as e:
149-
logger.warning(f"Failed to import module {name}: {e}")
149+
log.warning(f"Failed to import module {name}: {e}")
150150

151151
# Refresh providable APIs with external APIs if any
152152
external_apis = load_external_apis(config)
153153
for api, api_spec in external_apis.items():
154154
name = api_spec.name.lower()
155-
logger.info(f"Importing external API {name} module {api_spec.module}")
155+
log.info(f"Importing external API {name} module {api_spec.module}")
156156
try:
157157
module = importlib.import_module(api_spec.module)
158158
registry[api] = {a.provider_type: a for a in module.available_providers()}
@@ -161,7 +161,7 @@ def get_provider_registry(config=None) -> dict[Api, dict[str, ProviderSpec]]:
161161
# This assume that the in-tree provider(s) are not available for this API which means
162162
# that users will need to use external providers for this API.
163163
registry[api] = {}
164-
logger.error(
164+
log.error(
165165
f"Failed to import external API {name}: {e}. Could not populate the in-tree provider(s) registry for {api.name}. \n"
166166
"Install the API package to load any in-tree providers for this API."
167167
)
@@ -183,13 +183,13 @@ def get_provider_registry(config=None) -> dict[Api, dict[str, ProviderSpec]]:
183183
def get_external_providers_from_dir(
184184
registry: dict[Api, dict[str, ProviderSpec]], config
185185
) -> dict[Api, dict[str, ProviderSpec]]:
186-
logger.warning(
186+
log.warning(
187187
"Specifying external providers via `external_providers_dir` is being deprecated. Please specify `module:` in the provider instead."
188188
)
189189
external_providers_dir = os.path.abspath(os.path.expanduser(config.external_providers_dir))
190190
if not os.path.exists(external_providers_dir):
191191
raise FileNotFoundError(f"External providers directory not found: {external_providers_dir}")
192-
logger.info(f"Loading external providers from {external_providers_dir}")
192+
log.info(f"Loading external providers from {external_providers_dir}")
193193

194194
for api in providable_apis():
195195
api_name = api.name.lower()
@@ -198,13 +198,13 @@ def get_external_providers_from_dir(
198198
for provider_type in ["remote", "inline"]:
199199
api_dir = os.path.join(external_providers_dir, provider_type, api_name)
200200
if not os.path.exists(api_dir):
201-
logger.debug(f"No {provider_type} provider directory found for {api_name}")
201+
log.debug(f"No {provider_type} provider directory found for {api_name}")
202202
continue
203203

204204
# Look for provider spec files in the API directory
205205
for spec_path in glob.glob(os.path.join(api_dir, "*.yaml")):
206206
provider_name = os.path.splitext(os.path.basename(spec_path))[0]
207-
logger.info(f"Loading {provider_type} provider spec from {spec_path}")
207+
log.info(f"Loading {provider_type} provider spec from {spec_path}")
208208

209209
try:
210210
with open(spec_path) as f:
@@ -217,16 +217,16 @@ def get_external_providers_from_dir(
217217
spec = _load_inline_provider_spec(spec_data, api, provider_name)
218218
provider_type_key = f"inline::{provider_name}"
219219

220-
logger.info(f"Loaded {provider_type} provider spec for {provider_type_key} from {spec_path}")
220+
log.info(f"Loaded {provider_type} provider spec for {provider_type_key} from {spec_path}")
221221
if provider_type_key in registry[api]:
222-
logger.warning(f"Overriding already registered provider {provider_type_key} for {api.name}")
222+
log.warning(f"Overriding already registered provider {provider_type_key} for {api.name}")
223223
registry[api][provider_type_key] = spec
224-
logger.info(f"Successfully loaded external provider {provider_type_key}")
224+
log.info(f"Successfully loaded external provider {provider_type_key}")
225225
except yaml.YAMLError as yaml_err:
226-
logger.error(f"Failed to parse YAML file {spec_path}: {yaml_err}")
226+
log.error(f"Failed to parse YAML file {spec_path}: {yaml_err}")
227227
raise yaml_err
228228
except Exception as e:
229-
logger.error(f"Failed to load provider spec from {spec_path}: {e}")
229+
log.error(f"Failed to load provider spec from {spec_path}: {e}")
230230
raise e
231231

232232
return registry
@@ -241,7 +241,7 @@ def get_external_providers_from_module(
241241
else:
242242
provider_list = config.providers.items()
243243
if provider_list is None:
244-
logger.warning("Could not get list of providers from config")
244+
log.warning("Could not get list of providers from config")
245245
return registry
246246
for provider_api, providers in provider_list:
247247
for provider in providers:
@@ -272,6 +272,6 @@ def get_external_providers_from_module(
272272
"get_provider_spec not found. If specifying an external provider via `module` in the Provider spec, the Provider must have the `provider.get_provider_spec` module available"
273273
) from exc
274274
except Exception as e:
275-
logger.error(f"Failed to load provider spec from module {provider.module}: {e}")
275+
log.error(f"Failed to load provider spec from module {provider.module}: {e}")
276276
raise e
277277
return registry

llama_stack/core/external.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from llama_stack.core.datatypes import BuildConfig, StackRunConfig
1212
from llama_stack.log import get_logger
1313

14-
logger = get_logger(name=__name__, category="core")
14+
log = get_logger(name=__name__, category="core")
1515

1616

1717
def load_external_apis(config: StackRunConfig | BuildConfig | None) -> dict[Api, ExternalApiSpec]:
@@ -28,10 +28,10 @@ def load_external_apis(config: StackRunConfig | BuildConfig | None) -> dict[Api,
2828

2929
external_apis_dir = config.external_apis_dir.expanduser().resolve()
3030
if not external_apis_dir.is_dir():
31-
logger.error(f"External APIs directory is not a directory: {external_apis_dir}")
31+
log.error(f"External APIs directory is not a directory: {external_apis_dir}")
3232
return {}
3333

34-
logger.info(f"Loading external APIs from {external_apis_dir}")
34+
log.info(f"Loading external APIs from {external_apis_dir}")
3535
external_apis: dict[Api, ExternalApiSpec] = {}
3636

3737
# Look for YAML files in the external APIs directory
@@ -42,13 +42,13 @@ def load_external_apis(config: StackRunConfig | BuildConfig | None) -> dict[Api,
4242

4343
spec = ExternalApiSpec(**spec_data)
4444
api = Api.add(spec.name)
45-
logger.info(f"Loaded external API spec for {spec.name} from {yaml_path}")
45+
log.info(f"Loaded external API spec for {spec.name} from {yaml_path}")
4646
external_apis[api] = spec
4747
except yaml.YAMLError as yaml_err:
48-
logger.error(f"Failed to parse YAML file {yaml_path}: {yaml_err}")
48+
log.error(f"Failed to parse YAML file {yaml_path}: {yaml_err}")
4949
raise
5050
except Exception:
51-
logger.exception(f"Failed to load external API spec from {yaml_path}")
51+
log.exception(f"Failed to load external API spec from {yaml_path}")
5252
raise
5353

5454
return external_apis

0 commit comments

Comments
 (0)