Merge branch 'master' into develop-20260217

# Conflicts:
#	robot/database_integration.robot
This commit is contained in:
2026-02-19 00:57:48 +00:00
6 changed files with 70 additions and 17 deletions
@@ -106,6 +106,20 @@ def step_spec_service(context: Context) -> None:
context._cleanup_handlers = []
context._cleanup_handlers.append(context.service_patcher.stop)
# Patch the module-level Rich Console so it never injects ANSI escape
# codes. Without this, Rich detects a colour terminal and embeds
# escape sequences in the CLI output, causing plain-text assertions
# (e.g. ``"Action Created" in output``) to fail on real terminals
# while passing inside headless CI containers.
from rich.console import Console as _Console
_plain_console = _Console(no_color=True, highlight=False, width=300)
context.console_patcher = patch(
"cleveragents.cli.commands.action.console", _plain_console
)
context.console_patcher.start()
context._cleanup_handlers.append(context.console_patcher.stop)
# ---------------------------------------------------------------------------
# Given steps
+6 -1
View File
@@ -119,7 +119,12 @@ def _run_with_container(context: Any, func: Any, *args: Any, **kwargs: Any) -> N
mock_cont = _mock_container(context)
buf = StringIO()
test_console = RichConsole(file=buf, no_color=True)
# force_terminal=False and highlight=False prevent Rich from emitting
# ANSI escape codes when FORCE_COLOR is set or a real colour terminal
# is detected.
test_console = RichConsole(
file=buf, no_color=True, highlight=False, force_terminal=False
)
with (
patch(
@@ -30,6 +30,14 @@ from cleveragents.core.exceptions import ValidationError
_PATCH_TARGET = "cleveragents.cli.commands.resource._get_registry_service"
_PATCH_CONTAINER = "cleveragents.cli.commands.resource.get_container"
_PATCH_CONSOLE = "cleveragents.cli.commands.resource.console"
def _no_color_console():
"""Return a Rich Console that never emits ANSI escape codes."""
from rich.console import Console as _Console
return _Console(no_color=True, highlight=False, force_terminal=False)
def _make_mock_type_spec(*, built_in: bool = False) -> MagicMock:
@@ -136,7 +144,10 @@ def step_invoke_type_add_update(context: Context) -> None:
tmp.flush()
config_path = tmp.name
with patch(_PATCH_TARGET, return_value=context.rcb_mock_service):
with (
patch(_PATCH_TARGET, return_value=context.rcb_mock_service),
patch(_PATCH_CONSOLE, _no_color_console()),
):
context.rcb_result = runner.invoke(
app,
["type", "add", "--config", config_path, "--update"],
@@ -165,7 +176,10 @@ def step_invoke_type_add_fnf(context: Context) -> None:
tmp.flush()
config_path = tmp.name
with patch(_PATCH_TARGET, return_value=context.rcb_mock_service):
with (
patch(_PATCH_TARGET, return_value=context.rcb_mock_service),
patch(_PATCH_CONSOLE, _no_color_console()),
):
context.rcb_result = runner.invoke(
app,
["type", "add", "--config", config_path],
@@ -189,7 +203,10 @@ def step_invoke_type_remove_no(context: Context) -> None:
from cleveragents.cli.commands.resource import app
runner = CliRunner()
with patch(_PATCH_TARGET, return_value=context.rcb_mock_service):
with (
patch(_PATCH_TARGET, return_value=context.rcb_mock_service),
patch(_PATCH_CONSOLE, _no_color_console()),
):
context.rcb_result = runner.invoke(
app,
["type", "remove", "test/mock-type"],
@@ -234,7 +251,10 @@ def step_invoke_type_remove_row_none(context: Context) -> None:
from cleveragents.cli.commands.resource import app
runner = CliRunner()
with patch(_PATCH_TARGET, return_value=context.rcb_mock_service):
with (
patch(_PATCH_TARGET, return_value=context.rcb_mock_service),
patch(_PATCH_CONSOLE, _no_color_console()),
):
context.rcb_result = runner.invoke(
app,
["type", "remove", "test/mock-type", "--yes"],
@@ -282,7 +302,10 @@ def step_invoke_type_remove_exception(context: Context) -> None:
from cleveragents.cli.commands.resource import app
runner = CliRunner()
with patch(_PATCH_TARGET, return_value=context.rcb_mock_service):
with (
patch(_PATCH_TARGET, return_value=context.rcb_mock_service),
patch(_PATCH_CONSOLE, _no_color_console()),
):
context.rcb_result = runner.invoke(
app,
["type", "remove", "test/mock-type", "--yes"],
@@ -326,7 +349,10 @@ def step_invoke_resource_remove_edges(context: Context) -> None:
from cleveragents.cli.commands.resource import app
runner = CliRunner()
with patch(_PATCH_TARGET, return_value=context.rcb_mock_service):
with (
patch(_PATCH_TARGET, return_value=context.rcb_mock_service),
patch(_PATCH_CONSOLE, _no_color_console()),
):
context.rcb_result = runner.invoke(
app,
["remove", "local/mock-res", "--yes"],
@@ -377,7 +403,10 @@ def step_invoke_resource_remove_exception(context: Context) -> None:
from cleveragents.cli.commands.resource import app
runner = CliRunner()
with patch(_PATCH_TARGET, return_value=context.rcb_mock_service):
with (
patch(_PATCH_TARGET, return_value=context.rcb_mock_service),
patch(_PATCH_CONSOLE, _no_color_console()),
):
context.rcb_result = runner.invoke(
app,
["remove", "local/mock-res", "--yes"],
+6 -1
View File
@@ -35,7 +35,12 @@ def _make_service(context: Context) -> ResourceRegistryService:
def _capture_output(func: Any, *args: Any, **kwargs: Any) -> tuple[str, bool]:
"""Run a CLI function capturing its console output and success status."""
buf = StringIO()
console = Console(file=buf, width=200, no_color=True)
# force_terminal=False and highlight=False prevent Rich from emitting
# ANSI escape codes (bold, syntax highlighting) when FORCE_COLOR is set
# or a real colour terminal is detected.
console = Console(
file=buf, width=200, no_color=True, highlight=False, force_terminal=False
)
import cleveragents.cli.commands.resource as resource_mod
+7 -7
View File
@@ -19,7 +19,7 @@ Initialize New Project
[Setup] Setup Test Directory
${result}= Run Process ${PYTHON} -m cleveragents init ${PROJECT_NAME}
... cwd=${TEST_DIR} env:CLEVERAGENTS_AUTO_APPLY_MIGRATIONS=true stderr=STDOUT timeout=30s
... cwd=${TEST_DIR} env:CLEVERAGENTS_AUTO_APPLY_MIGRATIONS=true stderr=STDOUT timeout=60s
Should Be Equal As Integers ${result.rc} 0 Init failed: ${result.stdout}
Should Exist ${TEST_DIR}${/}.cleveragents
@@ -55,7 +55,7 @@ Create Plan With Tell
[Setup] Initialize Test Project
${result}= Run Process ${PYTHON} -m cleveragents tell Add error handling
... cwd=${TEST_DIR} timeout=30s
... cwd=${TEST_DIR} timeout=60s
Should Be Equal As Integers ${result.rc} 0
@@ -72,7 +72,7 @@ Build Plan
[Setup] Initialize Test Project With Plan
${result}= Run Process ${PYTHON} -m cleveragents build
... cwd=${TEST_DIR} env:CLEVERAGENTS_TESTING_USE_MOCK_AI=true timeout=30s
... cwd=${TEST_DIR} env:CLEVERAGENTS_TESTING_USE_MOCK_AI=true timeout=60s
Should Be Equal As Integers ${result.rc} 0
@@ -83,7 +83,7 @@ Apply Plan Changes
[Setup] Initialize Test Project With Built Plan
${result}= Run Process ${PYTHON} -m cleveragents apply --yes
... cwd=${TEST_DIR} timeout=30s
... cwd=${TEST_DIR} timeout=60s
Should Be Equal As Integers ${result.rc} 0
@@ -219,7 +219,7 @@ Clear All Context
[Setup] Initialize Test Project With Context
${result}= Run Process ${PYTHON} -m cleveragents context clear --yes
... cwd=${TEST_DIR} env:CLEVERAGENTS_AUTO_APPLY_MIGRATIONS=true stderr=STDOUT timeout=30s
... cwd=${TEST_DIR} env:CLEVERAGENTS_AUTO_APPLY_MIGRATIONS=true stderr=STDOUT timeout=60s
Should Be Equal As Integers ${result.rc} 0 Context clear failed: ${result.stdout}
@@ -266,14 +266,14 @@ Initialize Test Project With Plan
[Documentation] Initialize project and create a plan
Initialize Test Project
${result}= Run Process ${PYTHON} -m cleveragents tell Test instruction
... cwd=${TEST_DIR} env:CLEVERAGENTS_TESTING_USE_MOCK_AI=true timeout=30s
... cwd=${TEST_DIR} env:CLEVERAGENTS_TESTING_USE_MOCK_AI=true timeout=60s
Should Be Equal As Integers ${result.rc} 0
Initialize Test Project With Built Plan
[Documentation] Initialize project with a built plan
Initialize Test Project With Plan
${result}= Run Process ${PYTHON} -m cleveragents build
... cwd=${TEST_DIR} env:CLEVERAGENTS_TESTING_USE_MOCK_AI=true timeout=30s
... cwd=${TEST_DIR} env:CLEVERAGENTS_TESTING_USE_MOCK_AI=true timeout=60s
Should Be Equal As Integers ${result.rc} 0
Initialize Test Project With Multiple Plans
+1 -1
View File
@@ -755,7 +755,7 @@ Run Python Script
# Write to a temporary file
${temp_file}= Evaluate __import__('tempfile').NamedTemporaryFile(mode='w', suffix='.py', delete=False, dir='/tmp').name
Create File ${temp_file} ${full_code}
${result}= Run Process ${PYTHON} ${temp_file} timeout=30s stderr=STDOUT env:PYTHONWARNINGS=ignore env:PYTHONDONTWRITEBYTECODE=1
${result}= Run Process ${PYTHON} ${temp_file} timeout=60s stderr=STDOUT env:PYTHONWARNINGS=ignore env:PYTHONDONTWRITEBYTECODE=1
Remove File ${temp_file}
# Check if process failed and log stderr if present
IF ${result.rc} != 0