Publish curated ITWorx_MCP_Hub source from 7fde2770ba344c684b7e7a6b74f763dc19e7c560
This commit is contained in:
1 parent
18cf749bf5
commit
89703431af
11 files changed
+1247
-114
No files matched your search
+148
-49
@@ -1900,9 +1900,12 @@ class GiteaConnector:
|
||||
"status": str(item.get("status", ""))[:32],
|
||||
"conclusion": str(item.get("conclusion", ""))[:32],
|
||||
"event": str(item.get("event", ""))[:64],
|
||||
"headBranch": str(item.get("head_branch", ""))[:300],
|
||||
"headBranch": str("" if item.get("head_branch") is None else item["head_branch"])[:300],
|
||||
"headSha": str(item.get("head_sha", ""))[:64],
|
||||
"workflowId": str(item.get("workflow_id", ""))[:2_048],
|
||||
"workflowId": str(item.get("workflow_id") or "")[:2_048],
|
||||
"workflowPath": str(item.get("path") or "")[:2_048],
|
||||
"runNumber": max(int(item.get("run_number", item.get("id", 0))), 0),
|
||||
"runAttempt": max(int(item.get("run_attempt", 0)), 0),
|
||||
"displayTitle": safe_snippet(str(item.get("display_title", "")), max_bytes=500),
|
||||
"createdAt": str(item.get("created_at", ""))[:64],
|
||||
"updatedAt": str(item.get("updated_at", ""))[:64],
|
||||
@@ -1932,14 +1935,33 @@ class GiteaConnector:
|
||||
identities = cls._workflow_identity_values(workflow)
|
||||
if not identities:
|
||||
return []
|
||||
if not any(str(item.get("workflow_id", "")).strip() for item in runs):
|
||||
return runs if allow_legacy_without_workflow_id else []
|
||||
return [
|
||||
item
|
||||
for item in runs
|
||||
if str(item.get("workflow_id", "")).strip().casefold() in identities
|
||||
or str(item.get("workflow_id", "")).strip().casefold().rsplit("/", 1)[-1] in identities
|
||||
]
|
||||
output: list[dict[str, Any]] = []
|
||||
for item in runs:
|
||||
raw_path = item.get("path")
|
||||
workflow_id = str(item.get("workflow_id") or "").strip().casefold()
|
||||
if raw_path is not None:
|
||||
if not isinstance(raw_path, str) or not raw_path or len(raw_path) > 512:
|
||||
continue
|
||||
parts = raw_path.split("@")
|
||||
if len(parts) > 2 or parts[0].casefold() not in identities:
|
||||
continue
|
||||
if len(parts) == 2 and not re.fullmatch(
|
||||
r"refs/(?:pull/[1-9][0-9]*/head|heads/[A-Za-z0-9][A-Za-z0-9._/-]*)",
|
||||
parts[1],
|
||||
):
|
||||
continue
|
||||
elif not workflow_id:
|
||||
if (
|
||||
allow_legacy_without_workflow_id
|
||||
and isinstance(item.get("head_branch"), str)
|
||||
and bool(item["head_branch"])
|
||||
):
|
||||
output.append(item)
|
||||
continue
|
||||
if workflow_id and workflow_id not in identities:
|
||||
continue
|
||||
output.append(item)
|
||||
return output
|
||||
|
||||
def _find_reusable_validation_run(
|
||||
self,
|
||||
@@ -1994,10 +2016,29 @@ class GiteaConnector:
|
||||
job_id = max(int(job.get("id", 0)), 0)
|
||||
logs = ""
|
||||
logs_truncated = False
|
||||
logs_unavailable = False
|
||||
if include_logs and job_id:
|
||||
logs, logs_truncated = self.client.action_job_logs(repository, job_id)
|
||||
filtered_logs = safe_content(logs)
|
||||
logs = filtered_logs or "[log excluded: secret-like content detected]"
|
||||
if str(job.get("status", "")).casefold() in {
|
||||
"requested",
|
||||
"queued",
|
||||
"waiting",
|
||||
"pending",
|
||||
}:
|
||||
# Gitea returns 404 before a job has an effective task/log.
|
||||
logs = "[job not started; logs unavailable]"
|
||||
logs_unavailable = True
|
||||
elif job.get("conclusion") == "skipped" and not job.get("started_at"):
|
||||
logs_unavailable = True
|
||||
else:
|
||||
try:
|
||||
logs, logs_truncated = self.client.action_job_logs(repository, job_id)
|
||||
except GiteaError as exc:
|
||||
if exc.code != "GITEA_NOT_FOUND":
|
||||
raise
|
||||
logs_unavailable = True
|
||||
else:
|
||||
filtered_logs = safe_content(logs)
|
||||
logs = filtered_logs or "[log excluded: secret-like content detected]"
|
||||
projected_jobs.append(
|
||||
{
|
||||
"id": job_id,
|
||||
@@ -2008,6 +2049,7 @@ class GiteaConnector:
|
||||
"completedAt": str(job.get("completed_at", ""))[:64],
|
||||
"logs": logs,
|
||||
"logsTruncated": logs_truncated,
|
||||
"logsUnavailable": logs_unavailable,
|
||||
}
|
||||
)
|
||||
any_truncated = any_truncated or logs_truncated
|
||||
@@ -2182,12 +2224,41 @@ class GiteaConnector:
|
||||
None,
|
||||
)
|
||||
workflow = _select_validation_workflow(self.client.action_workflows(repository))
|
||||
commit_sha = str((branch_payload.get("commit") or {}).get("id", ""))[:64]
|
||||
runs = self._runs_for_workflow(
|
||||
self.client.action_runs(repository, branch=safe_branch, page=1, limit=100), workflow
|
||||
self.client.exact_head_action_runs(
|
||||
repository,
|
||||
branch=safe_branch,
|
||||
head_sha=commit_sha,
|
||||
pull_request_number=int(pull["number"]) if pull is not None else None,
|
||||
),
|
||||
workflow,
|
||||
)
|
||||
if not runs:
|
||||
# Preserve honest stale branch history, never synthetic or current
|
||||
# contradictory PR evidence, when the exact-head inventory is empty.
|
||||
history = self.client.action_runs(repository, branch=safe_branch, page=1, limit=100)
|
||||
history = [
|
||||
item
|
||||
for item in history
|
||||
if (
|
||||
type(item.get("id")) is int
|
||||
and item["id"] > 0
|
||||
and item.get("head_branch") == safe_branch
|
||||
and isinstance(item.get("head_sha"), str)
|
||||
and re.fullmatch(r"(?:[0-9a-fA-F]{40}|[0-9a-fA-F]{64})", item["head_sha"])
|
||||
and item["head_sha"] != commit_sha
|
||||
and self.client.matches_exact_head_action_run(
|
||||
item,
|
||||
branch=safe_branch,
|
||||
head_sha=item["head_sha"],
|
||||
pull_request_number=int(pull["number"]) if pull is not None else None,
|
||||
)
|
||||
)
|
||||
]
|
||||
runs = self._runs_for_workflow(history, workflow)
|
||||
projected_runs = [self._action_run_projection(item) for item in runs]
|
||||
latest_run = projected_runs[0] if projected_runs else None
|
||||
commit_sha = str((branch_payload.get("commit") or {}).get("id", ""))[:64]
|
||||
merge_eligibility: dict[str, Any] = {
|
||||
"eligible": False,
|
||||
"headSha": commit_sha,
|
||||
@@ -2443,9 +2514,13 @@ class GiteaConnector:
|
||||
published_names = {str(item["name"]) for item in descriptors}
|
||||
handler_names = set(self._tool_handlers())
|
||||
runtime = runtime_snapshot()
|
||||
upstream = (self.write_client or self.client).upstream_compatibility()
|
||||
merge_supported = upstream["compatibility"] == "SUPPORTED"
|
||||
return {
|
||||
"server": "itworx-gitea",
|
||||
"version": self.version,
|
||||
"connectorVersion": self.version,
|
||||
"upstreamGitea": upstream,
|
||||
"buildSha": os.environ.get("GITEA_CONNECTOR_BUILD_SHA", "unknown")[:64],
|
||||
"capabilityFingerprint": hashlib.sha256(encoded).hexdigest(),
|
||||
"toolCount": len(publications),
|
||||
@@ -2470,7 +2545,14 @@ class GiteaConnector:
|
||||
"catalog": "READY" if published_names == handler_names else "DEGRADED",
|
||||
"dispatcher": "READY",
|
||||
"worker": "READY" if runtime["circuitState"] == "CLOSED" else "DEGRADED",
|
||||
"upstream_gitea": "UNVERIFIED",
|
||||
"upstream_gitea": (
|
||||
"READY"
|
||||
if merge_supported
|
||||
else "UNAVAILABLE"
|
||||
if upstream["compatibility"] == "UNAVAILABLE"
|
||||
else "UNVERIFIED"
|
||||
),
|
||||
"merge": "READY" if merge_supported and self.write_client else "UNAVAILABLE",
|
||||
"search": "READY",
|
||||
"write": "READY" if self.write_client is not None else "DISABLED",
|
||||
"actions": "READY" if self.write_client is not None else "READ_ONLY",
|
||||
@@ -2506,6 +2588,8 @@ class GiteaConnector:
|
||||
"capabilityFingerprint": capability["capabilityFingerprint"],
|
||||
"toolCount": capability["toolCount"],
|
||||
"credentialMode": "mounted-secret",
|
||||
"connectorVersion": capability["connectorVersion"],
|
||||
"upstreamGitea": capability["upstreamGitea"],
|
||||
},
|
||||
source="gitea:connection",
|
||||
)
|
||||
@@ -2533,6 +2617,13 @@ class GiteaConnector:
|
||||
"status": "PASS" if connection["connected"] else "FAIL",
|
||||
"repositoryCount": connection["repositoryCount"],
|
||||
},
|
||||
{
|
||||
"name": "upstream-merge-compatibility",
|
||||
"status": "PASS"
|
||||
if capability["upstreamGitea"]["compatibility"] == "SUPPORTED"
|
||||
else "FAIL",
|
||||
"diagnostics": capability["upstreamGitea"],
|
||||
},
|
||||
{
|
||||
"name": "write-runtime",
|
||||
"status": "PASS" if self.write_client is not None else "DISABLED",
|
||||
@@ -3930,32 +4021,24 @@ class GiteaConnector:
|
||||
):
|
||||
raise GiteaError("GITEA_PROTECTION_DRIFT", "canonical PR check is not required")
|
||||
|
||||
workflow = _select_validation_workflow(self.client.action_workflows(repository))
|
||||
safe_branch = _validate_ref(str(head.get("ref", "")))
|
||||
|
||||
def exact_runs() -> list[dict[str, Any]]:
|
||||
runs: list[dict[str, Any]] = []
|
||||
for page in range(1, 6):
|
||||
batch = self.client.repository_action_runs(repository, page=page, limit=100)
|
||||
runs.extend(batch)
|
||||
if len(batch) < 100:
|
||||
break
|
||||
return sorted(
|
||||
(
|
||||
self._action_run_projection(item)
|
||||
for item in runs
|
||||
if str(item.get("event", "")) == "pull_request"
|
||||
and str(item.get("head_sha", "")) == expected_head_sha
|
||||
and (
|
||||
not isinstance(item.get("pull_requests"), list)
|
||||
or not item["pull_requests"]
|
||||
or any(
|
||||
int(pr.get("number", 0)) == number
|
||||
for pr in item["pull_requests"]
|
||||
if isinstance(pr, dict)
|
||||
)
|
||||
)
|
||||
runs = self._runs_for_workflow(
|
||||
self.client.exact_head_action_runs(
|
||||
repository,
|
||||
branch=safe_branch,
|
||||
head_sha=expected_head_sha,
|
||||
pull_request_number=number,
|
||||
),
|
||||
key=lambda item: int(item.get("id", 0)),
|
||||
reverse=True,
|
||||
workflow,
|
||||
)
|
||||
return [
|
||||
self._action_run_projection(item)
|
||||
for item in runs
|
||||
if item.get("event") == "pull_request"
|
||||
]
|
||||
|
||||
runs = exact_runs()
|
||||
statuses = self.client.commit_statuses(repository, expected_head_sha, 1, 100)
|
||||
@@ -4337,10 +4420,16 @@ class GiteaConnector:
|
||||
"GITEA_PR_VALIDATION_REQUIRED",
|
||||
"the required status has no verifiable canonical validation run",
|
||||
)
|
||||
run = self._action_run_projection(self.client.action_run(repository, int(run_match[1])))
|
||||
raw_run = self.client.action_run(repository, int(run_match[1]))
|
||||
run = self._action_run_projection(raw_run)
|
||||
workflow = _select_validation_workflow(self.client.action_workflows(repository))
|
||||
workflow_id = str(run.get("workflowId", "")).strip().casefold()
|
||||
identities = self._workflow_identity_values(workflow or {})
|
||||
canonical_run = bool(self._runs_for_workflow([raw_run], workflow))
|
||||
canonical_run = canonical_run and self.client.matches_exact_head_action_run(
|
||||
raw_run,
|
||||
branch=str(head.get("ref", "")),
|
||||
head_sha=expected_head_sha,
|
||||
pull_request_number=number,
|
||||
)
|
||||
jobs = self.client.action_run_jobs(repository, int(run_match[1]))
|
||||
full_job = next((job for job in jobs if job.get("name") == "full"), None)
|
||||
if (
|
||||
@@ -4349,11 +4438,7 @@ class GiteaConnector:
|
||||
or str(run.get("event", "")) != "pull_request"
|
||||
or str(run.get("status", "")) != "completed"
|
||||
or str(run.get("conclusion", "")) != "success"
|
||||
or (
|
||||
workflow_id
|
||||
and workflow_id not in identities
|
||||
and workflow_id.rsplit("/", 1)[-1] not in identities
|
||||
)
|
||||
or not canonical_run
|
||||
or not isinstance(full_job, dict)
|
||||
or full_job.get("status") != "completed"
|
||||
or full_job.get("conclusion") != "success"
|
||||
@@ -4614,13 +4699,18 @@ class GiteaConnector:
|
||||
key=lambda item: str(item["name"]),
|
||||
)
|
||||
runtime = runtime_snapshot()
|
||||
upstream = (self.write_client or self.client).upstream_compatibility()
|
||||
snapshot = {
|
||||
"status": "ready",
|
||||
"component": "gitea-connector",
|
||||
"readOnly": self.write_client is None,
|
||||
"writeMode": "pr-first" if self.write_client is not None else "disabled",
|
||||
"atomicChangesets": self.changeset_workspace is not None,
|
||||
"upstream": "reachable",
|
||||
"upstream": "unavailable"
|
||||
if upstream["compatibility"] == "UNAVAILABLE"
|
||||
else "reachable",
|
||||
"connectorVersion": self.version,
|
||||
"upstreamGitea": upstream,
|
||||
"toolCount": len(publications),
|
||||
"capabilityFingerprint": hashlib.sha256(
|
||||
json.dumps(descriptors, sort_keys=True, separators=(",", ":")).encode()
|
||||
@@ -4632,7 +4722,16 @@ class GiteaConnector:
|
||||
"dispatcher": "READY",
|
||||
"worker": ("READY" if runtime["circuitState"] == "CLOSED" else "DEGRADED"),
|
||||
"session": "RESUMABLE",
|
||||
"upstream_gitea": "READY",
|
||||
"upstream_gitea": (
|
||||
"READY"
|
||||
if upstream["compatibility"] == "SUPPORTED"
|
||||
else "UNAVAILABLE"
|
||||
if upstream["compatibility"] == "UNAVAILABLE"
|
||||
else "UNVERIFIED"
|
||||
),
|
||||
"merge": "READY"
|
||||
if upstream["compatibility"] == "SUPPORTED" and self.write_client
|
||||
else "UNAVAILABLE",
|
||||
},
|
||||
}
|
||||
with self._readiness_lock:
|
||||
|
||||
Reference in new issue
Block a user