• 
      

    Guard deletion of the GitHub App record account.

    Review Request #15194 — Created July 23, 2026 and submitted

    Information

    Review Board
    release-9.x

    Reviewers

    Installation accounts reference their hidden app-record account by
    primary key stored in JSON data rather than a database foreign key, so
    nothing at the database level stops the record from being deleted out
    from under them. Deleting it would silently break every installation of
    the app, which authenticates using the record's stored credentials.

    The django admin allows implementing a get_deleted_objects() method in
    order to allow us to prevent this.

    Testing Done:
    Ran unit tests.

    • Attempted to delete the app record and saw that it was protected.
    • Ran unit tests.
    Summary ID
    Guard deletion of the GitHub App record account.
    Installation accounts reference their hidden app-record account by primary key stored in JSON data rather than a database foreign key, so nothing at the database level stops the record from being deleted out from under them. Deleting it would silently break every installation of the app, which authenticates using the record's stored credentials. The django admin allows implementing a `get_deleted_objects()` method in order to allow us to prevent this. Testing Done: Ran unit tests.
    wmqqtrnulwzukrppwumnnmszmqprzqxp
    Description From Last Updated

    Django-stubs types this as Sequence[... | None], so we might need to handle this case.

    chipx86 chipx86

    This wraps weirdly. Can we just query for the objects above and then pass that in here?

    chipx86 chipx86

    Can we use the normal multi-line form here?

    chipx86 chipx86

    Can you put this in parens or indent to better indicate these aren't two things in the conditional?

    chipx86 chipx86

    We shouldn't have to type this.

    chipx86 chipx86

    Can we alphabetize these?

    chipx86 chipx86

    Can we alphabetize these?

    chipx86 chipx86

    Can we alphabetize these?

    chipx86 chipx86

    Can we alphabetize these?

    chipx86 chipx86

    Can we alphabetize these?

    chipx86 chipx86

    'collections.abc.Sequence' imported but unused Column: 5 Error code: F401

    reviewbot reviewbot

    'typing.ClassVar' imported but unused Column: 5 Error code: F401

    reviewbot reviewbot
    maubin
    1. Ship It!
    2. 
        
    chipx86
    1. 
        
    2. reviewboard/hostingsvcs/admin.py (Diff revision 1)
       
       
      Show all issues

      Django-stubs types this as Sequence[... | None], so we might need to handle this case.

      1. No?

        def get_deleted_objects(
            self, objs: Sequence[_ModelT] | QuerySet[_ModelT], request: HttpRequest
        ) -> tuple[list[str], dict[str, int], set[str], list[str]]: ...
        
    3. reviewboard/hostingsvcs/admin.py (Diff revision 1)
       
       
       
       
      Show all issues

      This wraps weirdly. Can we just query for the objects above and then pass that in here?

    4. Show all issues

      Can we use the normal multi-line form here?

    5. reviewboard/hostingsvcs/github/service.py (Diff revision 1)
       
       
       
      Show all issues

      Can you put this in parens or indent to better indicate these aren't two things in the conditional?

    6. Show all issues

      We shouldn't have to type this.

    7. Show all issues

      Can we alphabetize these?

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

      Can we alphabetize these?

    9. Show all issues

      Can we alphabetize these?

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

      Can we alphabetize these?

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

      Can we alphabetize these?

    12. 
        
    david
    Review request changed
    Commits:
    Summary ID
    Guard deletion of the GitHub App record account.
    Installation accounts reference their hidden app-record account by primary key stored in JSON data rather than a database foreign key, so nothing at the database level stops the record from being deleted out from under them. Deleting it would silently break every installation of the app, which authenticates using the record's stored credentials. The django admin allows implementing a `get_deleted_objects()` method in order to allow us to prevent this. Testing Done: Ran unit tests.
    wmqqtrnulwzukrppwumnnmszmqprzqxp
    Guard deletion of the GitHub App record account.
    Installation accounts reference their hidden app-record account by primary key stored in JSON data rather than a database foreign key, so nothing at the database level stops the record from being deleted out from under them. Deleting it would silently break every installation of the app, which authenticates using the record's stored credentials. The django admin allows implementing a `get_deleted_objects()` method in order to allow us to prevent this. Testing Done: Ran unit tests.
    wmqqtrnulwzukrppwumnnmszmqprzqxp

    Checks run (1 failed, 1 succeeded)

    flake8 failed.
    JSHint passed.

    flake8

    david
    david
    Review request changed
    Status:
    Completed
    Change Summary:
    Pushed to release-9.x (be176f5)