@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Document how webhooks work

Summary: Depends on D19049. Ref T11330. Adds some documentation for webhooks.

Test Plan: Read the documentation and found it to be exceptionally accurate and helpful.

Maniphest Tasks: T11330

Differential Revision: https://secure.phabricator.com/D19050

+219 -1
+4
src/applications/herald/application/PhabricatorHeraldApplication.php
··· 28 28 'name' => pht('Herald User Guide'), 29 29 'href' => PhabricatorEnv::getDoclink('Herald User Guide'), 30 30 ), 31 + array( 32 + 'name' => pht('User Guide: Webhooks'), 33 + 'href' => PhabricatorEnv::getDoclink('User Guide: Webhooks'), 34 + ), 31 35 ); 32 36 } 33 37
+1
src/applications/herald/worker/HeraldWebhookWorker.php
··· 155 155 'test' => $request->getIsTestAction(), 156 156 'silent' => $request->getIsSilentAction(), 157 157 'secure' => $request->getIsSecureAction(), 158 + 'epoch' => (int)$request->getDateCreated(), 158 159 ), 159 160 'transactions' => $xaction_data, 160 161 );
+1 -1
src/applications/transactions/bulk/PhabricatorBulkEngine.php
··· 377 377 ''))) 378 378 ->appendChild( 379 379 id(new AphrontFormSubmitControl()) 380 - ->setValue(pht('Apply Bulk Edit')) 380 + ->setValue(pht('Continue')) 381 381 ->addCancelButton($cancel_uri)); 382 382 } 383 383
+1
src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php
··· 4290 4290 ->setObjectPHID($object->getPHID()) 4291 4291 ->setTransactionPHIDs(mpull($xactions, 'getPHID')) 4292 4292 ->setTriggerPHIDs($trigger_phids) 4293 + ->setRetryMode(HeraldWebhookRequest::RETRY_FOREVER) 4293 4294 ->setIsSilentAction((bool)$this->getIsSilent()) 4294 4295 ->setIsSecureAction((bool)$this->getMustEncrypt()) 4295 4296 ->save();
+212
src/docs/user/userguide/webhooks.diviner
··· 1 + @title User Guide: Webhooks 2 + @group userguide 3 + 4 + Guide to configuring webhooks. 5 + 6 + 7 + Overview 8 + ======== 9 + 10 + If you'd like to react to events in Phabricator or publish them into external 11 + systems, you can configure webhooks. 12 + 13 + Configure webhooks in {nav Herald > Webhooks}. Users must have the 14 + "Can Create Webhooks" permission to create new webhooks. 15 + 16 + 17 + Triggering Hooks 18 + ================ 19 + 20 + Webhooks can be triggered in two ways: 21 + 22 + - Set the hook mode to **Firehose**. In this mode, your hook will be called 23 + for every event. 24 + - Set the hook mode to **Enabled**, then write Herald rules which use the 25 + **Call webhooks** action to choose when the hook is called. This allows 26 + you to choose a narrower range of events to be notified about. 27 + 28 + 29 + Testing Hooks 30 + ============= 31 + 32 + To test a webhook, use {nav New Test Request} from the web interface. 33 + 34 + You can also use the command-line tool, which supports a few additional 35 + options: 36 + 37 + ``` 38 + phabricator/ $ ./bin/webhook call --id 42 --object D123 39 + ``` 40 + 41 + You can use a tool like [[ https://requestb.in | RequestBin ]] to inspect 42 + the headers and payload for calls to hooks. 43 + 44 + 45 + Verifying Requests 46 + ================== 47 + 48 + When your webhook callback URI receives a request, it didn't necessarily come 49 + from Phabricator. An attacker or mischievous user can normally call your hook 50 + directly and pretend to be notifying you of an event. 51 + 52 + To verify that the request is authentic, first retrieve the webhook key from 53 + the web UI with {nav View HMAC Key}. This is a shared secret which will let you 54 + verify that Phabricator originated a request. 55 + 56 + When you receive a request, compute the SHA256 HMAC value of the request body 57 + using the HMAC key as the key. The value should match the value in the 58 + `X-Phabricator-Webhook-Signature` field. 59 + 60 + To compute the SHA256 HMAC of a string in PHP, do this: 61 + 62 + ```lang=php 63 + $signature = hash_hmac('sha256', $request_body, $hmac_key); 64 + ``` 65 + 66 + To compute the SHA256 HMAC of a string in Python, do this: 67 + 68 + ```lang=python 69 + from subprocess import check_output 70 + 71 + signature = check_output( 72 + [ 73 + "php", 74 + "-r", 75 + "echo hash_hmac('sha256', $argv[1], $argv[2]);", 76 + "--", 77 + request_body, 78 + hmac_key 79 + ]) 80 + ``` 81 + 82 + Other languages often provide similar support. 83 + 84 + If you somehow disclose the key by accident, use {nav Regenerate HMAC Key} to 85 + throw it away and generate a new one. 86 + 87 + 88 + Request Format 89 + ============== 90 + 91 + Webhook callbacks are POST requests with a JSON payload in the body. The 92 + payload looks like this: 93 + 94 + ```lang=json 95 + { 96 + "object": { 97 + "type": "TASK", 98 + "phid": "PHID-TASK-abcd..." 99 + }, 100 + "triggers": [ 101 + { 102 + "phid": "PHID-HRUL-abcd..." 103 + } 104 + ], 105 + "action": { 106 + "test": false, 107 + "silent": false, 108 + "secure": false, 109 + "epoch": 12345 110 + }, 111 + "transactions": [ 112 + { 113 + "phid": "PHID-XACT-TASK-abcd..." 114 + } 115 + ] 116 + } 117 + ``` 118 + 119 + The **object** map describes the object which was edited. 120 + 121 + The **triggers** are a list of reasons why the hook was called. When the hook 122 + is triggered by Herald rules, the specific rules which triggered the call will 123 + be listed. For firehose rules, the rule itself will be listed as the trigger. 124 + For test calls, the user making the request will be listed as a trigger. 125 + 126 + The **action** map has metadata about the action: 127 + 128 + - `test` This was a test call from the web UI or console. 129 + - `silent` This is a silent edit which won't send mail or notifications in 130 + Phabricator. If your hook is doing something like copying events into 131 + a chatroom, it may want to respect this flag. 132 + - `secure` Details about this object should only be transmitted over 133 + secure channels. Your hook may want to respect this flag. 134 + - `epoch` The epoch timestamp when the callback was queued. 135 + 136 + The **transactions** list contains information about the actual changes which 137 + triggered the callback. 138 + 139 + 140 + Responding to Requests 141 + ====================== 142 + 143 + Although trivial hooks may not need any more information than this to act, the 144 + information conveyed in the hook body is a minimum set of pointers to relevant 145 + data and likely insufficient for more complex hooks. 146 + 147 + Complex hooks should expect to react to receiving a request by making API 148 + calls to Conduit to retrieve additional information about the object and 149 + transactions. 150 + 151 + Hooks that are interested in reading object state should generally make a call 152 + to a method like `maniphest.search` or `differential.revision.search` using 153 + the PHID from the `object` field to retrieve full details about the object 154 + state. 155 + 156 + Hooks that are interested in changes should generally make a call to 157 + `transaction.search`, passing the transaction PHIDs as a constraint to retrieve 158 + details about the transactions. 159 + 160 + The `phid.query` method can also be used to retrieve generic information about 161 + a list of objects. 162 + 163 + 164 + Retries and Rate Limiting 165 + ========================= 166 + 167 + Test requests are never retried: they execute exactly once. 168 + 169 + Live requests are automatically retried. If your endpoint does not return a 170 + HTTP 2XX response, the request will be retried regularly until it suceeds. 171 + 172 + Retries will continue until the request succeeds or is garbage collected. By 173 + default, this is after 7 days. 174 + 175 + If a webhook is disabled, outstanding queued requests will be failed 176 + permanently. Activity which occurs while it is disabled will never be sent to 177 + the callback URI. (Disabling a hook does not "pause" it so that it can be 178 + "resumed" later and pick back up where it left off in the event stream.) 179 + 180 + If a webhook encounters a significant number of errors in a short period of 181 + time, the webhook will be paused for a few minutes before additional requests 182 + are made. The web UI shows a warning indicator when a hook is paused because of 183 + errors. 184 + 185 + Hook requests time out after 10 seconds. Consider offloading response handling 186 + to some kind of worker queue if you expect to routinely require more than 10 187 + seconds to respond to requests. 188 + 189 + Hook callbacks are single-threaded: you will never receive more than one 190 + simultaneous call to the same webhook from Phabricator. If you have a firehose 191 + hook on an active install, it may be important to respond to requests quickly 192 + to avoid accumulating a backlog. 193 + 194 + Callbacks may be invoked out-of-order. You should not assume that the order 195 + you receive requests in is chronological order. If your hook is order-dependent, 196 + you can ignore the transactions in the callback and use `transaction.search` to 197 + retrieve a consistent list of ordered changes to the object. 198 + 199 + Callbacks may be delayed for an arbitrarily long amount of time, up to the 200 + garbage collection limit. You should not assume that calls are real time. If 201 + your hook is doing something time-sensitive, you can measure the delivery delay 202 + by comparing the current time to the `epoch` value in the `action` field and 203 + ignoring old actions or handling them in some special way. 204 + 205 + 206 + Next Steps 207 + ========== 208 + 209 + Continue by: 210 + 211 + - learning more about Herald with @{article:Herald User Guide}; or 212 + - interacting with the Conduit API with @{article:Conduit API Overview}.