diff --git a/docs/en/rst/extensions/Webhooks/index-user.rst b/docs/en/rst/extensions/Webhooks/index-user.rst new file mode 100644 index 0000000000..a3daa41617 --- /dev/null +++ b/docs/en/rst/extensions/Webhooks/index-user.rst @@ -0,0 +1,366 @@ +.. _webhooks: + +Webhooks +======== + +A webhook is a callback triggered by one or more events. When an event occurs, +Bugzilla sends an HTTP POST request to a configured URL. + +Bugzilla webhooks can be triggered when a bug is created or changed. The +webhook payload contains information about the bug and the event so another +web application can respond to it. + +For example, a webhook could: + +* Update a copy of a Bugzilla bug in another system, such as Jira. +* Send a message to a chat service, such as Matrix or Slack. + +Creating a webhook +------------------ + +The :guilabel:`Webhooks` preferences tab is available only when webhooks are +enabled and your account belongs to the group configured by the Bugzilla +administrator. + +#. Log in to your Bugzilla account. +#. Go to :guilabel:`Preferences`, then select the :guilabel:`Webhooks` tab. +#. Fill in the webhook parameters: + + Name + A descriptive name for the webhook, such as "Jira webhook for new and + updated bugs in Core::Graphics". + + URL + The URL that will receive and process the webhook. + + Events + The bug events that will trigger the webhook: + + * When a new bug is created. + * When an existing bug is modified. + * When a new attachment is created. + * When an existing attachment is modified. + * When a new comment is created. + + Filters + Bug properties that determine which bugs the webhook receives: + + Product + The product containing the bugs you want to receive. The + :guilabel:`Any` option is available only to members of a group + configured by the Bugzilla administrator. + + Component + The component containing the bugs you want to receive. Select + :guilabel:`Any` to receive bugs from every component in the product. + + API keys + If the endpoint requires authentication, you can provide a header and + API key for the endpoint. For example, for the following header:: + + Authorization: Token zQ5TSBzq7tTZMtKYq9K1ZqJMjifKx3cPL7pIGk9Q + + enter ``Authorization`` as the API Key Header and + ``Token zQ5TSBzq7tTZMtKYq9K1ZqJMjifKx3cPL7pIGk9Q`` as the API Key Value. + + Bugzilla adds the header only when both values are set. If either value + is empty, Bugzilla sends the webhook without the authentication header. + +#. Click :guilabel:`Add`. + +Registered webhooks appear on the same preferences tab. To delete one or more +webhooks, select them in the :guilabel:`Your webhooks` table and click +:guilabel:`Remove selected`. + +You can also enable or disable each webhook from this table. If a webhook has +queued messages, the error count links to a page where you can inspect the +queue and delete individual messages. + +Delivered webhooks +------------------ + +When a webhook is triggered, Bugzilla sends an HTTP POST request containing a +JSON payload. The payload includes the webhook ID, webhook name, event +information, and information about the bug that matched the event and filters. + +Bugzilla ordinarily sends a webhook only if its owner can see the affected bug +and its product. A public-to-private transition can also be sent using the +bug's previous public state so the receiving system can remove information +that is no longer public. When a bug becomes public again, Bugzilla sends an +``is_private`` modification event containing its current public data. When a +payload's bug is private, its details are reduced to the bug ID and privacy +status. Private comments and attachments are sent only when the webhook owner +is authorized to see them; their payloads are also reduced to IDs and privacy +status. The receiving system must use the REST API with suitable credentials +to retrieve additional details. + +Webhooks are generally delivered in event timestamp order, but the relative +order of events with the same timestamp is not guaranteed. Bug creation and +modification events each produce a separate request. The ``changes`` field is +sent for ordinary public modification events and describes changes made to the +event target, such as the bug or attachment. Private modification payloads omit +this field. A public-to-private transition reports only the synthetic +``is_private`` change. + +The payloads below are representative. Bug objects can also contain custom +fields configured for their product and component. + +Public bug request +~~~~~~~~~~~~~~~~~~ + +.. code-block:: json + + { + "bug": { + "alias": "", + "assigned_to": "nobody@mozilla.org", + "assigned_to_detail": { + "id": 1, + "login": "nobody@mozilla.org", + "real_name": "Nobody; OK to take it and work on it" + }, + "classification": "Client Software", + "component": "Sync", + "creation_time": "2020-10-16T06:24:06", + "creator": "nobody@mozilla.org", + "creator_detail": { + "id": 1, + "login": "nobody@mozilla.org", + "real_name": "Nobody; OK to take it and work on it" + }, + "flags": [], + "id": 1629704, + "is_private": false, + "keywords": [], + "last_change_time": "2020-10-16T06:26:21", + "operating_system": "Unspecified", + "platform": "Unspecified", + "priority": "P1", + "product": "Firefox", + "qa_contact": "nobody@mozilla.org", + "qa_contact_detail": { + "id": 1, + "login": "nobody@mozilla.org", + "real_name": "Nobody; OK to take it and work on it" + }, + "resolution": "", + "see_also": [], + "severity": "--", + "status": "NEW", + "summary": "Webhook Test - Disregard", + "target_milestone": "---", + "type": "defect", + "url": "", + "version": "unspecified", + "whiteboard": "" + }, + "event": { + "action": "modify", + "routing_key": "bug.modify:priority", + "target": "bug", + "time": "2020-07-24T20:11:22", + "user": { + "id": 1, + "login": "nobody@mozilla.org", + "real_name": "Nobody; OK to take it and work on it" + }, + "changes": [ + { + "field": "priority", + "removed": "P3", + "added": "P1" + } + ] + }, + "webhook_id": 23, + "webhook_name": "test-bug" + } + +Private bug request +~~~~~~~~~~~~~~~~~~~ + +.. code-block:: json + + { + "bug": { + "id": 2, + "is_private": true + }, + "event": { + "action": "modify", + "routing_key": "bug.modify:priority", + "target": "bug", + "time": "2020-07-24T20:11:22", + "user": { + "id": 1, + "login": "nobody@mozilla.org", + "real_name": "Nobody; OK to take it and work on it" + } + }, + "webhook_id": 23, + "webhook_name": "test-bug" + } + +Response +~~~~~~~~ + +Bugzilla treats any HTTP 2xx response as successful. + +New comment +~~~~~~~~~~~ + +.. code-block:: json + + { + "bug": { + "alias": "", + "assigned_to": "nobody@mozilla.org", + "assigned_to_detail": { + "id": 1, + "login": "nobody@mozilla.org", + "real_name": "Nobody; OK to take it and work on it" + }, + "classification": "Client Software", + "comment": { + "body": "another test comment", + "creation_time": "2020-10-16T06:28:41", + "id": 14748073, + "is_private": false, + "number": 2 + }, + "component": "Sync", + "creation_time": "2020-10-16T06:24:06", + "creator": "nobody@mozilla.org", + "creator_detail": { + "id": 1, + "login": "nobody@mozilla.org", + "real_name": "Nobody; OK to take it and work on it" + }, + "flags": [], + "id": 1629704, + "is_private": false, + "keywords": [], + "last_change_time": "2020-10-16T06:26:21", + "operating_system": "Unspecified", + "platform": "Unspecified", + "priority": "", + "product": "Firefox", + "qa_contact": "", + "resolution": "", + "see_also": [], + "severity": "--", + "status": "NEW", + "summary": "Webhook Test - Disregard", + "target_milestone": "---", + "type": "defect", + "url": "", + "version": "unspecified", + "whiteboard": "" + }, + "event": { + "action": "create", + "routing_key": "comment.create", + "target": "comment", + "time": "2020-10-16T06:28:41", + "user": { + "id": 1, + "login": "nobody@mozilla.org", + "real_name": "Nobody; OK to take it and work on it" + } + }, + "webhook_id": 23, + "webhook_name": "test-comment" + } + +New attachment +~~~~~~~~~~~~~~ + +.. code-block:: json + + { + "bug": { + "alias": "", + "assigned_to": "nobody@mozilla.org", + "assigned_to_detail": { + "id": 1, + "login": "nobody@mozilla.org", + "real_name": "Nobody; OK to take it and work on it" + }, + "attachment": { + "content_type": "text/plain", + "creation_time": "2020-10-16T07:08:12", + "description": "test attachment", + "file_name": "file_1629704.txt", + "flags": [], + "id": 9180115, + "is_obsolete": false, + "is_patch": false, + "is_private": false, + "last_change_time": "2020-10-16T07:08:12" + }, + "classification": "Client Software", + "component": "Sync", + "creation_time": "2020-10-16T06:24:06", + "creator": "nobody@mozilla.org", + "creator_detail": { + "id": 1, + "login": "nobody@mozilla.org", + "real_name": "Nobody; OK to take it and work on it" + }, + "flags": [], + "id": 1629704, + "is_private": false, + "keywords": [], + "last_change_time": "2020-10-16T06:26:21", + "operating_system": "Unspecified", + "platform": "Unspecified", + "priority": "", + "product": "Firefox", + "qa_contact": "", + "resolution": "", + "see_also": [], + "severity": "--", + "status": "NEW", + "summary": "Webhook Test - Disregard", + "target_milestone": "---", + "type": "defect", + "url": "", + "version": "unspecified", + "whiteboard": "" + }, + "event": { + "action": "create", + "routing_key": "attachment.create", + "target": "attachment", + "time": "2020-10-16T07:08:12", + "user": { + "id": 1, + "login": "nobody@mozilla.org", + "real_name": "Nobody; OK to take it and work on it" + } + }, + "webhook_id": 23, + "webhook_name": "test-attachment" + } + +Errors and retries +------------------ + +If an endpoint does not return an HTTP 2xx response, or if delivery fails for +another reason, Bugzilla puts the message in the webhook's queue. After each +failed queued attempt, it schedules the next attempt using a backoff counter +shared by the webhook's queued messages. Starting the delivery daemon or +re-enabling the webhook resets this counter. From a reset state, delays are +5 seconds after the first failure, then 25, 125, and 625 seconds. After later +failures, the delay is 15 minutes. A successful delivery does not reset the +counter, so a later failure can start with a longer delay. The delivery daemon +polls every 30 seconds, so an attempt can occur later than its scheduled time. + +If a message remains stuck, later messages for that webhook remain queued until +the blocking message succeeds, is manually deleted, or is discarded because +the webhook owner is no longer authorized to receive it. + +Administrators can configure a per-message attempt limit and an exempt group. +Unless the exemption applies, Bugzilla disables the webhook and emails its +owner when a queued message reaches the limit. The owner can re-enable it from +the :guilabel:`Webhooks` preferences tab after fixing the problem. diff --git a/extensions/Webhooks/template/en/default/account/prefs/webhooks.html.tmpl b/extensions/Webhooks/template/en/default/account/prefs/webhooks.html.tmpl index 5511115932..cd8f631e61 100644 --- a/extensions/Webhooks/template/en/default/account/prefs/webhooks.html.tmpl +++ b/extensions/Webhooks/template/en/default/account/prefs/webhooks.html.tmpl @@ -53,7 +53,8 @@ window.onload = function() {

