Page MenuHomePhabricator

Add possibility to block push with herald custom action
Closed, WontfixPublic

Description

Hi,

I am trying to add a custom herald action to my firm's phabricator, since what we would like to implement isn't in the herald built-in conditions. But it appears we cannot create a custom task which rejects a push.

The point of this is to reject a push if someone has too much code reviews waiting for him, for example, in order not to let him pile up too much reviews, and block someone else from the firm.

For a testing purpose, I tried to duplicate the built-in "block push with message" action (phabricator/src/applications/diffusion/herald/DiffusionBlockHeraldAction.php), changed its name, and added it to the /src/extensions directory.
Here, an error displayed on my phabricator :

Two objects (of classes "CustomHeraldAction" and "DiffusionBlockHeraldAction", descendants of ancestor class "HeraldAction") returned the same key from "getActionConstant()" ("diffusion.block"), but each object in this class map must be identified by a unique key.

Apparently, 2 actions cannot have the same ACTIONCONST (ok, why not).

I looked up where the push reject for the built-in method was done, and found this starting at line 320 (https://github.com/phacility/phabricator/blob/master/src/applications/diffusion/engine/DiffusionCommitHookEngine.php) :

$block_action = DiffusionBlockHeraldAction::ACTIONCONST;
if ($blocking_effect === null) {
  foreach ($effects as $effect) {
    if ($effect->getAction() == $block_action) {
      $blocking_effect = $effect;
      $blocked_update = $update;
      $blocking_xscript = $xscript;
      break;
    }
  }
}

The push reject only seems to trigger when the $block_action is "diffusion.block", defined in DiffusionBlockHeraldAction.php.

What do you think would be the best way to bypass this problem, and being able to create a custom action which would reject a push ?
I thought about several ways of going, so that it could be pushed to the up-stream from your side :

  • Instead of defining the $block_action this way : $block_action = DiffusionBlockHeraldAction::ACTIONCONNT; why not do a test on the syntax of the different ACTIONCONST that could be defined : For example, : if ($effect->getAction() starts with diffusion.block), then do the block.
  • Allow several actions to have the same ACTIONCONNT (I didn't study this one, I do not know if it is possible at all. Please explain me why this uniqueness way of going if you have time).
  • Maybe return the result of another action from a custom action ? If (my condition in my custom action is true) then do built-in action "Block push with message".

Please tell me if I am not clear enough.

Thank you for your help, and keep up for good work,

Yann

Event Timeline

Please describe the root problem when requesting a feature. See Contributing Feature Requests. If you aren't sure what we mean, see Describing Root Problems for some more details.

In particular:

...what we would like to implement isn't in the herald built-in conditions...

What would you like to implement?

Sorry for that, I added it at the beginning. We'd like to try to make people do their code reviews more often, and not let them pile up while writing some new features.

Or also, reject a push if someone's oldest waiting code review has been waiting for more than XXX days.

ypicard updated the task description. (Show Details)
epriestley claimed this task.

If you want to block a push when a user has too many open reviews, you need to write a new condition, not a new action. Your rule will look like this:

When:
[Pusher's open revision count is too large][is true]
Take these actions:
[Block push with message]["You have too many open revisions."]

Generally, these sorts of conditions are definitely not things we want to bring upstream, and we don't offer help with custom development. See Support Resources.

Ok, thank you for your answer.
One last thing, is it possible to implement custom conditions as it is for custom actions? I haven't read about this anywhere.

If not, is any support of adding custom conditions planned for the up-stream one day?

Thanks again

Yeah -- you're actually going to extend HeraldField. A good place to start might be DiffusionPreCommitRefPusherProjectsHeraldField. Basically:

  • Copy that.
  • Change the name and strings.
  • Make it a STANDARD_BOOL.

Then:

  • In the getHeraldFieldValue() method, grab the HookEngine and then call getViewer() to get the pusher.
  • Run a query using the pusher's PHID to see how many open revisions they have.
  • Return true if they have too many (for whatever your limit is).

Herald doesn't currently have any "is more than" or "is less than" conditions so you'll have to hard-code the limit for the moment, but that's presumably fine.

Ok thank you for these precious answers, I'm going to start this way.

Are you planning to add the "is more than" and "is less than" someday ? Just to know :)