| import os |
| import subprocess |
| from pathlib import Path |
|
|
| from fastapi.testclient import TestClient |
|
|
| from hey_robo.codex_relay import RelaySettings, create_app |
|
|
|
|
| def _git(args, cwd: Path): |
| return subprocess.run(["git", *args], cwd=cwd, check=True, capture_output=True, text=True) |
|
|
|
|
| def test_codex_relay_creates_branch_before_running_codex(tmp_path, monkeypatch): |
| """Create a codex branch before invoking the configured Codex binary.""" |
| workspace = tmp_path / "workspace" |
| workspace.mkdir() |
| _git(["init"], workspace) |
| _git(["config", "user.email", "test@example.com"], workspace) |
| _git(["config", "user.name", "Test User"], workspace) |
| (workspace / "README.md").write_text("hello\n", encoding="utf-8") |
| _git(["add", "README.md"], workspace) |
| _git(["commit", "-m", "init"], workspace) |
|
|
| fake_codex = tmp_path / "codex" |
| fake_codex.write_text("#!/bin/sh\necho '{\"type\":\"assistant\",\"message\":\"done\"}'\n", encoding="utf-8") |
| fake_codex.chmod(0o755) |
|
|
| settings = RelaySettings( |
| token="secret", |
| workspaces={"current": workspace}, |
| codex_binary=str(fake_codex), |
| task_log_dir=tmp_path / "logs", |
| ) |
| client = TestClient(create_app(settings)) |
|
|
| response = client.post( |
| "/tasks", |
| headers={"Authorization": "Bearer secret"}, |
| json={"workspace_id": "current", "task": "Update README"}, |
| ) |
|
|
| assert response.status_code == 200 |
| task_id = response.json()["task_id"] |
| task = client.get(f"/tasks/{task_id}", headers={"Authorization": "Bearer secret"}).json() |
| assert task["state"] == "succeeded" |
| assert task["branch_name"].startswith("codex/hey-robo-") |
|
|
| branch = _git(["branch", "--show-current"], workspace).stdout.strip() |
| assert branch == task["branch_name"] |
|
|
|
|
| def test_codex_relay_rejects_dirty_workspace(tmp_path): |
| """Reject automated edits when the target workspace is dirty.""" |
| workspace = tmp_path / "workspace" |
| workspace.mkdir() |
| _git(["init"], workspace) |
| _git(["config", "user.email", "test@example.com"], workspace) |
| _git(["config", "user.name", "Test User"], workspace) |
| (workspace / "README.md").write_text("hello\n", encoding="utf-8") |
| _git(["add", "README.md"], workspace) |
| _git(["commit", "-m", "init"], workspace) |
| (workspace / "README.md").write_text("dirty\n", encoding="utf-8") |
|
|
| settings = RelaySettings( |
| token="secret", |
| workspaces={"current": workspace}, |
| codex_binary=os.devnull, |
| task_log_dir=tmp_path / "logs", |
| ) |
| client = TestClient(create_app(settings)) |
|
|
| response = client.post( |
| "/tasks", |
| headers={"Authorization": "Bearer secret"}, |
| json={"workspace_id": "current", "task": "Update README"}, |
| ) |
|
|
| task_id = response.json()["task_id"] |
| task = client.get(f"/tasks/{task_id}", headers={"Authorization": "Bearer secret"}).json() |
| assert task["state"] == "failed" |
| assert "uncommitted changes" in task["error"] |
|
|