Commit hooks do not fire when tags are updated

Hey there everyone,

First of all, thanks for your time and attention.

I’ve been working on getting Phabricator to update my packages on Packagist. It seems though that I’m running into an issue that is either broken on Phabricator’s end, or I am missing the point.

I have successfully created a webhook, which whenever I commit to a repository that I tagged with #packagist pushes a webhook to Packagist which then updates the package.

This sadly does not seem to work when I push a tag. The rule just doesn’t trigger and nothing happens. I thought that I’d try pushing the webhook from the “Commit Hook: Branches/Tags/Bookmarks” scenario, but this then doesn’t allow to specify a webhook to be called it just gives me the option to reject the task.

Am I doing this wrong? Am I missing something?

Instructions to reproduce

  1. Create a webhook
  2. Create a herald rule that uses the webhook and updates on commits
  3. git push --tags
  4. Nothing happens

Alternatively:

  1. Create a webhook
  2. Create a herald rule for Commit Hook: Branches/Tags/Bookmarks
  3. Can’t select a webhook from the actions

The Herald rule for “Commits” actually ignores pushes completely; it acts on each actual commit (and not necessarily in the right order).

The right tool here would be the “Commit hook: Tags” rule, which acts on the push event, but it doesn’t have the ability to send a webhook; I’m not sure if there’s any technical reason for it or if this is just an oversight.

My suspicion is that the Commit:tags rule has the webhooks disabled because (from what I gathered by looking at the code) it doesn’t work on the Phabricator objects but actually works closer to the repository level. Pushes are treated very differently from the way Commits are treated, since they appear to have no PHID. A push may lead to a commit, but it also may lead to a rejection.

I would still love to ask to enable the push webhooks, even if they did not refer to a specific commit but just included the affected repository. I’d rather have packagist updated once too often than having to manually check whether the package got pushed.

Also, in case somebody is interested, I wrote up a blog post detailing the exact process I used to create the hooks, in case anyone is interested.

This is mostly right: refs/tags/branches aren’t a Phabricator “object” today and don’t generate any transactions, so the webhook couldn’t actually send anything: there’s no Object PHID for it to reference and no Transaction PHIDs it could use to tell the receiver what happened.

Technically speaking, a push does have a PHID (corresponding to a PushEvent object, visible in the “Push Logs”) and Herald itself is acting on a sub-object with a PHID (a PushLog object, describing effects to one particular ref). Although this could be used as the object-representation of a push, it feels like it’s not really a great match for how other hooks operate: for consistency, I’d expect this hook to send users some kind of RepositoryRef object (which does not exist today as a persistent storage object) representing the affected object, not a PushLog/PushEvent object representing the specific change to the object.

An entangling concern is observed repositories. If you observe a repository on another service, we can’t tell when it receives a push in the general case, and can’t identify the user performing the push in Git or Mercurial, and obviously can’t block the push. But we could synthetically build a “push event” representing all ref changes between states we observe, and trigger notifications and webhooks based on these synthetic pushes. Although this is desirable, it doesn’t map cleanly to Herald today.

Phabricator may emit Webhooks for ref changes some day, but the path between here and there is fairly complex and there are no outstanding customer request for this so it’s likely some ways away.

That’s what I feared that you’d say. How unfeasible is it for me to define some kind of custom action that just, let’s say, invokes a URL without any PHID, authentication or similar? Just the ID of the repo that is receiving the push?

The complexity in the “Call webhook” implementation is that it queues the call, executes it asynchronously in the daemons, and retries on failure. An action with similar properties is moderately difficult to write, although most components are modular and it could be largely copied from the Webhook implementation.

If you’re comfortable with a synchronous call that doesn’t retry, you only need about 50 lines of code. Subclass HeraldAction and follow HeraldCallWebhookAction for a general outline, but have applyEffect() use HTTPSFuture directly to make a HTTP request.