feat: git-based agent version reference and unified outdated badge (0.20.0)

SAC reads latest RDP/ssh-monitor versions from configured git repos for outdated detection, update targets, and settings test-git.
This commit is contained in:
2026-06-20 16:25:53 +10:00
parent d820d941c1
commit f411d8f070
22 changed files with 932 additions and 45 deletions
+66 -3
View File
@@ -1,3 +1,5 @@
from datetime import datetime
from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel, Field
from sqlalchemy.orm import Session
@@ -45,6 +47,7 @@ from app.services.win_admin_settings import (
get_effective_win_admin_config,
upsert_win_admin_settings,
)
from app.services.agent_git_release import get_git_release_versions
from app.services.agent_update_settings import (
get_effective_agent_update_config,
upsert_agent_update_settings,
@@ -555,6 +558,13 @@ class AgentUpdateSettingsResponse(BaseModel):
min_rdp_version: str | None = None
min_ssh_version: str | None = None
win_agent_update_script: str | None = None
rdp_git_repo_url: str | None = None
ssh_git_repo_url: str | None = None
git_branch: str = "main"
git_latest_rdp_version: str | None = None
git_latest_ssh_version: str | None = None
git_fetched_at: datetime | None = None
git_errors: dict[str, str] = Field(default_factory=dict)
source: str = Field(description="env или db")
@@ -567,9 +577,31 @@ class AgentUpdateSettingsUpdate(BaseModel):
min_rdp_version: str | None = None
min_ssh_version: str | None = None
win_agent_update_script: str | None = None
rdp_git_repo_url: str | None = None
ssh_git_repo_url: str | None = None
git_branch: str | None = None
def _agent_update_to_response(cfg) -> AgentUpdateSettingsResponse:
class AgentGitTestResponse(BaseModel):
git_latest_rdp_version: str | None = None
git_latest_ssh_version: str | None = None
git_fetched_at: datetime | None = None
git_errors: dict[str, str] = Field(default_factory=dict)
from_cache: bool = False
def _agent_update_to_response(cfg, git_release=None) -> AgentUpdateSettingsResponse:
git_latest_rdp = None
git_latest_ssh = None
git_fetched_at = None
git_errors: dict[str, str] = {}
if git_release is not None:
from app.services.agent_update_settings import PRODUCT_RDP, PRODUCT_SSH
git_latest_rdp = git_release.versions.get(PRODUCT_RDP) or None
git_latest_ssh = git_release.versions.get(PRODUCT_SSH) or None
git_fetched_at = git_release.fetched_at
git_errors = dict(git_release.errors)
return AgentUpdateSettingsResponse(
mode=cfg.mode,
fallback_enabled=cfg.fallback_enabled,
@@ -579,6 +611,13 @@ def _agent_update_to_response(cfg) -> AgentUpdateSettingsResponse:
min_rdp_version=cfg.min_rdp_version or None,
min_ssh_version=cfg.min_ssh_version or None,
win_agent_update_script=cfg.win_agent_update_script or None,
rdp_git_repo_url=cfg.rdp_git_repo_url or None,
ssh_git_repo_url=cfg.ssh_git_repo_url or None,
git_branch=cfg.git_branch or "main",
git_latest_rdp_version=git_latest_rdp,
git_latest_ssh_version=git_latest_ssh,
git_fetched_at=git_fetched_at,
git_errors=git_errors,
source=cfg.source,
)
@@ -588,7 +627,9 @@ def get_agent_update_settings(
db: Session = Depends(get_db),
_user=Depends(require_admin),
) -> AgentUpdateSettingsResponse:
return _agent_update_to_response(get_effective_agent_update_config(db))
cfg = get_effective_agent_update_config(db)
git_release = get_git_release_versions(cfg, db=db)
return _agent_update_to_response(cfg, git_release)
@router.put("/agent-updates", response_model=AgentUpdateSettingsResponse)
@@ -608,7 +649,29 @@ def update_agent_update_settings(
min_rdp_version=body.min_rdp_version,
min_ssh_version=body.min_ssh_version,
win_agent_update_script=body.win_agent_update_script,
rdp_git_repo_url=body.rdp_git_repo_url,
ssh_git_repo_url=body.ssh_git_repo_url,
git_branch=body.git_branch,
)
except ValueError as exc:
raise HTTPException(status_code=422, detail=str(exc)) from exc
return _agent_update_to_response(cfg)
git_release = get_git_release_versions(cfg, db=db, force_refresh=True)
return _agent_update_to_response(cfg, git_release)
@router.post("/agent-updates/test-git", response_model=AgentGitTestResponse)
def test_agent_git_release(
db: Session = Depends(get_db),
_user=Depends(require_admin),
) -> AgentGitTestResponse:
cfg = get_effective_agent_update_config(db)
git_release = get_git_release_versions(cfg, db=db, force_refresh=True)
from app.services.agent_update_settings import PRODUCT_RDP, PRODUCT_SSH
return AgentGitTestResponse(
git_latest_rdp_version=git_release.versions.get(PRODUCT_RDP) or None,
git_latest_ssh_version=git_release.versions.get(PRODUCT_SSH) or None,
git_fetched_at=git_release.fetched_at,
git_errors=dict(git_release.errors),
from_cache=git_release.from_cache,
)