• 
      

    Dispatch GitHub App webhook events to handlers.

    Review Request #15335 — Created Sept. 24, 2026 and updated

    Information

    Review Board
    release-9.x

    Reviewers

    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
    Dispatch GitHub App webhook events to handlers.
    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.
    43d3094a939ab2e0552eaa862096e3c88d3417ff
    Description From Last Updated

    I don't know that we need this comment. Imports inside methods are always because of this.

    david david

    This seems like something we should definitely get in before we ship.

    david david

    We can check the account owner first by comparing it to the account: if owner.lower() != account.username.lower(): return None for …

    david david

    I'm about to land my update for github owner/name. Can you update this to use that?

    david david

    If an extension registered for an event without an installation object, every delivery would get a 400 error and GitHub …

    david david

    Add a comma after "ones"

    david david

    A generated ID looks real in logs but matches nothing in GitHub's delivery history. An empty string or clearly fake …

    david david

    Can we add a test that covers this? (AppInstallationWebhookPayload failing after the base payload succeeds)

    david david

    Before this, if any of our built-in handlers failed, we'd return a 500 to github, which would report a failed …

    david david

    Can we put a TODO in here about farming this out to an async task once we can do that? …

    david david

    This should go above with the other full-package imports.

    david david

    Can we include an assertLogs in here?

    david david

    Other test handlers don't use "test." in the ID.

    david david

    owner is already lowercase here.

    david david

    This isn't including the X-GitHub-Deliver header. Does this test run?

    david david
    maubin
    1. 
        
    2. I'll update this method for the changes in /r/15342/ later once they've landed.

    3. 
        
    david
    1. 
        
    2. Show all issues

      I don't know that we need this comment. Imports inside methods are always because of this.

      1. It's something that Christian has commented on for my code in the past. I agree it doesn't really add much but don't feel strongly either way.

    3. reviewboard/hostingsvcs/github/accounts.py (Diff revision 1)
       
       
       
      Show all issues

      This seems like something we should definitely get in before we ship.

      1. I'll take care of it in a separate change.

    4. reviewboard/hostingsvcs/github/accounts.py (Diff revision 1)
       
       
       
       
       
      Show all issues

      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
      
    5. reviewboard/hostingsvcs/github/accounts.py (Diff revision 1)
       
       
       
       
       
      Show all issues

      I'm about to land my update for github owner/name. Can you update this to use that?

    6. reviewboard/hostingsvcs/github/api.py (Diff revision 1)
       
       
       
       
       
       
      Show all issues

      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) = None or document in BaseGitHubAppWebhookHandler.events that only installation-scoped events are supported.

      1. Payloads will always contain an installation when the event is configured for and sent to a GitHub App. Except for the ping event, which I meant to always catch early before decoding the payload. I'll add that check in.

    7. reviewboard/hostingsvcs/github/views.py (Diff revision 1)
       
       
      Show all issues

      Add a comma after "ones"

    8. reviewboard/hostingsvcs/github/views.py (Diff revision 1)
       
       
       
      Show all issues

      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.

    9. reviewboard/hostingsvcs/github/views.py (Diff revision 1)
       
       
       
       
       
       
       
       
      Show all issues

      Can we add a test that covers this? (AppInstallationWebhookPayload failing after the base payload succeeds)

    10. reviewboard/hostingsvcs/github/views.py (Diff revision 1)
       
       
       
       
       
       
      Show all issues

      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.

    11. reviewboard/hostingsvcs/github/views.py (Diff revision 1)
       
       
       
       
       
       
       
       
       
      Show all issues

      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.

    12. Show all issues

      This should go above with the other full-package imports.

    13. reviewboard/hostingsvcs/tests/github/test_app_webhook_view.py (Diff revision 1)
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
      Show all issues

      Can we include an assertLogs in here?

    14. Show all issues

      Other test handlers don't use "test." in the ID.

    15. 
        
    maubin
    david
    1. 
        
    2. Show all issues

      owner is already lowercase here.

    3. Show all issues

      This isn't including the X-GitHub-Deliver header. Does this test run?

    4. 
        
    maubin
    Review request changed
    Commits:
    Summary ID
    Dispatch GitHub App webhook events to handlers.
    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.
    ce5e77bc8897b9acf78f7382231969488b65ff33
    Dispatch GitHub App webhook events to handlers.
    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.
    43d3094a939ab2e0552eaa862096e3c88d3417ff

    Checks run (2 succeeded)

    flake8 passed.
    JSHint passed.
    david
    1. Ship It!
    2.