Skip to content
This repository was archived by the owner on Jun 13, 2025. It is now read-only.

Commit a30a419

Browse files
Update
1 parent 40061d8 commit a30a419

File tree

2 files changed

+90
-51
lines changed

2 files changed

+90
-51
lines changed

webhook_handlers/tests/test_github.py

Lines changed: 83 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
GitHubWebhookEvents,
3232
WebhookHandlerErrorMessages,
3333
)
34-
from webhook_handlers.views.github import GithubWebhookHandler
3534

3635

3736
class MockedSubscription(object):
@@ -48,6 +47,7 @@ def __getitem__(self, key):
4847

4948
WEBHOOK_SECRET = b"testixik8qdauiab1yiffydimvi72ekq"
5049
DEFAULT_APP_ID = 1234
50+
AI_FEATURES_GH_APP_ID = 9999
5151

5252

5353
class GithubWebhookHandlerTests(APITestCase):
@@ -59,16 +59,23 @@ def inject_mocker(request, mocker):
5959
def mock_webhook_secret(self, mocker):
6060
mock_config_helper(mocker, configs={"github.webhook_secret": WEBHOOK_SECRET})
6161

62+
@pytest.fixture(autouse=True)
63+
def mock_ai_features_app_id(self, mocker):
64+
mock_config_helper(
65+
mocker, configs={"github.ai_features_app_id": AI_FEATURES_GH_APP_ID}
66+
)
67+
6268
@pytest.fixture(autouse=True)
6369
def mock_default_app_id(self, mocker):
6470
mock_config_helper(mocker, configs={"github.integration.id": DEFAULT_APP_ID})
6571

