feat: replace Aider with secure mini-SWE-agent worker
Some checks failed
CI / test (push) Has been cancelled
CI / test (pull_request) Has been cancelled

This commit is contained in:
Christian Meyer
2026-08-31 02:46:58 +02:00
parent 582db3a654
commit 25ed6a8439
30 changed files with 4215 additions and 2148 deletions

View File

@@ -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()