feat: 增加 Git 标签清单策略和接口

This commit is contained in:
2026-07-20 06:45:26 +00:00
parent bc44ce8053
commit 801622904c
16 changed files with 356 additions and 3 deletions
+2
View File
@@ -13,6 +13,7 @@ def policy_row_to_dict(row) -> dict:
"valid_until": "2099-12-31T23:59:59Z",
"min_supported_version": "",
"disabled_versions": [],
"git_tags_enabled": False,
"message": "",
}
try:
@@ -27,6 +28,7 @@ def policy_row_to_dict(row) -> dict:
"valid_until": row["valid_until"],
"min_supported_version": row["min_supported_version"] or "",
"disabled_versions": disabled if isinstance(disabled, list) else [],
"git_tags_enabled": bool(row["git_tags_enabled"]) if "git_tags_enabled" in row.keys() else False,
"message": row["message"] or "",
}
+129
View File
@@ -0,0 +1,129 @@
import json
import os
import ssl
import time
import urllib.parse
import urllib.request
from datetime import datetime, timezone
from typing import Any
_CACHE: dict[str, Any] = {
"expires_at": 0.0,
"payload": None,
}
def _env_bool(name: str, default: bool) -> bool:
value = os.getenv(name)
if value is None:
return default
return value.strip().lower() in {"1", "true", "yes", "on"}
def _base_url() -> str:
return os.getenv("GITEA_BASE_URL", "https://git.alimzs.com:6443").rstrip("/")
def _token() -> str:
return os.getenv("GITEA_TOKEN", "").strip()
def _request_json(path: str) -> Any:
headers = {"Accept": "application/json"}
token = _token()
if token:
headers["Authorization"] = f"token {token}"
context = None
if not _env_bool("GITEA_VERIFY_SSL", False):
context = ssl._create_unverified_context()
req = urllib.request.Request(_base_url() + path, headers=headers)
timeout = float(os.getenv("GITEA_TIMEOUT_SEC", "12"))
with urllib.request.urlopen(req, timeout=timeout, context=context) as resp:
return json.loads(resp.read().decode("utf-8"))
def _paged(path: str) -> list[Any]:
result: list[Any] = []
page = 1
while True:
sep = "&" if "?" in path else "?"
data = _request_json(f"{path}{sep}limit=100&page={page}")
if isinstance(data, dict) and "data" in data:
data = data.get("data") or []
if not data:
break
if not isinstance(data, list):
raise RuntimeError("Gitea API returned an unexpected response.")
result.extend(data)
page += 1
return result
def _repo_list() -> list[dict[str, Any]]:
if _token():
repos = _paged("/api/v1/user/repos")
else:
repos = _paged("/api/v1/repos/search")
return [repo for repo in repos if isinstance(repo, dict) and repo.get("full_name")]
def _repo_tags(full_name: str) -> list[str]:
owner, name = full_name.split("/", 1)
owner_q = urllib.parse.quote(owner, safe="")
name_q = urllib.parse.quote(name, safe="")
tags = _paged(f"/api/v1/repos/{owner_q}/{name_q}/tags")
return [str(item.get("name")) for item in tags if isinstance(item, dict) and item.get("name")]
def format_tags_text(repositories: list[dict[str, Any]], generated_at: str) -> str:
lines = [
"# SimCAE Git Tag List",
f"# Generated at: {generated_at}",
f"# Source: {_base_url()}",
"",
]
for repo in repositories:
visibility = "private" if repo.get("private") else "public"
lines.append(f"[{repo['full_name']}]")
lines.append(f"default_branch={repo.get('default_branch') or ''}")
lines.append(f"visibility={visibility}")
tags = repo.get("tags") or []
if tags:
lines.extend(str(tag) for tag in tags)
else:
lines.append("(no tags)")
lines.append("")
return "\n".join(lines).rstrip() + "\n"
def load_git_tags(force_refresh: bool = False) -> dict[str, Any]:
ttl = max(0, int(os.getenv("GITEA_TAG_CACHE_TTL_SEC", "300") or "300"))
now = time.time()
if not force_refresh and _CACHE["payload"] and now < float(_CACHE["expires_at"]):
return _CACHE["payload"]
generated_at = datetime.now(timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
repositories: list[dict[str, Any]] = []
for repo in _repo_list():
full_name = str(repo["full_name"])
tags = _repo_tags(full_name)
repositories.append(
{
"full_name": full_name,
"private": bool(repo.get("private")),
"default_branch": repo.get("default_branch") or "",
"html_url": repo.get("html_url") or "",
"tags": tags,
}
)
payload = {
"generated_at": generated_at,
"repo_count": len(repositories),
"tag_count": sum(len(repo["tags"]) for repo in repositories),
"repositories": repositories,
"tags_text": format_tags_text(repositories, generated_at),
}
_CACHE["payload"] = payload
_CACHE["expires_at"] = now + ttl
return payload