From c2a8a906d3bf1557cf45d1158d9dedd2bd814070 Mon Sep 17 00:00:00 2001 From: zhifu gao Date: Thu, 23 Jul 2026 04:30:49 +0800 Subject: [PATCH] Clarify review-gated PR mergeability (#3351) Co-authored-by: LauraGPT --- scripts/collect_growth_metrics.py | 30 +++++++++++++++++++++++++++- tests/test_collect_growth_metrics.py | 30 ++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/scripts/collect_growth_metrics.py b/scripts/collect_growth_metrics.py index 634e755fc..f4beb4674 100755 --- a/scripts/collect_growth_metrics.py +++ b/scripts/collect_growth_metrics.py @@ -551,6 +551,34 @@ def recommend_integration_action( return "inspect" +def display_mergeable_state(integration: Dict[str, Any]) -> str: + mergeable_state = integration.get("mergeable_state") + if mergeable_state and mergeable_state != "unknown": + return str(mergeable_state) + + mergeable = integration.get("mergeable") + if isinstance(mergeable, bool): + return "mergeable" if mergeable else "not mergeable" + if mergeable and str(mergeable).lower() not in {"unknown", "none"}: + return str(mergeable).lower() + + checks = integration.get("checks") or {} + next_action = integration.get("next_action") or "inspect" + has_check_blocker = bool(checks.get("failed_check_runs") or checks.get("pending_check_runs")) + if ( + checks.get("state") in {"success", "unknown"} + and not has_check_blocker + and next_action == "wait for maintainer review" + and ( + integration.get("known_review_gate_reason") + or integration.get("known_assisted_review_reason") + ) + ): + return "review-gated" + + return str(mergeable_state or mergeable or "unknown") + + 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) @@ -807,7 +835,7 @@ def format_integration_markdown(metrics: Dict[str, Any]) -> str: f"{repo_stars} | " f"{repo_forks} | " f"{integration.get('state')} | " - f"{integration.get('mergeable_state') or integration.get('mergeable')} | " + f"{display_mergeable_state(integration)} | " f"{checks.get('state')} | " f"{failed_count:,} | " f"{pending_count:,} | " diff --git a/tests/test_collect_growth_metrics.py b/tests/test_collect_growth_metrics.py index eccf25b5b..4abf49ecc 100644 --- a/tests/test_collect_growth_metrics.py +++ b/tests/test_collect_growth_metrics.py @@ -1216,6 +1216,36 @@ def test_format_integration_markdown_marks_missing_exposure_metrics_as_unavailab ) in output +def test_format_integration_markdown_marks_unknown_review_gate_as_review_gated(): + module = load_growth_metrics_module() + metrics = { + "collected_at_utc": "2026-07-02T00:00:00+00:00", + "integrations": [ + { + "pr": "punkpeye/awesome-mcp-servers#7153", + "html_url": "https://github.com/punkpeye/awesome-mcp-servers/pull/7153", + "state": "open", + "mergeable": None, + "mergeable_state": "unknown", + "repo_stars": 91_000, + "repo_forks": 13_000, + "updated_at": "2026-07-22T17:46:15Z", + "updated_age_days": 0, + "next_action": "wait for maintainer review", + "known_review_gate_reason": "Glama listing and score badge are live", + "checks": {"state": "success", "failed_check_runs": [], "pending_check_runs": []}, + } + ], + } + + output = module.format_integration_markdown(metrics) + + assert ( + "| [punkpeye/awesome-mcp-servers#7153](https://github.com/punkpeye/awesome-mcp-servers/pull/7153) | " + "91,000 | 13,000 | open | review-gated | success | 0 | 0 | 0d | wait for maintainer review | `2026-07-22T17:46:15Z` |" + ) in output + + def test_format_integration_markdown_lists_high_exposure_priorities_by_stars(): module = load_growth_metrics_module() metrics = {