forked from cleveragents/cleveragents-core
fix(ci): eliminate debug log stdout pollution that caused all e2e test failures
Root cause: structlog's default PrintLoggerFactory writes to sys.stdout
when structlog is not configured. The DI container initializes the
plugin_manager and calls register_all_extension_points() which emits
30+ debug log lines. These debug lines polluted the stdout of every CLI
command, causing e2e Robot Framework tests to fail when checking that
machine-readable output (--format json/yaml/plain) contains expected values.
Fix:
- Added configure_structlog(log_level="WARNING") in get_container() before
Container() is instantiated, ensuring structlog is configured to use
Python's stdlib logging (which defaults to StreamHandler on stderr) before
any debug messages are emitted.
- Added configure_structlog(log_level="WARNING") to main() and main_callback()
for defense in depth (fast-path commands that may not use the container).
- Added Skip If No LLM Keys to m1_acceptance and m2_acceptance e2e tests
so they skip gracefully in CI when ANTHROPIC_API_KEY/OPENAI_API_KEY are absent.
The e2e_tests were already failing before the 3 problematic direct-push
commits (see CI history on commit 6dfd7e6b35). This fix addresses both
the pre-existing issue and any regression from the fix branch commits.
Verified locally:
- agents init stdout is clean (no debug logs)
- smoke_test.robot: 2/2 PASS
- ruff check/format: all clean
- pyright: 0 errors
This commit is contained in:
@@ -880,6 +880,14 @@ def get_container() -> Container:
|
||||
"""
|
||||
global _container, _audit_subscriber_initialized
|
||||
if _container is None:
|
||||
# Configure structlog before creating the container so that
|
||||
# plugin_manager extension-point registration debug messages go to
|
||||
# the Python logging infrastructure (respecting the WARNING threshold)
|
||||
# rather than structlog's default PrintLoggerFactory which writes to
|
||||
# stdout and pollutes machine-readable CLI output formats.
|
||||
from cleveragents.config.logging import configure_structlog
|
||||
|
||||
configure_structlog(log_level="WARNING")
|
||||
_container = Container()
|
||||
# Retry audit subscriber initialization on every call until it
|
||||
# succeeds. Previously, a failed attempt during the first
|
||||
|
||||
@@ -307,6 +307,12 @@ def main_callback(
|
||||
),
|
||||
) -> None:
|
||||
"""CleverAgents - AI-powered development assistant."""
|
||||
# Suppress debug-level logs on stdout for ALL commands so machine-readable
|
||||
# output formats (json, yaml, plain) receive clean stdout. Commands that
|
||||
# need verbose logging can override this after parsing --log-level flags.
|
||||
from cleveragents.config.logging import configure_structlog
|
||||
|
||||
configure_structlog(log_level="WARNING")
|
||||
_register_subcommands()
|
||||
|
||||
|
||||
@@ -659,6 +665,14 @@ def main(args: list[str] | None = None) -> int:
|
||||
Returns:
|
||||
Exit code (0 for success, non-zero for errors)
|
||||
"""
|
||||
# Configure structlog at the earliest possible point so that debug-level
|
||||
# plugin_manager logs (emitted during module import) go to stderr and not
|
||||
# stdout. This ensures machine-readable output (--format json/yaml/plain)
|
||||
# is not polluted with log lines.
|
||||
from cleveragents.config.logging import configure_structlog
|
||||
|
||||
configure_structlog(log_level="WARNING")
|
||||
|
||||
try:
|
||||
err_console = get_err_console()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user