• 
      

    Add a base class for groups of actions.

    Review Request #14643 — Created Oct. 19, 2025 and submitted

    Information

    Review Board
    release-7.1.x

    Reviewers

    When actions were implemented, the only group of actions we needed were
    menus. As we begin to use action for more purposes, we need other groups
    of actions, meaning it's a good time to come up with a more general base
    class for this.

    This change introduces BaseGroupAction, which MenuAction is built
    upon. This manages a group of actions, allowing for explicit ordering
    and -- just like menus (though it would be up to an implementation how
    it wants to handle this).

    There's a JavaScript side as well, which is equivalent to what
    MenuAction was before. MenuAction is now a very thin subclass over
    GroupAction.

    For testing, our formerly registry-specific set of test action classes
    have been moved into a common module, along with some new actions for
    groups.

    On top of this, actions now have a parent registry, assigned when
    registering and unassigned when unregistering. This is primarily for
    unit test purposes, but removes the assumption of actions_registry for
    child actions.

    Unit tests pass.

    Tested all the actions in the UI to make sure they still work and
    still show the menu items in the right order.

    Summary ID
    Add a base class for groups of actions.
    When actions were implemented, the only group of actions we needed were menus. As we begin to use action for more purposes, we need other groups of actions, meaning it's a good time to come up with a more general base class for this. This change introduces `BaseGroupAction`, which `MenuAction` is built upon. This manages a group of actions, allowing for explicit ordering and `--` just like menus (though it would be up to an implementation how it wants to handle this). There's a JavaScript side as well, which is equivalent to what `MenuAction` was before. `MenuAction` is now a very thin subclass over `GroupAction`. For testing, our formerly registry-specific set of test action classes have been moved into a common module, along with some new actions for groups. On top of this, actions now have a parent registry, assigned when registering and unassigned when unregistering. This is primarily for unit test purposes, but removes the assumption of `actions_registry` for child actions.
    2fba3d9d54d6468579af923f7c99c36db3f0942c
    Description From Last Updated

    'typing.TYPE_CHECKING' imported but unused Column: 1 Error code: F401

    reviewbotreviewbot

    'django.http.HttpRequest' imported but unused Column: 1 Error code: F401

    reviewbotreviewbot

    'django.test.client.RequestFactory' imported but unused Column: 1 Error code: F401

    reviewbotreviewbot

    'reviewboard.actions.registry.ActionsRegistry' imported but unused Column: 1 Error code: F401

    reviewbotreviewbot

    'reviewboard.actions.tests.base.TestAction' imported but unused Column: 1 Error code: F401

    reviewbotreviewbot

    Should probably be "child menu IDs" -> "child action IDs"

    daviddavid

    A real exception seems better here too.

    daviddavid

    It seems like this must have changed as you iterated. A dict doesn't make sense given the usage here -- …

    daviddavid

    It seems like a real exception would be better than assert here.

    daviddavid

    Should we instead just do del ... to remove the members?

    daviddavid

    Leftover debug output.

    daviddavid

    Seems like it might be more consistent/future-proof if we did: export interface MenuActionAttrs extends GroupActionAttrs {}

    daviddavid
    Checks run (1 failed, 1 succeeded)
    flake8 failed.
    JSHint passed.

    flake8

    chipx86
    maubin
    1. Ship It!
    2. 
        
    david
    1. 
        
    2. reviewboard/actions/base.py (Diff revision 2)
       
       
      Show all issues

      Should probably be "child menu IDs" -> "child action IDs"

    3. reviewboard/actions/base.py (Diff revision 2)
       
       
       
       
       
      Show all issues

      A real exception seems better here too.

    4. reviewboard/actions/base.py (Diff revision 2)
       
       
       
       
       
       
      Show all issues

      It seems like this must have changed as you iterated. A dict doesn't make sense given the usage here -- you always set the values to True and never use them later, only using .keys(). Can you change this to use a set?

      The naming here is also confusing. Can we call it something like unprocessed_child_ids?

      1. This is effectively an ordered set. We want to quickly test for presence, but maintain order of keys.

        This gets revised with better naming later. At this stage in development, I'd rather avoid the merge conflicts for now, if you don't mind a bit of temporary naming.

    5. reviewboard/actions/registry.py (Diff revision 2)
       
       
       
       
       
      Show all issues

      It seems like a real exception would be better than assert here.

    6. reviewboard/actions/tests/test_group_action.py (Diff revision 2)
       
       
       
       
       
       
      Show all issues

      Should we instead just do del ... to remove the members?

    7. Show all issues

      Leftover debug output.

    8. Show all issues

      Seems like it might be more consistent/future-proof if we did:

      export interface MenuActionAttrs extends GroupActionAttrs {}
      
      1. Agreed, but that triggers lint errors:

        An interface declaring no members is equivalent to its supertype.

        I wouldn't mind disabling that. Happy to switch it and just ignore the warning.

      2. @typescript-eslint/no-empty-interface

      3. The newer @typescript-eslint that we'll pick up with my changes replaces this rule with a more generic one, but I can configure that to allow this when we're extending an interface. I'll get a change up for that.

    9. 
        
    chipx86
    chipx86
    david
    1. Ship It!
    2. 
        
    chipx86
    Review request changed
    Status:
    Completed
    Change Summary:
    Pushed to release-7.1.x (3222270)