|
| 1 | +import asyncio |
| 2 | + |
| 3 | +import gidgethub.routing |
| 4 | +from gidgethub.abc import GitHubAPI |
| 5 | + |
| 6 | +router = gidgethub.routing.Router() |
| 7 | + |
| 8 | +MERGE_CONFLICT_LABEL = "merge-conflict" |
| 9 | + |
| 10 | + |
| 11 | +@router.register("push") |
| 12 | +async def new_commit_pushed_to_main(event, gh: GitHubAPI, *arg, **kwargs) -> None: |
| 13 | + """If there is a new commit pushed to main, update all open PRs merge status.""" |
| 14 | + if event.data["ref"] != "refs/heads/main": |
| 15 | + return |
| 16 | + |
| 17 | + prs_to_add_conflict_label = [] |
| 18 | + prs_to_remove_conflict_label = [] |
| 19 | + |
| 20 | + after = None |
| 21 | + while True: |
| 22 | + query = """ |
| 23 | +query ($after: String) { |
| 24 | + repository(name: "cpython", owner: "python") { |
| 25 | + id |
| 26 | + pullRequests(first: 10, after: $after, states: OPEN) { |
| 27 | + nodes { |
| 28 | + id |
| 29 | + mergeable |
| 30 | + number |
| 31 | + # title |
| 32 | + # url |
| 33 | + # state |
| 34 | + labels(first: 100) { |
| 35 | + edges { |
| 36 | + node { |
| 37 | + name |
| 38 | + } |
| 39 | + } |
| 40 | + } |
| 41 | + } |
| 42 | + pageInfo { |
| 43 | + endCursor |
| 44 | + hasNextPage |
| 45 | + } |
| 46 | + } |
| 47 | + } |
| 48 | + rateLimit { |
| 49 | + remaining |
| 50 | + } |
| 51 | +} |
| 52 | +""" |
| 53 | + data = await gh.graphql(query, after=after) |
| 54 | + for pr in data["repository"]["pullRequests"]["nodes"]: |
| 55 | + has_conflict_label = MERGE_CONFLICT_LABEL in ( |
| 56 | + edge["node"]["name"] for edge in pr["labels"]["edges"] |
| 57 | + ) |
| 58 | + if pr["mergeable"] == "CONFLICTING": |
| 59 | + if not has_conflict_label: |
| 60 | + prs_to_add_conflict_label.append(pr) |
| 61 | + else: |
| 62 | + if has_conflict_label: |
| 63 | + prs_to_remove_conflict_label.append(pr) |
| 64 | + |
| 65 | + if data["rateLimit"]["remaining"] < 1000: |
| 66 | + break |
| 67 | + after = data["repository"]["pullRequests"]["pageInfo"]["endCursor"] |
| 68 | + if not data["repository"]["pullRequests"]["pageInfo"]["hasNextPage"]: |
| 69 | + break |
| 70 | + |
| 71 | + futs = [ |
| 72 | + gh.post( |
| 73 | + f"https://api.github.com/repos/python/cpython/issues/{pr['number']}/labels", |
| 74 | + data={"labels": [MERGE_CONFLICT_LABEL]}, |
| 75 | + ) |
| 76 | + for pr in prs_to_add_conflict_label |
| 77 | + ] + [ |
| 78 | + gh.delete( |
| 79 | + f"https://api.github.com/repos/python/cpython/issues/{pr['number']}/labels/{MERGE_CONFLICT_LABEL}", |
| 80 | + ) |
| 81 | + for pr in prs_to_remove_conflict_label |
| 82 | + ] |
| 83 | + for fut in asyncio.as_completed(futs): |
| 84 | + await fut |
0 commit comments