Skip to content

Commit ef76ed7

Browse files
authored
Retry failed backport due to redis ConnectionError up to 5 times (#229)
Closes python/miss-islington#228
1 parent 631c1b7 commit ef76ed7

File tree

2 files changed

+89
-14
lines changed

2 files changed

+89
-14
lines changed

miss_islington/backport_pr.py

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
import gidgethub.routing
2-
1+
import asyncio
2+
import os
33
import random
44

5-
from . import tasks
6-
from . import util
5+
import gidgethub.routing
6+
import redis
7+
8+
from . import tasks, util
79

810
EASTER_EGG = "I'm not a witch! I'm not a witch!"
911

@@ -46,7 +48,10 @@ async def backport_pr(event, gh, *args, **kwargs):
4648
thanks_to = f"Thanks @{created_by} for the PR 🌮🎉."
4749
else:
4850
thanks_to = f"Thanks @{created_by} for the PR, and @{merged_by} for merging it 🌮🎉."
49-
message = f"{thanks_to}. I'm working now to backport this PR to: {', '.join(branches)}." f"\n🐍🍒⛏🤖 {easter_egg}"
51+
message = (
52+
f"{thanks_to}. I'm working now to backport this PR to: {', '.join(branches)}."
53+
f"\n🐍🍒⛏🤖 {easter_egg}"
54+
)
5055

5156
await util.leave_comment(gh, issue_number, message)
5257

@@ -55,10 +60,38 @@ async def backport_pr(event, gh, *args, **kwargs):
5560
)
5661

5762
for branch in sorted_branches:
58-
tasks.backport_task.delay(
59-
commit_hash,
60-
branch,
61-
issue_number=issue_number,
62-
created_by=created_by,
63-
merged_by=merged_by,
63+
await kickoff_backport_task(
64+
gh, commit_hash, branch, issue_number, created_by, merged_by
6465
)
66+
67+
68+
async def kickoff_backport_task(
69+
gh, commit_hash, branch, issue_number, created_by, merged_by, retry_num=0
70+
):
71+
try:
72+
tasks.backport_task.delay(
73+
commit_hash,
74+
branch,
75+
issue_number=issue_number,
76+
created_by=created_by,
77+
merged_by=merged_by,
78+
)
79+
except redis.exceptions.ConnectionError as ce:
80+
retry_num = retry_num + 1
81+
if retry_num < 5:
82+
err_message = f"I'm having trouble backporting to `{branch}`. Reason: '`{ce}`'. Will retry in 1 minute. Retry # {retry_num}"
83+
await util.leave_comment(gh, issue_number, err_message)
84+
await asyncio.sleep(int(os.environ.get("RETRY_SLEEP_TIME", "60")))
85+
await kickoff_backport_task(
86+
gh,
87+
commit_hash,
88+
branch,
89+
issue_number,
90+
created_by,
91+
merged_by,
92+
retry_num=retry_num,
93+
)
94+
else:
95+
err_message = f"I'm still having trouble backporting after {retry_num} attempts. Please backport manually."
96+
await util.leave_comment(gh, issue_number, err_message)
97+
await util.assign_pr_to_core_dev(gh, issue_number, merged_by)

tests/test_backport_pr.py

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,23 @@
11
import os
2-
3-
42
from unittest import mock
3+
4+
import redis
55
from gidgethub import sansio
66

77
os.environ["REDIS_URL"] = "someurl"
8+
os.environ["RETRY_SLEEP_TIME"] = "1"
9+
810
from miss_islington import backport_pr
911

1012

1113
class FakeGH:
12-
def __init__(self, *, getitem=None, post=None):
14+
def __init__(self, *, getitem=None, post=None, patch=None):
1315
self._getitem_return = getitem
1416
self.getitem_url = None
1517
self.getiter_url = None
1618
self._post_return = post
19+
self._patch_return = patch
20+
self.patch_url = self.patch_data = None
1721

1822
async def getitem(self, url, url_vars={}):
1923
self.getitem_url = sansio.format_url(url, url_vars)
@@ -24,6 +28,11 @@ async def post(self, url, *, data):
2428
self.post_data = data
2529
return self._post_return
2630

31+
async def patch(self, url, *, data):
32+
self.patch_url = url
33+
self.patch_data = data
34+
return self._patch_return
35+
2736

2837
async def test_unmerged_pr_is_ignored():
2938
data = {"action": "closed", "pull_request": {"merged": False}}
@@ -206,3 +215,36 @@ async def test_easter_egg():
206215
assert "Thanks @gvanrossum for the PR" in gh.post_data["body"]
207216
assert "I'm not a witch" in gh.post_data["body"]
208217
assert gh.post_url == "/repos/python/cpython/issues/1/comments"
218+
219+
220+
async def test_backport_pr_redis_connection_error():
221+
data = {
222+
"action": "closed",
223+
"pull_request": {
224+
"merged": True,
225+
"number": 1,
226+
"merged_by": {"login": "Mariatta"},
227+
"user": {"login": "gvanrossum"},
228+
"merge_commit_sha": "f2393593c99dd2d3ab8bfab6fcc5ddee540518a9",
229+
},
230+
"repository": {
231+
"issues_url": "https://github.com/api/repos/python/cpython/issues/1"
232+
},
233+
}
234+
event = sansio.Event(data, event="pull_request", delivery_id="1")
235+
236+
getitem = {
237+
"https://github.com/api/repos/python/cpython/issues/1": {
238+
"labels_url": "https://github.com/api/repos/python/cpython/issues/1/labels{/name}"
239+
},
240+
"https://github.com/api/repos/python/cpython/issues/1/labels": [
241+
{"name": "CLA signed"},
242+
{"name": "needs backport to 3.7"},
243+
],
244+
}
245+
246+
gh = FakeGH(getitem=getitem)
247+
with mock.patch("miss_islington.tasks.backport_task.delay") as backport_delay_mock:
248+
backport_delay_mock.side_effect = redis.exceptions.ConnectionError
249+
await backport_pr.router.dispatch(event, gh)
250+
assert "trouble backporting after 5 attempts" in gh.post_data["body"]

0 commit comments

Comments
 (0)