d98666651f
CI / lint (pull_request) Successful in 15s
CI / typecheck (pull_request) Successful in 27s
CI / security (pull_request) Successful in 22s
CI / quality (pull_request) Successful in 15s
CI / integration_tests (pull_request) Successful in 4m24s
CI / build (pull_request) Successful in 16s
CI / unit_tests (pull_request) Successful in 9m27s
CI / lint (push) Waiting to run
CI / typecheck (push) Waiting to run
CI / security (push) Waiting to run
CI / quality (push) Waiting to run
CI / unit_tests (push) Waiting to run
CI / integration_tests (push) Waiting to run
CI / coverage (push) Blocked by required conditions
CI / build (push) Waiting to run
CI / docker (push) Blocked by required conditions
CI / coverage (pull_request) Successful in 6m55s
CI / docker (pull_request) Successful in 39s
- Enforce config-only 'action create --config <file>' (remove legacy inline flags: --name, --strategy-actor, --execution-actor, --definition-of-done, --arg) - Load config via ActionConfigSchema.from_yaml_file() then Action.from_config() with clear validation error surfacing - Remove 'action available' subcommand (no draft state; actions are available by default) - Add REGEX positional arg to 'action list' for name filtering - Add Short Name and Definition of Done summary to all CLI outputs - Add 'action list --namespace/-n' and '--state/-s' filters - Update existing tests to match new config-only create flow - Add features/action_cli_spec_alignment.feature (19 scenarios) - Add robot/action_cli_spec.robot smoke tests - Add benchmarks/action_cli_bench.py ASV benchmarks - Add docs/reference/action_cli.md
135 lines
4.1 KiB
Python
135 lines
4.1 KiB
Python
"""ASV benchmarks for Action CLI command throughput.
|
|
|
|
Measures the performance of:
|
|
- Config-only create (YAML load + validate + Action.from_config)
|
|
- List command rendering
|
|
- Show command rendering
|
|
- Archive command rendering
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import importlib
|
|
import os
|
|
import sys
|
|
import tempfile
|
|
from datetime import datetime
|
|
from pathlib import Path
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
# Ensure the local *source* tree is importable even when ASV has an
|
|
# older build of the package installed.
|
|
_SRC = str(Path(__file__).resolve().parents[1] / "src")
|
|
if _SRC not in sys.path:
|
|
sys.path.insert(0, _SRC)
|
|
|
|
import cleveragents # noqa: E402
|
|
|
|
importlib.reload(cleveragents)
|
|
|
|
from typer.testing import CliRunner # noqa: E402
|
|
|
|
from cleveragents.cli.commands.action import app as action_app # noqa: E402
|
|
from cleveragents.domain.models.core.action import Action, ActionState # noqa: E402
|
|
from cleveragents.domain.models.core.plan import NamespacedName # noqa: E402
|
|
|
|
_VALID_YAML = """\
|
|
name: local/bench-action
|
|
description: Benchmark action
|
|
strategy_actor: openai/gpt-4
|
|
execution_actor: openai/gpt-4
|
|
definition_of_done: Benchmarks pass
|
|
"""
|
|
|
|
_runner = CliRunner()
|
|
|
|
|
|
def _mock_action(name: str = "local/bench-action") -> Action:
|
|
return Action(
|
|
namespaced_name=NamespacedName.parse(name),
|
|
description="Benchmark action",
|
|
definition_of_done="Benchmarks pass",
|
|
strategy_actor="openai/gpt-4",
|
|
execution_actor="openai/gpt-4",
|
|
state=ActionState.AVAILABLE,
|
|
created_at=datetime.now(),
|
|
updated_at=datetime.now(),
|
|
)
|
|
|
|
|
|
class ActionCLICreateSuite:
|
|
"""Benchmark action create --config throughput."""
|
|
|
|
def setup(self) -> None:
|
|
"""Write a temporary YAML file and set up mock service."""
|
|
fd, self._path = tempfile.mkstemp(suffix=".yaml")
|
|
with os.fdopen(fd, "w") as fh:
|
|
fh.write(_VALID_YAML)
|
|
self._mock_service = MagicMock()
|
|
self._mock_service.create_action.return_value = _mock_action()
|
|
self._patcher = patch(
|
|
"cleveragents.cli.commands.action._get_lifecycle_service",
|
|
return_value=self._mock_service,
|
|
)
|
|
self._patcher.start()
|
|
|
|
def teardown(self) -> None:
|
|
"""Clean up."""
|
|
self._patcher.stop()
|
|
Path(self._path).unlink(missing_ok=True)
|
|
|
|
def time_create_from_config(self) -> None:
|
|
"""Benchmark create --config end-to-end."""
|
|
_runner.invoke(action_app, ["create", "--config", self._path])
|
|
|
|
|
|
class ActionCLIListSuite:
|
|
"""Benchmark action list throughput."""
|
|
|
|
def setup(self) -> None:
|
|
"""Set up mock service with actions."""
|
|
self._mock_service = MagicMock()
|
|
self._mock_service.list_actions.return_value = [
|
|
_mock_action(f"local/action-{i}") for i in range(50)
|
|
]
|
|
self._patcher = patch(
|
|
"cleveragents.cli.commands.action._get_lifecycle_service",
|
|
return_value=self._mock_service,
|
|
)
|
|
self._patcher.start()
|
|
|
|
def teardown(self) -> None:
|
|
self._patcher.stop()
|
|
|
|
def time_list_all(self) -> None:
|
|
"""Benchmark listing all actions."""
|
|
_runner.invoke(action_app, ["list"])
|
|
|
|
def time_list_with_namespace(self) -> None:
|
|
"""Benchmark listing with namespace filter."""
|
|
_runner.invoke(action_app, ["list", "--namespace", "local"])
|
|
|
|
def time_list_with_state(self) -> None:
|
|
"""Benchmark listing with state filter."""
|
|
_runner.invoke(action_app, ["list", "--state", "available"])
|
|
|
|
|
|
class ActionCLIShowSuite:
|
|
"""Benchmark action show throughput."""
|
|
|
|
def setup(self) -> None:
|
|
self._mock_service = MagicMock()
|
|
self._mock_service.get_action_by_name.return_value = _mock_action()
|
|
self._patcher = patch(
|
|
"cleveragents.cli.commands.action._get_lifecycle_service",
|
|
return_value=self._mock_service,
|
|
)
|
|
self._patcher.start()
|
|
|
|
def teardown(self) -> None:
|
|
self._patcher.stop()
|
|
|
|
def time_show(self) -> None:
|
|
"""Benchmark showing an action."""
|
|
_runner.invoke(action_app, ["show", "local/bench-action"])
|