Initial curated ITWorx_MCP_Hub source from 368fba691ea8d23403b4d56b53b5ec670d7c5020
This commit is contained in:
commit
cb5be898ea
663 files changed
+82674
No files matched your search
@@ -0,0 +1,114 @@
|
||||
"""Compatibility hardening for Gitea validation discovery and request latency.
|
||||
|
||||
Some Gitea versions expose pull-request check results as commit statuses while
|
||||
returning an empty branch-filtered Actions run wrapper. The base client treats
|
||||
collections strictly; this subclass preserves that strictness while translating
|
||||
a fully-green exact-head status set into one synthetic completed validation run.
|
||||
|
||||
Large repositories can require longer than the historical 15-second client
|
||||
budget to commit files, apply changesets, or materialize a server-side squash
|
||||
merge. The resilient client therefore uses the already allowlisted 60-second
|
||||
maximum from ``GiteaSettings``. All HTTP method allowlisting, redirect handling,
|
||||
response budgets, access checks and non-forcing merge behavior remain in the
|
||||
base client and are not duplicated here.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
import httpx
|
||||
|
||||
from .gitea import GiteaClient as BaseGiteaClient
|
||||
from .gitea import GiteaError, GiteaSettings, RegisteredRepository, TokenProvider
|
||||
|
||||
GITEA_REQUEST_TIMEOUT_SECONDS = 60.0
|
||||
|
||||
|
||||
class GiteaClient(BaseGiteaClient):
|
||||
"""Gitea client with exact-head validation fallback and bounded latency."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
settings: GiteaSettings,
|
||||
token_provider: TokenProvider,
|
||||
*,
|
||||
transport: httpx.BaseTransport | None = None,
|
||||
) -> None:
|
||||
resilient_settings = settings.model_copy(
|
||||
update={"timeout_seconds": GITEA_REQUEST_TIMEOUT_SECONDS}
|
||||
)
|
||||
super().__init__(resilient_settings, token_provider, transport=transport)
|
||||
|
||||
def action_runs(
|
||||
self,
|
||||
repository: RegisteredRepository,
|
||||
*,
|
||||
branch: str,
|
||||
page: int,
|
||||
limit: int,
|
||||
) -> list[dict[str, Any]]:
|
||||
payload = self._request(
|
||||
self._path("repos", repository.owner, repository.name, "actions", "runs"),
|
||||
{"branch": branch, "page": page, "limit": limit},
|
||||
)
|
||||
if isinstance(payload, dict):
|
||||
if "workflow_runs" in payload:
|
||||
payload = payload.get("workflow_runs")
|
||||
elif "runs" in payload:
|
||||
payload = payload.get("runs")
|
||||
else:
|
||||
payload = None
|
||||
runs = self._as_list(payload)
|
||||
if runs:
|
||||
return runs
|
||||
|
||||
# Only an actually empty Actions result can fall back. Malformed
|
||||
# collections still fail above, preserving strict response validation.
|
||||
try:
|
||||
branch_payload = self.branch(repository, branch)
|
||||
except GiteaError:
|
||||
return []
|
||||
commit = branch_payload.get("commit")
|
||||
if not isinstance(commit, dict):
|
||||
return []
|
||||
head_sha = str(commit.get("id") or commit.get("sha") or "")
|
||||
if len(head_sha) != 40 or any(
|
||||
character not in "0123456789abcdefABCDEF" for character in head_sha
|
||||
):
|
||||
return []
|
||||
|
||||
statuses = self.commit_statuses(repository, head_sha, 1, 100)
|
||||
if not statuses:
|
||||
return []
|
||||
latest_by_context: dict[str, dict[str, Any]] = {}
|
||||
for item in statuses:
|
||||
status_context = str(item.get("context") or "__default__")
|
||||
previous = latest_by_context.get(status_context)
|
||||
if previous is None or str(item.get("created_at") or "") > str(
|
||||
previous.get("created_at") or ""
|
||||
):
|
||||
latest_by_context[status_context] = item
|
||||
latest_states = {
|
||||
str(item.get("status") or "").casefold() for item in latest_by_context.values()
|
||||
}
|
||||
# Gitea can omit ``head_branch`` for pull_request runs, causing the
|
||||
# branch-filtered run list above to be empty even though the exact-head
|
||||
# commit statuses are available. Skipped jobs are neutral evidence;
|
||||
# require at least one success and reject every non-terminal state.
|
||||
if "success" not in latest_states or not latest_states <= {"success", "skipped"}:
|
||||
return []
|
||||
|
||||
return [
|
||||
{
|
||||
"id": 0,
|
||||
"name": "Exact-head commit status validation",
|
||||
"status": "completed",
|
||||
"conclusion": "success",
|
||||
"event": "commit_status_fallback",
|
||||
"head_branch": branch,
|
||||
"head_sha": head_sha,
|
||||
"html_url": "",
|
||||
"validation_evidence": "commit-statuses",
|
||||
}
|
||||
]
|
||||
Reference in new issue
Block a user