def get_closed_prs()

in tools/release-notes-automator/generate_release_notes.py [0:0]


def get_closed_prs(repo, milestone_number):
    """
    Retrieve all closed PRs for a given repo and milestone number,
    filtered by the 'Release-Candidate' label. Handles pagination.
    Only returns PRs that are:
      - Closed and merged
      - Not linked to any issue
      - Belong to the current milestone
      - Have the "Release-Candidate" label
    """
    prs = []
    page = 1
    while True:
        url = f"https://api.github.com/repos/{repo}/pulls"
        params = {
            "state": "closed",
            "per_page": 100,
            "page": page
        }
        response = safe_github_request(url, headers=HEADERS, params=params)
        data = response.json()
        if not data:
            break
        for pr in data:
            # Only consider PRs that are closed and merged
            if pr.get("state") != "closed" or not pr.get("merged_at"):
                continue
            # Must have milestone and match the current milestone number
            pr_milestone = pr.get("milestone")
            if not pr_milestone or pr_milestone.get("number") != milestone_number:
                continue
            # Must have the "Release-Candidate" label
            pr_labels = [lbl["name"] for lbl in pr.get("labels", [])]
            if "Release-Candidate" not in pr_labels:
                continue
            # Check for linked issues via timeline events
            pr_number = pr["number"]
            events_url = f"https://api.github.com/repos/{repo}/issues/{pr_number}/events"
            events_resp = safe_github_request(events_url, headers=HEADERS)
            events = events_resp.json()
            linked_issue = any(
                e["event"] == "connected" and e.get("commit_id") is None and e.get("source", {}).get("type") == "issue"
                for e in events
            )
            if not linked_issue:
                prs.append(pr)
        page += 1
    return prs