Add integration next action metrics

Surface the recommended next action for each tracked external integration PR so growth巡检 can prioritize clean, blocked, pending, and failing upstream work.
This commit is contained in:
zhifu gao
2026-06-30 11:37:07 +08:00
committed by GitHub
parent 2e4848a4c2
commit a639beefc0
2 changed files with 66 additions and 5 deletions
+24 -2
View File
@@ -159,6 +159,26 @@ def days_since(value: Optional[str], now: dt.datetime) -> Optional[int]:
return max((now - parsed).days, 0)
def recommend_integration_action(pull_request: Dict[str, Any], checks: Dict[str, Any]) -> str:
if pull_request.get("state") != "open":
return "archive"
if pull_request.get("draft"):
return "finish draft"
check_state = checks.get("state")
if check_state == "failure":
return "fix checks"
if check_state == "pending":
return "wait for checks"
mergeable_state = pull_request.get("mergeable_state")
if check_state == "success" and mergeable_state == "clean":
return "request review"
if check_state == "success" and mergeable_state in {"blocked", "unstable"}:
return "review gate"
return "inspect"
def collect_pull_request_metrics(spec: str, now: Optional[dt.datetime] = None) -> Dict[str, Any]:
repo, pr_number = parse_pull_request_spec(spec)
now = now or dt.datetime.now(dt.timezone.utc)
@@ -180,6 +200,7 @@ def collect_pull_request_metrics(spec: str, now: Optional[dt.datetime] = None) -
"mergeable_state": pull_request.get("mergeable_state"),
"updated_at": updated_at,
"updated_age_days": days_since(updated_at, now),
"next_action": recommend_integration_action(pull_request, checks),
"html_url": pull_request.get("html_url"),
"head_ref": head.get("ref"),
"head_sha": head_sha,
@@ -373,8 +394,8 @@ 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 | Age | Updated |",
"|---|---|---|---|---:|---:|---:|---|",
"| Pull request | State | Mergeable | Checks | Failed | Pending | Age | Action | Updated |",
"|---|---|---|---|---:|---:|---:|---|---|",
]
for integration in metrics["integrations"]:
checks = integration.get("checks", {})
@@ -390,6 +411,7 @@ def format_integration_markdown(metrics: Dict[str, Any]) -> str:
f"{failed_count:,} | "
f"{pending_count:,} | "
f"{age} | "
f"{integration.get('next_action') or 'inspect'} | "
f"`{integration.get('updated_at')}` |"
)
lines.extend(["", "## Failed or pending checks", ""])
+42 -3
View File
@@ -224,6 +224,7 @@ def test_collect_integration_metrics_summarizes_pull_request_checks(monkeypatch)
integration = metrics["integrations"][0]
assert integration["pr"] == "huggingface/transformers#46180"
assert integration["title"] == "Add Fun-ASR-Nano model"
assert integration["next_action"] == "fix checks"
assert integration["updated_age_days"] == 2
assert integration["mergeable"] is True
assert integration["checks"]["state"] == "failure"
@@ -274,7 +275,43 @@ def test_format_ecosystem_markdown_includes_open_pull_requests():
assert "| [modelscope/FunASR](https://github.com/modelscope/FunASR) | 18,716 | 3,100 | 3 | 2 |" in output
def test_format_integration_markdown_includes_update_age():
def test_collect_integration_metrics_recommends_review_for_clean_success_pr(monkeypatch):
module = load_growth_metrics_module()
def fake_fetch_json(url, headers=None):
if url == "https://api.github.com/repos/infiniflow/ragflow/pulls/16473":
return {
"number": 16473,
"title": "feat(stt): add FunASR / SenseVoice provider",
"state": "open",
"draft": False,
"mergeable": True,
"mergeable_state": "clean",
"html_url": "https://github.com/infiniflow/ragflow/pull/16473",
"updated_at": "2026-06-30T03:16:39Z",
"head": {"sha": "818a295", "ref": "funasr/ragflow-15526-conflict-fix"},
"base": {"ref": "main"},
"user": {"login": "LauraGPT"},
}
if url == "https://api.github.com/repos/infiniflow/ragflow/commits/818a295/status":
return {"state": "success", "statuses": []}
if url == "https://api.github.com/repos/infiniflow/ragflow/commits/818a295/check-runs?per_page=100":
return {
"total_count": 1,
"check_runs": [
{"name": "CodeRabbit", "status": "completed", "conclusion": "success"},
],
}
raise AssertionError(f"unexpected URL: {url}")
monkeypatch.setattr(module, "fetch_json", fake_fetch_json)
metrics = module.collect_integration_metrics(["infiniflow/ragflow#16473"])
assert metrics["integrations"][0]["next_action"] == "request review"
def test_format_integration_markdown_includes_update_age_and_next_action():
module = load_growth_metrics_module()
metrics = {
"collected_at_utc": "2026-07-02T00:00:00+00:00",
@@ -286,6 +323,7 @@ def test_format_integration_markdown_includes_update_age():
"mergeable_state": "blocked",
"updated_at": "2026-06-29T23:45:57Z",
"updated_age_days": 2,
"next_action": "fix checks",
"checks": {"state": "failure", "failed_check_runs": [], "pending_check_runs": []},
}
],
@@ -293,10 +331,10 @@ def test_format_integration_markdown_includes_update_age():
output = module.format_integration_markdown(metrics)
assert "| Pull request | State | Mergeable | Checks | Failed | Pending | Age | Updated |" in output
assert "| Pull request | State | Mergeable | Checks | Failed | Pending | Age | Action | Updated |" in output
assert (
"| [huggingface/transformers#46180](https://github.com/huggingface/transformers/pull/46180) | "
"open | blocked | failure | 0 | 0 | 2d | `2026-06-29T23:45:57Z` |"
"open | blocked | failure | 0 | 0 | 2d | fix checks | `2026-06-29T23:45:57Z` |"
) in output
@@ -488,3 +526,4 @@ def test_main_outputs_integrations_json(monkeypatch):
integration = payload["integrations"][0]
assert integration["pr"] == "ray-project/ray#64053"
assert integration["checks"]["state"] == "success"
assert integration["next_action"] == "request review"