Dispatch GitHub App webhook events to handlers.
Review Request #15335 — Created Sept. 24, 2026 and updated
Previously, the GitHub App webhook view only handled installation related
events and ignored all others. This change makes the view pass events to all
the registered handlers that support them, with the core of the view still
handling installation events.Exceptions raised from handlers are logged and we always respond with a HTTP
204 so that the webhook is considered healthy. We add the same logging to our
existing signature and payload verification exception paths, and exceptions
raised during the handling of installation events.This also adds
find_repository_for_installation()which matches by owner
and name against the repositories connected through the installation
(excluding archived ones), to pass the repository to the webhook handler.
- Ran unit tests.
- Used in the Pull Request integration work.
| Summary | ID |
|---|---|
| 43d3094a939ab2e0552eaa862096e3c88d3417ff |
| Description | From | Last Updated |
|---|---|---|
|
I don't know that we need this comment. Imports inside methods are always because of this. |
|
|
|
This seems like something we should definitely get in before we ship. |
|
|
|
We can check the account owner first by comparing it to the account: if owner.lower() != account.username.lower(): return None for … |
|
|
|
I'm about to land my update for github owner/name. Can you update this to use that? |
|
|
|
If an extension registered for an event without an installation object, every delivery would get a 400 error and GitHub … |
|
|
|
Add a comma after "ones" |
|
|
|
A generated ID looks real in logs but matches nothing in GitHub's delivery history. An empty string or clearly fake … |
|
|
|
Can we add a test that covers this? (AppInstallationWebhookPayload failing after the base payload succeeds) |
|
|
|
Before this, if any of our built-in handlers failed, we'd return a 500 to github, which would report a failed … |
|
|
|
Can we put a TODO in here about farming this out to an async task once we can do that? … |
|
|
|
This should go above with the other full-package imports. |
|
|
|
Can we include an assertLogs in here? |
|
|
|
Other test handlers don't use "test." in the ID. |
|
|
|
owner is already lowercase here. |
|
|
|
This isn't including the X-GitHub-Deliver header. Does this test run? |
|
-
-
-
-
We can check the account owner first by comparing it to the account:
if owner.lower() != account.username.lower(): return None for repository in account.repositories.filter(archived=False): ... if repo_name.lower() == name: return repository -
-
If an extension registered for an event without an installation object, every delivery would get a 400 error and GitHub would mark the webhook as unhealthy.
We should either specify this as
(WebhookInstallation | None) = Noneor document inBaseGitHubAppWebhookHandler.eventsthat only installation-scoped events are supported. -
-
A generated ID looks real in logs but matches nothing in GitHub's delivery history. An empty string or clearly fake value would be better.
-
Can we add a test that covers this? (
AppInstallationWebhookPayloadfailing after the base payload succeeds) -
Before this, if any of our built-in handlers failed, we'd return a 500 to github, which would report a failed delivery that an admin could trigger a retry for. Now it's logged but we return 204, so the installation status could silently stay stale.
Given that the intent is to swallow failures for third-party handlers, I think we should leave core state tracking un-wrapped and let the 500 happen.
-
Can we put a TODO in here about farming this out to an async task once we can do that? A long-running third-party handler could cause GitHub to timeout the delivery.
-
-
-
- Change Summary:
-
- Use the new
GitHub.get_repository_ids()instead of the old repo owner and name parsing methods. - Lets installation events fail and report a 500 back to GitHub.
- Use the new
- Commits:
-
Summary ID efd66f621ee9a28467273b6d0e6700156cf54daa ce5e77bc8897b9acf78f7382231969488b65ff33 - Diff:
-
Revision 2 (+1490 -68)
Checks run (2 succeeded)
- Commits:
-
Summary ID ce5e77bc8897b9acf78f7382231969488b65ff33 43d3094a939ab2e0552eaa862096e3c88d3417ff - Diff:
-
Revision 3 (+1492 -68)