fix: move router to api layer and add missing imports/guards

- Move APIRouter definition from instance_service.py back to tool_instances.py
  (service files should not define FastAPI routers)
- Add missing prepare_manifest_instance import in tool_instances.py
- Guard repo.remote_url before clone_repository call
- Guard tool_type.compose_template before render_compose_template call
- Rename subprocess result variable to avoid shadowing SQLAlchemy Result
- Build error message as local string to avoid None/bool type issues

Quality gates: py_compile pass, LSP clean
This commit is contained in:
Alex Blank
2026-06-05 23:11:08 +02:00
parent 51a98a0c63
commit a388a8bec9
2 changed files with 21 additions and 12 deletions
+20 -6
View File
@@ -92,6 +92,7 @@ from src.services.tool.instance_service import (
expand_glob_source,
modify_compose_file,
normalize_git_mount,
prepare_manifest_instance,
pull_repository_updates,
resolve_git_mount_mappings,
resolve_git_mounts,
@@ -104,6 +105,8 @@ from src.services.tool.instance_service import (
logger = logging.getLogger(__name__)
_event_bus = InstanceEventBus()
router = APIRouter(prefix="/projects", tags=["tool-instances"])
@router.post(
"/{project_id}/repositories/{repo_id}/instances",
@@ -257,6 +260,11 @@ async def create_instance(
ssh_key_path = os.path.join(ssh_dir, "id_ed25519")
# Clone repository
if not repo.remote_url:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Repository has no remote URL configured",
)
clone_path = clone_repository(
remote_url=repo.remote_url,
ssh_key_path=ssh_key_path,
@@ -298,16 +306,16 @@ async def create_instance(
# Create new local branch if requested
if data.clone_mode == "clone" and data.new_branch:
try:
result = subprocess.run(
git_result = subprocess.run(
["git", "-C", repo_path, "checkout", "-b", data.new_branch],
capture_output=True,
text=True,
)
if result.returncode != 0:
if git_result.returncode != 0:
logger.error(
"Failed to create branch %s: %s", data.new_branch, result.stderr
"Failed to create branch %s: %s", data.new_branch, git_result.stderr
)
raise RuntimeError(f"Failed to create branch: {result.stderr}")
raise RuntimeError(f"Failed to create branch: {git_result.stderr}")
logger.debug(
"Created local branch %s in cloned repository", data.new_branch
)
@@ -421,6 +429,11 @@ services:
"USER_ID": str(user_id),
"PROJECT_ID": str(project_id),
}
if not tool_type.compose_template:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Tool type has no compose template configured",
)
compose_content = render_compose_template(
tool_type.compose_template, variables
)
@@ -1912,9 +1925,10 @@ async def check_instance_tunnel_health(
# If container is not running, override error message
if not container_healthy:
response["error"] = f"Container is {container_info['status']}"
error_msg = f"Container is {container_info['status']}"
if container_info["exit_code"] is not None:
response["error"] += f" (exit code: {container_info['exit_code']})"
error_msg += f" (exit code: {container_info['exit_code']})"
response["error"] = error_msg
return response
@@ -71,6 +71,7 @@ from src.auth.dependencies import _get_owned_project, _get_user
logger = logging.getLogger(__name__)
_event_bus = InstanceEventBus()
async def resolve_git_mounts(
session: AsyncSession,
resolved: ResolvedProfile,
@@ -399,9 +400,6 @@ def expand_glob_source(source_path: str, repo_path: str) -> list[str]:
return results
router = APIRouter(prefix="/projects", tags=["tool-instances"])
async def validate_config_profile(
session: AsyncSession,
profile_id: str | None,
@@ -741,7 +739,6 @@ def ensure_backend_network_in_compose(compose_path: str) -> None:
logger.info("Injected backend network '%s' into compose file", network_name)
async def prepare_manifest_instance(
session: AsyncSession,
instance: ToolInstance,
@@ -882,5 +879,3 @@ async def prepare_manifest_instance(
home_dir = get_manifest_home_dir(manifest)
return image_tag, compose_content, manifest, home_dir