Add integration status metrics (#3055)

This commit is contained in:
zhifu gao
2026-06-30 10:26:27 +08:00
committed by GitHub
parent 541b84e206
commit 8d836946cd
3 changed files with 259 additions and 5 deletions
+145 -2
View File
@@ -27,6 +27,12 @@ DEFAULT_PACKAGE = "funasr"
DEFAULT_BASELINE_STARS = 31224
DEFAULT_TARGET_ADDITIONAL_STARS = 20000
DEFAULT_TARGET_DATE = "2026-09-30"
DEFAULT_INTEGRATION_PRS = [
"huggingface/transformers#46180",
"ray-project/ray#64053",
"huggingface/optimum-intel#1801",
]
FAILED_CHECK_CONCLUSIONS = {"action_required", "cancelled", "failure", "startup_failure", "timed_out"}
def fetch_json(url: str, headers: Optional[Dict[str, str]] = None) -> Any:
@@ -68,6 +74,90 @@ def collect_github_repo_metrics(repo: str) -> Dict[str, Any]:
}
def parse_pull_request_spec(spec: str) -> tuple[str, int]:
if "#" not in spec:
raise ValueError(f"pull request spec must look like owner/repo#number: {spec}")
repo, number = spec.split("#", 1)
repo = repo.strip("/")
try:
pr_number = int(number)
except ValueError as exc:
raise ValueError(f"pull request number must be an integer: {spec}") from exc
if repo.count("/") != 1 or pr_number <= 0:
raise ValueError(f"pull request spec must look like owner/repo#number: {spec}")
return repo, pr_number
def summarize_commit_checks(repo: str, head_sha: str) -> Dict[str, Any]:
status = fetch_json(f"https://api.github.com/repos/{repo}/commits/{head_sha}/status", github_headers())
check_runs_payload = fetch_json(
f"https://api.github.com/repos/{repo}/commits/{head_sha}/check-runs?per_page=100",
github_headers(),
)
check_runs = check_runs_payload.get("check_runs", [])
failed_check_runs = []
pending_check_runs = []
for check_run in check_runs:
name = check_run.get("name")
url = check_run.get("html_url") or check_run.get("details_url")
if check_run.get("status") != "completed":
pending_check_runs.append({"name": name, "status": check_run.get("status"), "url": url})
elif check_run.get("conclusion") in FAILED_CHECK_CONCLUSIONS:
failed_check_runs.append({"name": name, "conclusion": check_run.get("conclusion"), "url": url})
status_state = status.get("state")
if failed_check_runs or status_state in {"error", "failure"}:
state = "failure"
elif pending_check_runs or status_state == "pending":
state = "pending"
elif check_runs or status.get("statuses"):
state = "success"
else:
state = "unknown"
return {
"state": state,
"commit_status_state": status_state,
"total_check_runs": check_runs_payload.get("total_count", len(check_runs)),
"failed_check_runs": failed_check_runs,
"pending_check_runs": pending_check_runs,
}
def collect_pull_request_metrics(spec: str) -> Dict[str, Any]:
repo, pr_number = parse_pull_request_spec(spec)
pull_request = fetch_json(f"https://api.github.com/repos/{repo}/pulls/{pr_number}", github_headers())
head = pull_request.get("head") or {}
base = pull_request.get("base") or {}
author = pull_request.get("user") or {}
head_sha = head.get("sha")
checks = summarize_commit_checks(repo, head_sha) if head_sha else {"state": "unknown"}
return {
"pr": f"{repo}#{pr_number}",
"repo": repo,
"number": pr_number,
"title": pull_request.get("title"),
"state": pull_request.get("state"),
"draft": pull_request.get("draft"),
"mergeable": pull_request.get("mergeable"),
"mergeable_state": pull_request.get("mergeable_state"),
"updated_at": pull_request.get("updated_at"),
"html_url": pull_request.get("html_url"),
"head_ref": head.get("ref"),
"head_sha": head_sha,
"base_ref": base.get("ref"),
"author": author.get("login"),
"checks": checks,
}
def collect_integration_metrics(prs: Sequence[str]) -> Dict[str, Any]:
return {
"collected_at_utc": dt.datetime.now(dt.timezone.utc).replace(microsecond=0).isoformat(),
"integrations": [collect_pull_request_metrics(pr) for pr in prs],
}
def collect_metrics(repo: str, package: str) -> Dict[str, Any]:
github = collect_github_repo_metrics(repo)
pypi = fetch_json(f"https://pypi.org/pypi/{package}/json", {"User-Agent": "funasr-growth-metrics"})
@@ -190,6 +280,48 @@ def format_ecosystem_markdown(metrics: Dict[str, Any]) -> str:
return "\n".join(lines) + "\n"
def format_integration_markdown(metrics: Dict[str, Any]) -> str:
lines = [
f"# FunASR External Integration Snapshot ({metrics['collected_at_utc']})",
"",
"| Pull request | State | Mergeable | Checks | Failed | Pending | Updated |",
"|---|---|---|---|---:|---:|---|",
]
for integration in metrics["integrations"]:
checks = integration.get("checks", {})
failed_count = len(checks.get("failed_check_runs") or [])
pending_count = len(checks.get("pending_check_runs") or [])
lines.append(
f"| [{integration['pr']}]({integration.get('html_url')}) | "
f"{integration.get('state')} | "
f"{integration.get('mergeable_state') or integration.get('mergeable')} | "
f"{checks.get('state')} | "
f"{failed_count:,} | "
f"{pending_count:,} | "
f"`{integration.get('updated_at')}` |"
)
lines.extend(["", "## Failed or pending checks", ""])
for integration in metrics["integrations"]:
checks = integration.get("checks", {})
failed = checks.get("failed_check_runs") or []
pending = checks.get("pending_check_runs") or []
if not failed and not pending:
continue
lines.append(f"### {integration['pr']}")
for check in failed:
url = check.get("url")
suffix = f" ({url})" if url else ""
lines.append(f"- Failed: {check.get('name')} [{check.get('conclusion')}]{suffix}")
for check in pending:
url = check.get("url")
suffix = f" ({url})" if url else ""
lines.append(f"- Pending: {check.get('name')} [{check.get('status')}]{suffix}")
lines.append("")
if lines[-1] == "## Failed or pending checks":
lines.append("")
return "\n".join(lines).rstrip() + "\n"
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(description="Collect FunASR growth metrics.")
parser.add_argument("--repo", default=DEFAULT_REPO, help="GitHub repository, e.g. modelscope/FunASR")
@@ -200,6 +332,13 @@ def parse_args() -> argparse.Namespace:
help="GitHub repositories for --ecosystem mode",
)
parser.add_argument("--ecosystem", action="store_true", help="Collect the four-repository FunASR ecosystem")
parser.add_argument("--integrations", action="store_true", help="Collect tracked external integration PRs")
parser.add_argument(
"--integration-prs",
nargs="+",
default=DEFAULT_INTEGRATION_PRS,
help="GitHub pull requests for --integrations mode, e.g. owner/repo#123",
)
parser.add_argument("--pypi-package", default=DEFAULT_PACKAGE, help="PyPI package name")
parser.add_argument("--star-goal", type=int, default=20000, help="Target GitHub star count")
parser.add_argument("--baseline-stars", type=int, default=DEFAULT_BASELINE_STARS, help="Ecosystem baseline stars")
@@ -217,7 +356,9 @@ def parse_args() -> argparse.Namespace:
def main() -> int:
args = parse_args()
try:
if args.ecosystem:
if args.integrations:
metrics = collect_integration_metrics(args.integration_prs)
elif args.ecosystem:
metrics = collect_ecosystem_metrics(
args.repos,
args.pypi_package,
@@ -227,12 +368,14 @@ def main() -> int:
)
else:
metrics = collect_metrics(args.repo, args.pypi_package)
except RuntimeError as exc:
except (RuntimeError, ValueError) as exc:
print(exc, file=sys.stderr)
return 1
if args.format == "json":
print(json.dumps(metrics, ensure_ascii=False, indent=2))
elif args.integrations:
print(format_integration_markdown(metrics), end="")
elif args.ecosystem:
print(format_ecosystem_markdown(metrics), end="")
else: