Skip to content

Commit d084ec0

Browse files
authored
discord router v 1.0.1 (#13)
small post-release bugfixes
1 parent bfe9f81 commit d084ec0

File tree

8 files changed

+124
-25
lines changed

8 files changed

+124
-25
lines changed

deploy/playbooks/03_app.yml

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,16 @@
2424
src: ../templates/app/docker-compose.app.yml.j2
2525
dest: ./docker-compose.yml
2626

27+
- name: Copy env file example
28+
ansible.builtin.copy:
29+
src: ../templates/app/intbot.env.example
30+
dest: intbot.env.example
31+
2732
- name: Check if the env file exists
2833
ansible.builtin.stat:
2934
path: intbot.env
3035
register: env_file
3136

32-
- name: If env file doesn't exist - copy the example
33-
ansible.builtin.copy:
34-
src: ../templates/app/intbot.env.example
35-
dest: intbot.env.example
36-
when: not env_file.stat.exists
37-
3837
- name: If the env file doesn't exist - fail with error message
3938
ansible.builtin.fail:
4039
msg: "The env file doesn't exist. Please ssh, copy the example and adjust"

intbot/core/integrations/github.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,14 +89,18 @@ class GithubDraftIssue(BaseModel):
8989
def as_discord_message(self):
9090
return self.title
9191

92+
9293
JsonType = dict[str, Any]
9394

95+
9496
class GithubWebhook:
9597
"""
9698
Base class for all the other specific types of webhooks.
9799
"""
98100

99-
def __init__(self, action: str, headers: JsonType, content: JsonType, extra: JsonType):
101+
def __init__(
102+
self, action: str, headers: JsonType, content: JsonType, extra: JsonType
103+
):
100104
self.action = action
101105
self.headers = headers
102106
self.content = content
@@ -154,7 +158,6 @@ def get_repository(self) -> GithubRepository:
154158
return GithubRepository(name="Placeholder", id="placeholder-repo")
155159

156160
def changes(self) -> dict:
157-
158161
# Early return! \o/
159162
if "changes" not in self.content:
160163
# Fallback because some webhooks just don't have changes.
@@ -218,7 +221,7 @@ def prep_github_webhook(wh: Webhook):
218221
if event == "projects_v2_item":
219222
node_id = wh.content["projects_v2_item"]["node_id"]
220223
project_item = fetch_github_project_item(node_id)
221-
wh.event = f"{event}.{wh.content['projects_v2_item']['action']}"
224+
wh.event = f"{event}.{wh.content['action']}"
222225
wh.extra = project_item
223226
wh.save()
224227
return wh
@@ -228,6 +231,7 @@ def prep_github_webhook(wh: Webhook):
228231

229232
class GithubAPIError(Exception):
230233
"""Custom exception for GithubAPI Errors"""
234+
231235
pass
232236

233237

@@ -244,7 +248,9 @@ def fetch_github_project_item(item_id: str) -> dict[str, Any]:
244248
if response.status_code == 200:
245249
return response.json()["data"]["node"]
246250
else:
247-
raise GithubAPIError(f"GitHub API error: {response.status_code} - {response.text}")
251+
raise GithubAPIError(
252+
f"GitHub API error: {response.status_code} - {response.text}"
253+
)
248254

249255

250256
def parse_github_webhook(wh: Webhook):

intbot/core/migrations/0003_added_extra_field_to_webhook.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,14 @@
44

55

66
class Migration(migrations.Migration):
7-
87
dependencies = [
9-
('core', '0002_test'),
8+
("core", "0002_test"),
109
]
1110

1211
operations = [
1312
migrations.AddField(
14-
model_name='webhook',
15-
name='extra',
13+
model_name="webhook",
14+
name="extra",
1615
field=models.JSONField(default={}),
1716
preserve_default=False,
1817
),

intbot/core/tasks.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
logger = logging.getLogger()
1010

1111

12-
1312
@task
1413
def process_webhook(wh_uuid: str):
1514
wh = Webhook.objects.get(uuid=wh_uuid)
@@ -65,10 +64,9 @@ def process_github_webhook(wh: Webhook):
6564
DiscordMessage.objects.create(
6665
channel_id=channel.channel_id,
6766
channel_name=channel.channel_name,
68-
content=f"GitHub: {parsed.message}",
67+
content=f"GitHub: {parsed.as_discord_message()}",
6968
# Mark as unsend - to be sent with the next batch
7069
sent_at=None,
7170
)
72-
wh.event = parsed.event_action
7371
wh.processed_at = timezone.now()
7472
wh.save()

intbot/intbot/settings.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ def get(name) -> str:
136136

137137
return value or ""
138138

139+
139140
# Discord
140141
# This is only needed if you end up running the bot locally, hence it
141142
# doesn't fail explicilty – however it does emit a warning.
@@ -192,7 +193,6 @@ def get(name) -> str:
192193
WEBHOOK_INTERNAL_TOKEN = "dev-token"
193194

194195

195-
196196
elif DJANGO_ENV == "test":
197197
DEBUG = True
198198
ALLOWED_HOSTS = ["127.0.0.1", "localhost"]
@@ -343,7 +343,6 @@ def get(name) -> str:
343343
]
344344

345345

346-
347346
elif DJANGO_ENV == "build":
348347
# Currently used only for collecting staticfiles in docker
349348
DEBUG = False

intbot/tests/test_bot/test_main.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
# it seems to fix the issue and also speed up the test from ~6s down to 1s.
1717
# Thanks to (@gbdlin) for help with debugging.
1818

19+
1920
@pytest.fixture(autouse=True)
2021
def fix_async_db(request):
2122
"""

intbot/tests/test_integrations/test_github.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,6 @@ def test_github_project_item_edited_event_no_changes():
179179

180180

181181
class TestGithubProjectV2Item:
182-
183182
def test_changes_for_single_select(self):
184183
parser = GithubProjectV2Item(
185184
action="changed",
@@ -249,7 +248,6 @@ def test_changes_for_unsupported_format(self):
249248
"field": "Randomfield",
250249
}
251250

252-
253251
def test_get_project_parses_project_correctly(self, github_data):
254252
wh = Webhook(
255253
meta={"X-Github-Event": "projects_v2_item"},
@@ -285,7 +283,6 @@ def test_sender_formats_sender_correctly(self, github_data):
285283
)
286284
gwh = parse_github_webhook(wh)
287285

288-
289286
assert isinstance(gwh.sender, str)
290287
assert (
291288
gwh.sender == "[@github-project-automation[bot]]("
@@ -307,10 +304,10 @@ def test_prep_github_webhook_fetches_extra_data_for_project_v2_item():
307304
wh = Webhook(
308305
meta={"X-Github-Event": "projects_v2_item"},
309306
content={
307+
"action": "random",
310308
"projects_v2_item": {
311309
"node_id": "PVTI_random_projectItemV2ID",
312-
"action": "random",
313-
}
310+
},
314311
},
315312
)
316313
node = {
@@ -354,7 +351,9 @@ def test_prep_github_webhook_reraises_exception_in_case_of_API_error():
354351

355352
respx.post(GITHUB_API_URL).mock(return_value=Response(500, json={"lol": "failed"}))
356353

357-
with pytest.raises(GithubAPIError, match='GitHub API error: 500 - {"lol":"failed"}'):
354+
with pytest.raises(
355+
GithubAPIError, match='GitHub API error: 500 - {"lol":"failed"}'
356+
):
358357
wh = prep_github_webhook(wh)
359358

360359

intbot/tests/test_tasks.py

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
import logging
2+
from django.conf import settings
23

34
import pytest
5+
import respx
6+
from core.integrations.github import GITHUB_API_URL
47
from core.models import DiscordMessage, Webhook
58
from core.tasks import process_github_webhook, process_internal_webhook, process_webhook
9+
from django.utils import timezone
610
from django_tasks.task import ResultStatus
11+
from httpx import Response
712

813

914
@pytest.mark.django_db
@@ -69,3 +74,96 @@ def test_process_github_webhook_logs_unsupported_event(caplog):
6974
caplog.records[0].message
7075
== f"Not processing Github Webhook {wh.uuid}: Event `testrandom` not supported"
7176
)
77+
78+
79+
@pytest.mark.django_db
80+
@respx.mock
81+
def test_process_github_webhook_skips_a_message_when_unsupported_project(
82+
github_data,
83+
):
84+
wh = Webhook.objects.create(
85+
source="github",
86+
event="",
87+
meta={"X-Github-Event": "projects_v2_item"},
88+
content=github_data["project_v2_item.edited"],
89+
extra={},
90+
)
91+
node = {
92+
"project": {
93+
"id": "PVT_Random_Project",
94+
"title": "Random Project",
95+
"url": "https://github.com/europython",
96+
},
97+
"content": {
98+
"__typename": "Issue",
99+
"id": "I_randomIssueID",
100+
"title": "Test Issue",
101+
"url": "https://github.com/test-issue",
102+
},
103+
}
104+
105+
mocked_response = {
106+
"data": {
107+
"node": node,
108+
}
109+
}
110+
111+
respx.post(GITHUB_API_URL).mock(return_value=Response(200, json=mocked_response))
112+
process_github_webhook(wh)
113+
114+
# Skip the message but mark as processed
115+
assert DiscordMessage.objects.count() == 0
116+
assert wh.processed_at is not None
117+
assert wh.processed_at < timezone.now()
118+
assert wh.event == "projects_v2_item.edited"
119+
120+
121+
@pytest.mark.django_db
122+
@respx.mock
123+
def test_process_github_webhook_creates_a_message_from_supported(
124+
github_data,
125+
):
126+
wh = Webhook.objects.create(
127+
source="github",
128+
event="",
129+
meta={"X-Github-Event": "projects_v2_item"},
130+
content=github_data["project_v2_item.edited"],
131+
extra={},
132+
)
133+
node = {
134+
"project": {
135+
"id": "PVT_Test_Board_Project",
136+
"title": "Test Board Project",
137+
"url": "https://github.com/europython",
138+
},
139+
"content": {
140+
"__typename": "Issue",
141+
"id": "I_randomIssueID",
142+
"title": "Test Issue",
143+
"url": "https://github.com/test-issue",
144+
},
145+
}
146+
147+
mocked_response = {
148+
"data": {
149+
"node": node,
150+
}
151+
}
152+
153+
respx.post(GITHUB_API_URL).mock(return_value=Response(200, json=mocked_response))
154+
process_github_webhook(wh)
155+
156+
dm = DiscordMessage.objects.get()
157+
assert wh.processed_at is not None
158+
assert wh.processed_at < timezone.now()
159+
assert wh.event == "projects_v2_item.edited"
160+
assert dm.channel_id == settings.DISCORD_BOARD_CHANNEL_ID
161+
assert dm.channel_name == settings.DISCORD_BOARD_CHANNEL_NAME
162+
assert dm.content == (
163+
"GitHub: [@github-project-automation[bot]]"
164+
"(https://github.com/apps/github-project-automation)"
165+
" projects_v2_item.edited **Status** of "
166+
"**[Test Issue](https://github.com/test-issue)**"
167+
" from **Done** to **In progress**"
168+
)
169+
assert dm.sent_at is None

0 commit comments

Comments
 (0)