Skip to content

Commit d25c6d3

Browse files
committed
PoC for labelling merge conflicts
1 parent b12ebac commit d25c6d3

File tree

2 files changed

+86
-2
lines changed

2 files changed

+86
-2
lines changed

bedevere/__main__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@
1111
from gidgethub import routing
1212
from gidgethub import sansio
1313

14-
from . import backport, gh_issue, close_pr, filepaths, news, stage
14+
from . import backport, conflict, gh_issue, close_pr, filepaths, news, stage
1515

1616
import sentry_sdk
1717

1818
router = routing.Router(backport.router, gh_issue.router, close_pr.router,
1919
filepaths.router, news.router,
20-
stage.router)
20+
stage.router, conflict.router)
2121
cache = cachetools.LRUCache(maxsize=500)
2222

2323
sentry_sdk.init(os.environ.get("SENTRY_DSN"))

bedevere/conflict.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
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

Comments
 (0)