66-
def _post_event_data(self, event, data={}):
72+
def _post_event_data(self, event, data={}, app_id=DEFAULT_APP_ID):
6773
return self.client.post(
6874
reverse("github-webhook"),
6975
**{
7076
GitHubHTTPHeaders.EVENT: event,
7177
GitHubHTTPHeaders.DELIVERY_TOKEN: uuid.UUID(int=5),
78+
GitHubHTTPHeaders.HOOK_INSTALLATION_TARGET_ID: app_id,
7279
GitHubHTTPHeaders.SIGNATURE_256: "sha256="
7380
+ hmac.new(
7481
WEBHOOK_SECRET,
@@ -1422,69 +1429,97 @@ def test_repo_creation_doesnt_crash_for_forked_repo(self):
14221429

14231430
assert owner.repository_set.filter(name="testrepo").exists()
14241431

1425-
def test_check_codecov_ai_auto_enabled_reviews(self):
1426-
"""
1427-
Tests the check_codecov_ai_auto_enabled_reviews method directly
1428-
for both enabled and disabled AI PR review cases
1429-
"""
1432+
def test_check_codecov_ai_auto_enabled_reviews_enabled(self):
14301433
# Create an organization with AI PR review enabled
14311434
org_with_ai_enabled = OwnerFactory(
1432-
service=Service.GITHUB.value,
1433-
yaml={"ai_pr_review": {"auto_review": True}}
1435+
service=Service.GITHUB.value, yaml={"ai_pr_review": {"auto_review": True}}
14341436
)
1435-
1436-
# Create an organization with AI PR review disabled
1437-
org_with_ai_disabled = OwnerFactory(
1438-
service=Service.GITHUB.value,
1439-
yaml={"ai_pr_review": {"auto_review": False}}
1440-
)
1441-
1442-
# Create an organization with no AI PR review configuration
1443-
org_with_no_ai_config = OwnerFactory(
1444-
service=Service.GITHUB.value,
1445-
yaml={}
1446-
)
1447-
1448-
handler = GithubWebhookHandler()
1449-
1450-
# Test with AI PR review enabled
1451-
request = self.factory.post("/", data={"organization": {"id": org_with_ai_enabled.service_id}})
1452-
response = handler.check_codecov_ai_auto_enabled_reviews(request)
1453-
assert response.data == {"auto_review_enabled": True}
1454-
1455-
# Test with AI PR review disabled
1456-
request = self.factory.post("/", data={"organization": {"id": org_with_ai_disabled.service_id}})
1457-
response = handler.check_codecov_ai_auto_enabled_reviews(request)
1458-
assert response.data == {"auto_review_enabled": False}
1459-
1460-
# Test with no AI PR review configuration
1461-
request = self.factory.post("/", data={"organization": {"id": org_with_no_ai_config.service_id}})
1462-
response = handler.check_codecov_ai_auto_enabled_reviews(request)
1463-
assert response.data == {"auto_review_enabled": False}
1464-
1465-
def test_repo_creation_doesnt_crash_for_forked_repo(self):
1466-
owner = OwnerFactory(service=Service.GITHUB.value, integration_id=4850403)
1467-
self._post_event_data(
1468-
event=GitHubWebhookEvents.REPOSITORY,
1437+
1438+
response = self._post_event_data(
1439+
event=GitHubWebhookEvents.PULL_REQUEST,
14691440
data={
1470-
"action": "publicized",
1441+
"action": "pull_request",
14711442
"repository": {
14721443
"id": 506003,
14731444
"name": "testrepo",
14741445
"private": False,
1475-
"default_branch": "master",
1476-
"owner": {"id": owner.service_id},
1446+
"default_branch": "main",
1447+
"owner": {"id": org_with_ai_enabled.service_id},
14771448
"fork": True,
14781449
"parent": {
14791450
"name": "mainrepo",
14801451
"language": "python",
14811452
"id": 7940284,
14821453
"private": False,
1483-
"default_branch": "master",
1454+
"default_branch": "main",
14841455
"owner": {"id": 8495712939, "login": "alogin"},
14851456
},
14861457
},
14871458
},
1459+
app_id=AI_FEATURES_GH_APP_ID,
14881460
)
1461+
assert response.data == {"auto_review_enabled": True}
14891462

1490-
assert owner.repository_set.filter(name="testrepo").exists()
1463+
def test_check_codecov_ai_auto_enabled_reviews_disabled(self):
1464+
# Test with AI PR review disabled
1465+
org_with_ai_disabled = OwnerFactory(
1466+
service=Service.GITHUB.value, yaml={"ai_pr_review": {"auto_review": False}}
1467+
)
1468+
1469+
response = self._post_event_data(
1470+
event=GitHubWebhookEvents.PULL_REQUEST,
1471+
data={
1472+
"action": "pull_request",
1473+
"repository": {
1474+
"id": 506004,
1475+
"name": "testrepo2",
1476+
"private": False,
1477+
"default_branch": "main",
1478+
"owner": {"id": org_with_ai_disabled.service_id},
1479+
},
1480+
},
1481+
app_id=AI_FEATURES_GH_APP_ID,
1482+
)
1483+
assert response.data == {"auto_review_enabled": False}
1484+
1485+
def test_check_codecov_ai_auto_enabled_reviews_no_config(self):
1486+
# Test with no yaml config
1487+
org_with_no_config = OwnerFactory(service=Service.GITHUB.value, yaml={})
1488+
1489+
response = self._post_event_data(
1490+
event=GitHubWebhookEvents.PULL_REQUEST,
1491+
data={
1492+
"action": "pull_request",
1493+
"repository": {
1494+
"id": 506005,
1495+
"name": "testrepo3",
1496+
"private": False,
1497+
"default_branch": "main",
1498+
"owner": {"id": org_with_no_config.service_id},
1499+
},
1500+
},
1501+
app_id=AI_FEATURES_GH_APP_ID,
1502+
)
1503+
assert response.data == {"auto_review_enabled": False}
1504+
1505+
def test_check_codecov_ai_auto_enabled_reviews_partial_config(self):
1506+
# Test with partial yaml config
1507+
org_with_partial_config = OwnerFactory(
1508+
service=Service.GITHUB.value, yaml={"ai_pr_review": {}}
1509+
)
1510+
1511+
response = self._post_event_data(
1512+
event=GitHubWebhookEvents.PULL_REQUEST,
1513+
data={
1514+
"action": "pull_request",
1515+
"repository": {
1516+
"id": 506006,
1517+
"name": "testrepo4",
1518+
"private": False,
1519+
"default_branch": "main",
1520+
"owner": {"id": org_with_partial_config.service_id},
1521+
},
1522+
},
1523+
app_id=AI_FEATURES_GH_APP_ID,
1524+
)
1525+
assert response.data == {"auto_review_enabled": False}

webhook_handlers/views/github.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838

3939
# This should probably go somewhere where it can be easily shared
4040
regexp_ci_skip = re.compile(r"\[(ci|skip| |-){3,}\]").search
41+
AI_FEATURES_GH_APP_ID = get_config("github", "ai_features_app_id")
4142

4243

4344
class GithubWebhookHandler(APIView):
@@ -365,7 +366,10 @@ def status(self, request, *args, **kwargs):
365366
return Response()
366367

367368
def pull_request(self, request, *args, **kwargs):
368-
if request.headers.get(GitHubHTTPHeaders.HOOK_INSTALLATION_TARGET_ID):
369+
if (
370+
request.META.get(GitHubHTTPHeaders.HOOK_INSTALLATION_TARGET_ID, "")
371+
== AI_FEATURES_GH_APP_ID
372+
):
369373
return self.check_codecov_ai_auto_enabled_reviews(request)
370374

371375
repo = self._get_repo(request)
@@ -404,8 +408,9 @@ def pull_request(self, request, *args, **kwargs):
404408
def check_codecov_ai_auto_enabled_reviews(self, request):
405409
org = Owner.objects.get(
406410
service=self.service_name,
407-
service_id=request.data["organization"]["id"],
411+
service_id=request.data["repository"]["owner"]["id"],
408412
)
413+
409414
auto_review_enabled = org.yaml.get("ai_pr_review", {}).get("auto_review", False)
410415
return Response(
411416
data={
@@ -768,7 +773,6 @@ def post(self, request, *args, **kwargs):
768773
delivery=self.request.META.get(GitHubHTTPHeaders.DELIVERY_TOKEN),
769774
),
770775
)
771-
772776
self.validate_signature(request)
773777

774778
if handler := getattr(self, self.event, None):

0 commit comments

Comments
 (0)