"""Helper script for Robot Framework built-in git tools smoke tests.""" from __future__ import annotations import shutil import subprocess import sys import tempfile from pathlib import Path from typing import Any # Ensure src is importable when run from workspace root sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src")) from cleveragents.tool.builtins import register_git_tools from cleveragents.tool.registry import ToolRegistry from cleveragents.tool.runner import ToolRunner def _git(args: list[str], cwd: str) -> subprocess.CompletedProcess[str]: """Run a git command with CI-safe environment variables. Sets ``safe.directory`` so git does not refuse to operate in temp directories owned by a different user (common in Docker / CI). """ import os env = { **os.environ, "GIT_CONFIG_NOSYSTEM": "1", "GIT_TERMINAL_PROMPT": "0", "GIT_CONFIG_COUNT": "1", "GIT_CONFIG_KEY_0": "safe.directory", "GIT_CONFIG_VALUE_0": cwd, } return subprocess.run( ["git", *args], cwd=cwd, capture_output=True, text=True, check=True, timeout=30, env=env, ) def _make_repo() -> str: """Create a temporary git repository with an initial commit.""" repo_dir = tempfile.mkdtemp() _git(["init"], cwd=repo_dir) _git(["config", "user.email", "test@test.com"], cwd=repo_dir) _git(["config", "user.name", "Test User"], cwd=repo_dir) readme = Path(repo_dir) / "README.md" readme.write_text("# Test repo\n") _git(["add", "."], cwd=repo_dir) _git(["commit", "-m", "Initial commit"], cwd=repo_dir) return repo_dir def _make_runner() -> ToolRunner: registry = ToolRegistry() register_git_tools(registry) return ToolRunner(registry) def test_status() -> None: repo = _make_repo() try: runner = _make_runner() result = runner.execute( "builtin/git-status", {"repo_path": repo, "_sandbox_root": repo}, ) assert result.success, f"Failed: {result.error}" assert "nothing to commit" in result.output["output"] print("git-status-ok") finally: shutil.rmtree(repo, ignore_errors=True) def test_diff() -> None: repo = _make_repo() try: # Modify a file to create a diff f = Path(repo) / "README.md" f.write_text("# Modified\n") runner = _make_runner() result = runner.execute( "builtin/git-diff", {"repo_path": repo, "_sandbox_root": repo}, ) assert result.success, f"Failed: {result.error}" assert "Modified" in result.output["output"] print("git-diff-ok") finally: shutil.rmtree(repo, ignore_errors=True) def test_log() -> None: repo = _make_repo() try: runner = _make_runner() result = runner.execute( "builtin/git-log", {"repo_path": repo, "_sandbox_root": repo}, ) assert result.success, f"Failed: {result.error}" assert "Initial commit" in result.output["output"] print("git-log-ok") finally: shutil.rmtree(repo, ignore_errors=True) def test_blame() -> None: repo = _make_repo() try: runner = _make_runner() result = runner.execute( "builtin/git-blame", {"repo_path": repo, "path": "README.md", "_sandbox_root": repo}, ) assert result.success, f"Failed: {result.error}" assert "Test User" in result.output["output"] print("git-blame-ok") finally: shutil.rmtree(repo, ignore_errors=True) def test_traversal() -> None: repo = _make_repo() try: runner = _make_runner() result = runner.execute( "builtin/git-status", {"repo_path": "../../etc", "_sandbox_root": repo}, ) assert not result.success assert "traversal" in (result.error or "").lower() print("traversal-ok") finally: shutil.rmtree(repo, ignore_errors=True) if __name__ == "__main__": cmd = sys.argv[1] if len(sys.argv) > 1 else "status" dispatch: dict[str, Any] = { "status": test_status, "diff": test_diff, "log": test_log, "blame": test_blame, "traversal": test_traversal, } fn = dispatch.get(cmd) if fn is None: print(f"Unknown command: {cmd}", file=sys.stderr) sys.exit(1) try: fn() except Exception as exc: # pylint: disable=broad-except # Print to stdout so Robot Framework captures the error message print(f"ERROR: {type(exc).__name__}: {exc}") sys.exit(1)