feat: replace Aider with secure mini-SWE-agent worker
This commit is contained in:
@@ -1,75 +1,74 @@
|
||||
from pathlib import Path
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
from lai_automation.config import Settings
|
||||
|
||||
|
||||
def settings(**overrides) -> Settings:
|
||||
values = {
|
||||
"database_host": "db",
|
||||
"database_port": 3306,
|
||||
"database_name": "lai",
|
||||
"database_user": "worker",
|
||||
"database_password": "secret",
|
||||
"source_repository": "https://example.test/lai.git",
|
||||
"source_branch": "main",
|
||||
"workspace_root": Path("/tmp/workspaces"),
|
||||
"mode": "dry-run",
|
||||
"allow_direct_main": False,
|
||||
"gitea_url": "https://example.test",
|
||||
"gitea_owner": "owner",
|
||||
"gitea_repository": "lai",
|
||||
"gitea_token": "",
|
||||
"gitea_username": "bot",
|
||||
"agent_command": "aider",
|
||||
"agent_model": "mistral/test",
|
||||
"test_commands": ("php artisan test",),
|
||||
"test_database_host": "test-db",
|
||||
"test_database_port": 3306,
|
||||
"test_database_name": "lai_agent_test",
|
||||
"test_database_user": "test_runner",
|
||||
"test_database_password": "test-secret",
|
||||
"test_customer_database": "customer_agent_test",
|
||||
"test_config_database": "cockpit_agent_test",
|
||||
"poll_seconds": 60,
|
||||
"max_changed_files": 12,
|
||||
"max_changed_lines": 800,
|
||||
"max_agent_attempts": 2,
|
||||
"stale_claim_minutes": 90,
|
||||
"dry_run": True,
|
||||
}
|
||||
values.update(overrides)
|
||||
return Settings(**values)
|
||||
def base_environment(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
monkeypatch.setenv(
|
||||
"SOURCE_REPOSITORY",
|
||||
"https://gitea.example.test/owner/lai.git",
|
||||
)
|
||||
monkeypatch.setenv("GITEA_URL", "https://gitea.example.test")
|
||||
monkeypatch.setenv("GITEA_OWNER", "owner")
|
||||
monkeypatch.setenv("GITEA_REPOSITORY", "lai")
|
||||
monkeypatch.setenv("GITEA_TOKEN", "secret")
|
||||
monkeypatch.setenv("MISTRAL_API_KEY", "model-secret")
|
||||
monkeypatch.setenv("TEST_DB_NAME", "lai_agent_test")
|
||||
monkeypatch.setenv("TEST_CUSTOMER_DB", "customer_agent_test")
|
||||
monkeypatch.setenv("TEST_CONFIG_DB", "config_agent_test")
|
||||
|
||||
|
||||
def test_direct_main_requires_explicit_kill_switch() -> None:
|
||||
config = settings(mode="direct-main", dry_run=False, gitea_token="token")
|
||||
with pytest.raises(ValueError, match="ALLOW_DIRECT_MAIN"):
|
||||
config.validate()
|
||||
def test_settings_load_issue_workflow_defaults(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
base_environment(monkeypatch)
|
||||
|
||||
settings = Settings.from_env()
|
||||
|
||||
assert settings.queued_label == "ai:queued"
|
||||
assert settings.running_label == "ai:running"
|
||||
assert settings.agent_model == "mistral/devstral-latest"
|
||||
assert settings.test_commands == ("npm run build", "php artisan test")
|
||||
assert settings.test_environment["DB_DATABASE"] == "lai_agent_test"
|
||||
assert settings.test_environment["ERP_DATABASE"] == "customer_agent_test"
|
||||
assert settings.test_environment["COCKPIT_CONFIG_DATABASE"] == "config_agent_test"
|
||||
assert settings.test_environment["AGENT_TEST_DB_ENABLED"] == "true"
|
||||
assert settings.test_environment["AI_MISTRAL_API_KEY"] == "test-only-placeholder"
|
||||
assert "GITEA_TOKEN" not in settings.test_environment
|
||||
assert "MISTRAL_API_KEY" not in settings.test_environment
|
||||
|
||||
|
||||
def test_pr_requires_gitea_token() -> None:
|
||||
config = settings(mode="pr", dry_run=False)
|
||||
with pytest.raises(ValueError, match="GITEA_TOKEN"):
|
||||
config.validate()
|
||||
def test_settings_reject_non_https_source(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
base_environment(monkeypatch)
|
||||
monkeypatch.setenv(
|
||||
"SOURCE_REPOSITORY",
|
||||
"http://gitea.example.test/owner/lai.git",
|
||||
)
|
||||
|
||||
with pytest.raises(ValueError, match="HTTPS"):
|
||||
Settings.from_env()
|
||||
|
||||
|
||||
def test_default_commands_initialize_disposable_laravel_schema(monkeypatch) -> None:
|
||||
monkeypatch.setenv("FAILURE_DB_PASSWORD", "failure-secret")
|
||||
monkeypatch.setenv("TEST_DB_PASSWORD", "test-secret")
|
||||
monkeypatch.delenv("TEST_COMMANDS", raising=False)
|
||||
def test_settings_reject_different_repository_host(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
base_environment(monkeypatch)
|
||||
monkeypatch.setenv(
|
||||
"SOURCE_REPOSITORY",
|
||||
"https://attacker.example/owner/lai.git",
|
||||
)
|
||||
|
||||
config = Settings.from_env()
|
||||
|
||||
assert "npm ci" in config.test_commands
|
||||
assert "npm run build" in config.test_commands
|
||||
assert "php artisan migrate:fresh --force" in config.test_commands
|
||||
assert config.test_commands[-1] == "php artisan test"
|
||||
with pytest.raises(ValueError, match="configured Gitea"):
|
||||
Settings.from_env()
|
||||
|
||||
|
||||
def test_agent_attempts_are_bounded() -> None:
|
||||
with pytest.raises(ValueError, match="MAX_AGENT_ATTEMPTS"):
|
||||
settings(max_agent_attempts=6).validate()
|
||||
def test_settings_require_isolated_test_database(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
base_environment(monkeypatch)
|
||||
monkeypatch.setenv("TEST_DB_NAME", "production")
|
||||
|
||||
settings(max_agent_attempts=5).validate()
|
||||
with pytest.raises(ValueError, match="isolated test database"):
|
||||
Settings.from_env()
|
||||
|
||||
Reference in New Issue
Block a user