Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PoC for labelling merge conflicts #530

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions bedevere/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@
from gidgethub import routing
from gidgethub import sansio

from . import backport, gh_issue, close_pr, filepaths, news, stage
from . import backport, conflict, gh_issue, close_pr, filepaths, news, stage

import sentry_sdk

router = routing.Router(backport.router, gh_issue.router, close_pr.router,
filepaths.router, news.router,
stage.router)
stage.router, conflict.router)
cache = cachetools.LRUCache(maxsize=500)

sentry_sdk.init(os.environ.get("SENTRY_DSN"))
Expand Down
84 changes: 84 additions & 0 deletions bedevere/conflict.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import asyncio

import gidgethub.routing
from gidgethub.abc import GitHubAPI

router = gidgethub.routing.Router()

MERGE_CONFLICT_LABEL = "merge-conflict"


@router.register("push")
async def new_commit_pushed_to_main(event, gh: GitHubAPI, *arg, **kwargs) -> None:
"""If there is a new commit pushed to main, update all open PRs merge status."""
if event.data["ref"] != "refs/heads/main":
return

prs_to_add_conflict_label = []
prs_to_remove_conflict_label = []

after = None
while True:
query = """
query ($after: String) {
repository(name: "cpython", owner: "python") {
id
pullRequests(first: 10, after: $after, states: OPEN) {
nodes {
id
mergeable
number
# title
# url
# state
labels(first: 100) {
edges {
node {
name
}
}
}
}
pageInfo {
endCursor
hasNextPage
}
}
}
rateLimit {
remaining
}
}
"""
data = await gh.graphql(query, after=after)
for pr in data["repository"]["pullRequests"]["nodes"]:
has_conflict_label = MERGE_CONFLICT_LABEL in (
edge["node"]["name"] for edge in pr["labels"]["edges"]
)
if pr["mergeable"] == "CONFLICTING":
if not has_conflict_label:
prs_to_add_conflict_label.append(pr)
else:
if has_conflict_label:
prs_to_remove_conflict_label.append(pr)

if data["rateLimit"]["remaining"] < 1000:
break
after = data["repository"]["pullRequests"]["pageInfo"]["endCursor"]
if not data["repository"]["pullRequests"]["pageInfo"]["hasNextPage"]:
break

futs = [
gh.post(
f"https://api.github.com/repos/python/cpython/issues/{pr['number']}/labels",
data={"labels": [MERGE_CONFLICT_LABEL]},
)
for pr in prs_to_add_conflict_label
] + [
gh.delete(
f"https://api.github.com/repos/python/cpython/issues/{pr['number']}/labels/{MERGE_CONFLICT_LABEL}",
)
for pr in prs_to_remove_conflict_label
]
for fut in asyncio.as_completed(futs):
await fut