It will be sent a POST request with the information of the [% terms.bugs %] that match with the events and filters selected to your URL.
- Documentation about webhooks is available here. + Documentation about webhooks is available + here.

diff --git a/extensions/Webhooks/template/en/default/pages/webhooks.html.tmpl b/extensions/Webhooks/template/en/default/pages/webhooks.html.tmpl deleted file mode 100644 index c5f47dc2a4..0000000000 --- a/extensions/Webhooks/template/en/default/pages/webhooks.html.tmpl +++ /dev/null @@ -1,340 +0,0 @@ -[%# This Source Code Form is subject to the terms of the Mozilla Public - # License, v. 2.0. If a copy of the MPL was not distributed with this - # file, You can obtain one at http://mozilla.org/MPL/2.0/. - # - # This Source Code Form is | "Incompatible With Secondary Licenses", as - # defined by the Mozilla Public License, v. 2.0. - #%] - -[% PROCESS global/header.html.tmpl - title = "Webhooks Documentation" - style = "#bugzilla-body li { - margin: 5px - } - h4 { - margin-bottom: 0px - } - .heading { - font-weight: bold - } - #main-inner{ - margin-left: 20%; - margin-right: 20%; - margin-bottom: 5% - } - " -%] - -

[% terms.Bugzilla %] Webhooks

- -

A webhook is a custom callback defined by events. Is triggered when those events happen, and a POST -request is sent to a defined URL.

- -

In the case of [% terms.Bugzilla %], a webhook can be triggered by a change to, or creation of a [% terms.bug %]. The -parameters of the [% terms.bug %] are exposed to the webhook handler which makes a callback (over HTTP) to another -web application.

- -

Examples of [% terms.Bugzilla %] webhooks could include:

- - -

Creating a webhook

-

To create a webhook follow the next steps:

-
    -
  1. Access to your [% terms.Bugzilla %] Account.
  2. -
  3. Go to your Preferences Panel > Webhooks.
  4. -
  5. Fill out all of the parameters:
  6. -

    Name

    -

    A name for the webhook, which should be descriptive (e.g. “Jira Webhook for New & Updated [% terms.Bugs %] in Core::Graphics”)

    - -

    URL

    -

    The URL which will receive and process the webhook.

    - -

    Events

    -

    The [% terms.bug %] events that will trigger your new webhook.

    - - -

    Filters

    -

    Properties of a [% terms.bug %] that specify which [% terms.bugs %] you will receive.

    - - -

    API Keys

    -

    If your endpoint requires authentication, you may optionally provide a header and API key for your endpoint. - An example of a header may look like Authorization: Token zQ5TSBzq7tTZMtKYq9K1ZqJMjifKx3cPL7pIGk9Q. - So you would enter Authorization for the API Key Header and - Token zQ5TSBzq7tTZMtKYq9K1ZqJMjifKx3cPL7pIGk9Q for the API Key Value.

    -

    Note: If one or both of the values are empty, the webhook will still send the data to your endpoint, - but the request may fail if the endoint requires authentication.

    - -
  7. Add the webhook.
  8. -
- -

You can see your registered webhooks in the same panel.

-

If you want to delete a webhook, select the webhook in “Your webhooks” table and click remove -selected. You can select more than one.

- -

Delivered webhook

-

When a webhook is triggered the HTTP POST of a fixed JSON structure payload that is delivered -contains the webhook_id, webhook_name and the information about the [% terms.bug %] that matches the event and filters.

- -

If the [% terms.bug %] is private, only the [% terms.bug %] id and some other basic information is sent and the external system will -need to query BMO over the REST API to get the actual details of the [% terms.bug %].

- -

The webhooks will be called in the same order as the events triggering them and will be one request per new -[% terms.bug %] and per changed [% terms.bug %]. The "changes" parameter will be sent only when the triggered event is changed and will -content every change made in the [% terms.bug %].

- -

Public [% terms.Bug %] Request

- -{ - "[% terms.bug %]": { - "alias": "", - "assigned_to": "nobody@mozilla.org", - "assigned_to_detail": { - "id": 1, - "login": "nobody@mozilla.org", - "real_name": "Nobody; OK to take it and work on it" - }, - "classification": "Client Software", - "comment": { - "body": "another test comment", - "creation_time": "2020-10-16T06:28:41", - "id": 14748073, - "is_private": false, - "number": 2 - }, - "component": "Sync", - "creation_time": "2020-10-16T06:24:06", - "creator": "nobody@mozilla.org", - "creator_detail": { - "id": 1, - "login": "nobody@mozilla.org", - "real_name": "Nobody; OK to take it and work on it" - }, - "flags": [], - "id": 1629704, - "is_private": false, - "keywords": [], - "last_change_time": "2020-10-16T06:26:21", - "operating_system": "Unspecified", - "platform": "Unspecified", - "priority": "P1", - "product": "Firefox", - "qa_contact": "nobody@mozilla.org", - "qa_contact_detail": { - "id": 1, - "login": "nobody@mozilla.org", - "real_name": "Nobody; OK to take it and work on it" - }, - "resolution": "", - "severity": "--", - "status": "NEW", - "summary": "Webhook Test - Disregard", - "target_milestone": "---", - "type": "defect", - "url": "", - "version": "unspecified", - "whiteboard": "" - }, - "event": { - "action": "modify", - "routing_key": "bug.modify:priority" - "target": "bug", - "time": "2020-07-24T20:11:22", - "user": { - "id": 1, - "login": "nobody@mozilla.org", - "real_name": "Nobody; OK to take it and work on it" - }, - "changes": [ - { - "field": "priority", - "removed": "P3", - "added": "P1" - } - ] - }, - "webhook_id": 23, - "webhook_name": "test-bug" -} - - -

Private [% terms.Bug %] Request

- -{ - "[% terms.bug %]": { - "id": 2, - "is_private": true - }, - "event": { - "action": "modify", - "routing_key": "bug.modify:priority" - "target": "bug", - "time": "2020-07-24T20:11:22", - "user": { - "id": 1, - "login": "nobody@mozilla.org", - "real_name": "Nobody; OK to take it and work on it" - } - }, - "webhook_id": 23, - "webhook_name": "test-bug", -} - - -

Response

-

HTTP 200 OK. The request has succeeded.

- -

New Comment

- -{ - "[% terms.bug %]": { - "alias": "", - "assigned_to": "nobody@mozilla.org", - "assigned_to_detail": { - "id": 1, - "login": "nobody@mozilla.org", - "real_name": "Nobody; OK to take it and work on it" - }, - "classification": "Client Software", - "comment": { - "body": "another test comment", - "creation_time": "2020-10-16T06:28:41", - "id": 14748073, - "is_private": false, - "number": 2 - }, - "component": "Sync", - "creation_time": "2020-10-16T06:24:06", - "creator": "nobody@mozilla.org", - "creator_detail": { - "id": 1, - "login": "nobody@mozilla.org", - "real_name": "Nobody; OK to take it and work on it" - }, - "flags": [], - "id": 1629704, - "is_private": false, - "keywords": [], - "last_change_time": "2020-10-16T06:26:21", - "operating_system": "Unspecified", - "platform": "Unspecified", - "priority": "", - "product": "Firefox", - "qa_contact": "", - "resolution": "", - "severity": "--", - "status": "NEW", - "summary": "Webhook Test - Disregard", - "target_milestone": "---", - "type": "defect", - "url": "", - "version": "unspecified", - "whiteboard": "" - }, - "event": { - "action": "create", - "routing_key": "comment.create", - "target": "comment", - "time": "2020-10-16T06:28:41", - "user": { - "id": 1, - "login": "nobody@mozilla.org", - "real_name": "Nobody; OK to take it and work on it" - } - }, - "webhook_id": 23, - "webhook_name": "test-comment" -} - - -

New Attachment

- -{ - "[% terms.bug %]": { - "alias": "", - "assigned_to": "nobody@mozilla.org", - "assigned_to_detail": { - "id": 1, - "login": "nobody@mozilla.org", - "real_name": "Nobody; OK to take it and work on it" - }, - "attachment": { - "content_type": "text/plain", - "creation_time": "2020-10-16T07:08:12", - "description": "test attachment", - "file_name": "file_1629704.txt", - "flags": [], - "id": 9180115, - "is_obsolete": false, - "is_patch": false, - "is_private": false, - "last_change_time": "2020-10-16T07:08:12" - } - "classification": "Client Software", - "component": "Sync", - "creation_time": "2020-10-16T06:24:06", - "creator": "nobody@mozilla.org", - "creator_detail": { - "id": 1, - "login": "nobody@mozilla.org", - "real_name": "Nobody; OK to take it and work on it" - }, - "flags": [], - "id": 1629704, - "is_private": false, - "keywords": [], - "last_change_time": "2020-10-16T06:26:21", - "operating_system": "Unspecified", - "platform": "Unspecified", - "priority": "", - "product": "Firefox", - "qa_contact": "", - "resolution": "", - "severity": "--", - "status": "NEW", - "summary": "Webhook Test - Disregard", - "target_milestone": "---", - "type": "defect", - "url": "", - "version": "unspecified", - "whiteboard": "" - }, - "event": { - "action": "create", - "routing_key": "attachment.create", - "target": "attachment", - "time": "2020-10-16T07:08:12", - "user": { - "id": 1, - "login": "nobody@mozilla.org", - "real_name": "Nobody; OK to take it and work on it" - } - }, - "webhook_id": 23, - "webhook_name": "test-attachment" -} - - -

Errors

-

If the response is not 200, the [% terms.Bugzilla %] system will retry 4 attempts, waiting 5s, 10s, 15s and -20s between each attempt. If none of those attempts is successful, the system will continue trying -every 15 minutes.

- -

If a message is stuck without a successful attempt, the next messages that trigger the webhook -will be stored in a queue in the order that were triggered and will be delivered in that order when -the first message in the queue is delivered.

- -[% INCLUDE global/footer.html.tmpl %]