This is an automated email from the ASF dual-hosted git repository.

potiuk pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new bf3400aa1e4 Resolve UNKNOWN mergeable status in auto-triage via REST 
API (#63317)
bf3400aa1e4 is described below

commit bf3400aa1e461affc89c035b2ca7cb9e232a4a28
Author: Jarek Potiuk <[email protected]>
AuthorDate: Wed Mar 11 09:49:10 2026 +0100

    Resolve UNKNOWN mergeable status in auto-triage via REST API (#63317)
    
    GitHub's GraphQL API computes mergeability lazily and often returns
    UNKNOWN. Add a phase that queries the REST API (which triggers the
    computation) for PRs with unknown status, with one retry after a
    short delay for cases where GitHub hasn't finished computing yet.
    
    Co-authored-by: Claude Opus 4.6 <[email protected]>
---
 .../src/airflow_breeze/commands/pr_commands.py     | 82 ++++++++++++++++++++++
 1 file changed, 82 insertions(+)

diff --git a/dev/breeze/src/airflow_breeze/commands/pr_commands.py 
b/dev/breeze/src/airflow_breeze/commands/pr_commands.py
index d7b6cf84b9a..d1dcee5c863 100644
--- a/dev/breeze/src/airflow_breeze/commands/pr_commands.py
+++ b/dev/breeze/src/airflow_breeze/commands/pr_commands.py
@@ -1174,6 +1174,71 @@ def _display_workflow_approval_panel(pr: PRData, 
author_profile: dict | None, pe
     console.print(Panel(info_text, title="Workflow Approval Needed", 
border_style="bright_cyan"))
 
 
+def _resolve_unknown_mergeable(token: str, github_repository: str, prs: 
list[PRData]) -> int:
+    """Resolve UNKNOWN mergeable status for PRs via REST API.
+
+    GitHub's GraphQL API computes mergeability lazily and often returns 
UNKNOWN.
+    The REST API triggers computation and returns the result. Sometimes the 
first
+    call still returns null, so we retry once after a short delay.
+
+    Returns the number of PRs whose status was resolved.
+    """
+    import time
+
+    import requests
+
+    unknown_prs = [pr for pr in prs if pr.mergeable == "UNKNOWN"]
+    if not unknown_prs:
+        return 0
+
+    resolved = 0
+    still_unknown: list[PRData] = []
+
+    for pr in unknown_prs:
+        url = 
f"https://api.github.com/repos/{github_repository}/pulls/{pr.number}";
+        response = requests.get(
+            url,
+            headers={"Authorization": f"Bearer {token}", "Accept": 
"application/vnd.github.v3+json"},
+            timeout=30,
+        )
+        if response.status_code == 200:
+            data = response.json()
+            mergeable = data.get("mergeable")
+            if mergeable is True:
+                pr.mergeable = "MERGEABLE"
+                resolved += 1
+            elif mergeable is False:
+                pr.mergeable = "CONFLICTING"
+                resolved += 1
+            else:
+                # null means GitHub hasn't computed it yet — retry later
+                still_unknown.append(pr)
+        else:
+            still_unknown.append(pr)
+
+    if still_unknown:
+        # Give GitHub a moment to compute mergeability, then retry
+        time.sleep(2)
+        for pr in still_unknown:
+            url = 
f"https://api.github.com/repos/{github_repository}/pulls/{pr.number}";
+            response = requests.get(
+                url,
+                headers={"Authorization": f"Bearer {token}", "Accept": 
"application/vnd.github.v3+json"},
+                timeout=30,
+            )
+            if response.status_code == 200:
+                data = response.json()
+                mergeable = data.get("mergeable")
+                if mergeable is True:
+                    pr.mergeable = "MERGEABLE"
+                    resolved += 1
+                elif mergeable is False:
+                    pr.mergeable = "CONFLICTING"
+                    resolved += 1
+
+    return resolved
+
+
 def _fetch_pr_diff(token: str, github_repository: str, pr_number: int) -> str 
| None:
     """Fetch the diff for a PR via GitHub REST API. Returns the diff text or 
None on failure."""
     import requests
@@ -1644,6 +1709,23 @@ def auto_triage(
                 )
                 pr.failed_checks = _fetch_failed_checks(token, 
github_repository, pr.head_sha)
 
+    # Phase 2b2: Resolve UNKNOWN mergeable status via REST API
+    unknown_count = sum(1 for pr in candidate_prs if pr.mergeable == "UNKNOWN")
+    if unknown_count:
+        get_console().print(
+            f"[info]Resolving merge conflict status for {unknown_count} "
+            f"{'PRs' if unknown_count != 1 else 'PR'} with unknown 
status...[/]"
+        )
+        resolved = _resolve_unknown_mergeable(token, github_repository, 
candidate_prs)
+        remaining = unknown_count - resolved
+        if remaining:
+            get_console().print(
+                f"  [dim]{resolved} resolved, {remaining} still unknown "
+                f"(GitHub hasn't computed mergeability yet).[/]"
+            )
+        else:
+            get_console().print(f"  [dim]All {resolved} resolved.[/]")
+
     # Phase 2c: Fetch unresolved review comment counts for candidate PRs
     if candidate_prs and run_ci:
         get_console().print(

Reply via email to