diff options
Diffstat (limited to 'doc/user/project/integrations/webhooks.md')
-rw-r--r-- | doc/user/project/integrations/webhooks.md | 1913 |
1 files changed, 150 insertions, 1763 deletions
diff --git a/doc/user/project/integrations/webhooks.md b/doc/user/project/integrations/webhooks.md index 44225ac2921..0891d48c038 100644 --- a/doc/user/project/integrations/webhooks.md +++ b/doc/user/project/integrations/webhooks.md @@ -6,1802 +6,226 @@ info: To determine the technical writer assigned to the Stage/Group associated w # Webhooks **(FREE)** -Project webhooks allow you to trigger a percent-encoded URL if, for example, new code is pushed or -a new issue is created. You can configure webhooks to listen for specific events -like pushes, issues or merge requests. GitLab sends a POST request with data -to the webhook URL. - -You usually need to set up your own [webhook receiver](#example-webhook-receiver) -to receive information from GitLab and send it to another app, according to your requirements. -We already have a [built-in receiver](slack.md) -for sending [Slack](https://api.slack.com/incoming-webhooks) notifications _per project_. - -## Overview - -[Webhooks](https://en.wikipedia.org/wiki/Webhook) are "_user-defined HTTP -callbacks_". They are usually triggered by some -event, such as pushing code to a repository or a comment being posted to a blog. -When that event occurs, the source app makes an HTTP request to the URI -configured for the webhook. The action taken may be anything. -Common uses are to trigger builds with continuous integration systems or to -notify bug tracking systems. - -Webhooks can be used to update an external issue tracker, trigger CI jobs, -update a backup mirror, or even deploy to your production server. - -Webhooks are available: - -- Per project, at a project's **Settings > Webhooks** menu. **(FREE)** -- Additionally per group, at a group's **Settings > Webhooks** menu. **(PREMIUM)** - -GitLab.com enforces various [webhook limits](../../../user/gitlab_com/index.md#webhooks), including: - -- The maximum number of webhooks and their size, both per project, and per group. -- The number of webhook calls per minute. - -## Possible uses for webhooks - -- You can set up a webhook in GitLab to send a notification to +[Webhooks](https://en.wikipedia.org/wiki/Webhook) are custom HTTP callbacks +that you define. They are usually triggered by an +event, such as pushing code to a repository or posting a comment on a blog. +When the event occurs, the source app makes an HTTP request to the URI +configured for the webhook. The action to take may be anything. For example, +you can use webhooks to: + +- Trigger continuous integration (CI) jobs, update external issue trackers, + update a backup mirror, or deploy to your production server. +- Send a notification to [Slack](https://api.slack.com/incoming-webhooks) every time a job fails. -- You can [integrate with Twilio to be notified via SMS](https://www.datadoghq.com/blog/send-alerts-sms-customizable-webhooks-twilio/) - every time an issue is created for a specific project or group within GitLab -- You can use them to [automatically assign labels to merge requests](https://about.gitlab.com/blog/2016/08/19/applying-gitlab-labels-automatically/). - -## Webhook endpoint tips - -If you are writing your own endpoint (web server) to receive -GitLab webhooks, keep in mind the following: - -- Your endpoint should send its HTTP response as fast as possible. If the response takes longer than - the configured timeout, GitLab decides the hook failed and retries it. For information on - customizing this timeout, see - [Webhook fails or multiple webhook requests are triggered](#webhook-fails-or-multiple-webhook-requests-are-triggered). -- Your endpoint should ALWAYS return a valid HTTP response. If you do - not do this then GitLab thinks the hook failed and retries it. - Most HTTP libraries take care of this for you automatically but if - you are writing a low-level hook this is important to remember. -- GitLab ignores the HTTP status code returned by your endpoint. - -## Secret token - -If you specify a secret token, it is sent with the hook request in the -`X-Gitlab-Token` HTTP header. Your webhook endpoint can check that to verify -that the request is legitimate. - -## SSL verification - -By default, the SSL certificate of the webhook endpoint is verified based on -an internal list of Certificate Authorities. This means the certificate cannot -be self-signed. - -You can turn this off in the webhook settings in your GitLab projects. - -## Branch filtering - -> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/20338) in GitLab 11.3. - -Push events can be filtered by branch using a branch name or wildcard pattern -to limit which push events are sent to your webhook endpoint. By default the -field is blank causing all push events to be sent to your webhook endpoint. - -## Events - -Below are described the supported events. - -### Push events - -Triggered when you push to the repository except when pushing tags. - -NOTE: -When more than 20 commits are pushed at once, the `commits` webhook -attribute only contains the newest 20 for performance reasons. Loading -detailed commit data is expensive. Note that despite only 20 commits being -present in the `commits` attribute, the `total_commits_count` attribute contains the actual total. - -NOTE: -If a branch creation push event is generated without new commits being introduced, the -`commits` attribute in the payload is empty. - -Also, if a single push includes changes for more than three (by default, depending on -[`push_event_hooks_limit` setting](../../../api/settings.md#list-of-settings-that-can-be-accessed-via-api-calls)) -branches, this hook isn't executed. - -**Request header**: - -```plaintext -X-Gitlab-Event: Push Hook -``` - -**Payload example:** - -```json -{ - "object_kind": "push", - "before": "95790bf891e76fee5e1747ab589903a6a1f80f22", - "after": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7", - "ref": "refs/heads/master", - "checkout_sha": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7", - "user_id": 4, - "user_name": "John Smith", - "user_username": "jsmith", - "user_email": "john@example.com", - "user_avatar": "https://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=8://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=80", - "project_id": 15, - "project":{ - "id": 15, - "name":"Diaspora", - "description":"", - "web_url":"http://example.com/mike/diaspora", - "avatar_url":null, - "git_ssh_url":"git@example.com:mike/diaspora.git", - "git_http_url":"http://example.com/mike/diaspora.git", - "namespace":"Mike", - "visibility_level":0, - "path_with_namespace":"mike/diaspora", - "default_branch":"master", - "homepage":"http://example.com/mike/diaspora", - "url":"git@example.com:mike/diaspora.git", - "ssh_url":"git@example.com:mike/diaspora.git", - "http_url":"http://example.com/mike/diaspora.git" - }, - "repository":{ - "name": "Diaspora", - "url": "git@example.com:mike/diaspora.git", - "description": "", - "homepage": "http://example.com/mike/diaspora", - "git_http_url":"http://example.com/mike/diaspora.git", - "git_ssh_url":"git@example.com:mike/diaspora.git", - "visibility_level":0 - }, - "commits": [ - { - "id": "b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327", - "message": "Update Catalan translation to e38cb41.\n\nSee https://gitlab.com/gitlab-org/gitlab for more information", - "title": "Update Catalan translation to e38cb41.", - "timestamp": "2011-12-12T14:27:31+02:00", - "url": "http://example.com/mike/diaspora/commit/b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327", - "author": { - "name": "Jordi Mallach", - "email": "jordi@softcatala.org" - }, - "added": ["CHANGELOG"], - "modified": ["app/controller/application.rb"], - "removed": [] - }, - { - "id": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7", - "message": "fixed readme", - "title": "fixed readme", - "timestamp": "2012-01-03T23:36:29+02:00", - "url": "http://example.com/mike/diaspora/commit/da1560886d4f094c3e6c9ef40349f7d38b5d27d7", - "author": { - "name": "GitLab dev user", - "email": "gitlabdev@dv6700.(none)" - }, - "added": ["CHANGELOG"], - "modified": ["app/controller/application.rb"], - "removed": [] - } - ], - "total_commits_count": 4 -} -``` +- [Integrate with Twilio to be notified via SMS](https://www.datadoghq.com/blog/send-alerts-sms-customizable-webhooks-twilio/) + every time an issue is created for a specific project or group in GitLab. +- [Automatically assign labels to merge requests](https://about.gitlab.com/blog/2016/08/19/applying-gitlab-labels-automatically/). -### Tag events +You can configure your GitLab project or [group](#group-webhooks) to trigger +a percent-encoded webhook URL when an event occurs. For example, when new code +is pushed or a new issue is created. +The webhook listens for specific [events](#events) and +GitLab sends a POST request with data to the webhook URL. -Triggered when you create (or delete) tags to the repository. - -NOTE: -If a single push includes changes for more than three (by default, depending on -[`push_event_hooks_limit` setting](../../../api/settings.md#list-of-settings-that-can-be-accessed-via-api-calls)) -tags, this hook is not executed. +Usually, you set up your own [webhook receiver](#create-an-example-webhook-receiver) +to receive information from GitLab and send it to another app, according to your requirements. +We have a [built-in receiver](slack.md) +for sending [Slack](https://api.slack.com/incoming-webhooks) notifications per project. -**Request header**: +GitLab.com enforces [webhook limits](../../../user/gitlab_com/index.md#webhooks), +including: -```plaintext -X-Gitlab-Event: Tag Push Hook -``` +- The maximum number of webhooks and their size, both per project and per group. +- The number of webhook calls per minute. -**Payload example:** - -```json -{ - "object_kind": "tag_push", - "before": "0000000000000000000000000000000000000000", - "after": "82b3d5ae55f7080f1e6022629cdb57bfae7cccc7", - "ref": "refs/tags/v1.0.0", - "checkout_sha": "82b3d5ae55f7080f1e6022629cdb57bfae7cccc7", - "user_id": 1, - "user_name": "John Smith", - "user_avatar": "https://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=8://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=80", - "project_id": 1, - "project":{ - "id": 1, - "name":"Example", - "description":"", - "web_url":"http://example.com/jsmith/example", - "avatar_url":null, - "git_ssh_url":"git@example.com:jsmith/example.git", - "git_http_url":"http://example.com/jsmith/example.git", - "namespace":"Jsmith", - "visibility_level":0, - "path_with_namespace":"jsmith/example", - "default_branch":"master", - "homepage":"http://example.com/jsmith/example", - "url":"git@example.com:jsmith/example.git", - "ssh_url":"git@example.com:jsmith/example.git", - "http_url":"http://example.com/jsmith/example.git" - }, - "repository":{ - "name": "Example", - "url": "ssh://git@example.com/jsmith/example.git", - "description": "", - "homepage": "http://example.com/jsmith/example", - "git_http_url":"http://example.com/jsmith/example.git", - "git_ssh_url":"git@example.com:jsmith/example.git", - "visibility_level":0 - }, - "commits": [], - "total_commits_count": 0 -} -``` +## Group webhooks **(PREMIUM)** -### Issue events +You can configure a webhook for a group to ensure all projects in the group +receive the same webhook settings. -Triggered when a new issue is created or an existing issue was updated/closed/reopened. +## Configure a webhook -**Request header**: +You can configure a webhook for a group or a project. -```plaintext -X-Gitlab-Event: Issue Hook -``` +1. In your project or group, on the left sidebar, select **Settings > Webhooks**. +1. In **URL**, enter the URL of the webhook endpoint. + The URL must be percentage-encoded, if necessary. +1. In **Secret token**, enter the [secret token](#validate-payloads-by-using-a-secret-token) to validate payloads. +1. In the **Trigger** section, select the [events](webhook_events.md) to trigger the webhook. +1. Optional. Clear the **Enable SSL verification** checkbox to disable [SSL verification](#verify-an-ssl-certificate). +1. Select **Add webhook**. -**Available `object_attributes.action`:** - -- `open` -- `close` -- `reopen` -- `update` - -**Payload example:** - -```json -{ - "object_kind": "issue", - "event_type": "issue", - "user": { - "id": 1, - "name": "Administrator", - "username": "root", - "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon", - "email": "admin@example.com" - }, - "project": { - "id": 1, - "name":"Gitlab Test", - "description":"Aut reprehenderit ut est.", - "web_url":"http://example.com/gitlabhq/gitlab-test", - "avatar_url":null, - "git_ssh_url":"git@example.com:gitlabhq/gitlab-test.git", - "git_http_url":"http://example.com/gitlabhq/gitlab-test.git", - "namespace":"GitlabHQ", - "visibility_level":20, - "path_with_namespace":"gitlabhq/gitlab-test", - "default_branch":"master", - "ci_config_path": null, - "homepage":"http://example.com/gitlabhq/gitlab-test", - "url":"http://example.com/gitlabhq/gitlab-test.git", - "ssh_url":"git@example.com:gitlabhq/gitlab-test.git", - "http_url":"http://example.com/gitlabhq/gitlab-test.git" - }, - "object_attributes": { - "id": 301, - "title": "New API: create/update/delete file", - "assignee_ids": [51], - "assignee_id": 51, - "author_id": 51, - "project_id": 14, - "created_at": "2013-12-03T17:15:43Z", - "updated_at": "2013-12-03T17:15:43Z", - "updated_by_id": 1, - "last_edited_at": null, - "last_edited_by_id": null, - "relative_position": 0, - "description": "Create new API for manipulations with repository", - "milestone_id": null, - "state_id": 1, - "confidential": false, - "discussion_locked": true, - "due_date": null, - "moved_to_id": null, - "duplicated_to_id": null, - "time_estimate": 0, - "total_time_spent": 0, - "time_change": 0, - "human_total_time_spent": null, - "human_time_estimate": null, - "human_time_change": null, - "weight": null, - "iid": 23, - "url": "http://example.com/diaspora/issues/23", - "state": "opened", - "action": "open", - "labels": [{ - "id": 206, - "title": "API", - "color": "#ffffff", - "project_id": 14, - "created_at": "2013-12-03T17:15:43Z", - "updated_at": "2013-12-03T17:15:43Z", - "template": false, - "description": "API related issues", - "type": "ProjectLabel", - "group_id": 41 - }] - }, - "repository": { - "name": "Gitlab Test", - "url": "http://example.com/gitlabhq/gitlab-test.git", - "description": "Aut reprehenderit ut est.", - "homepage": "http://example.com/gitlabhq/gitlab-test" - }, - "assignees": [{ - "name": "User1", - "username": "user1", - "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon" - }], - "assignee": { - "name": "User1", - "username": "user1", - "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon" - }, - "labels": [{ - "id": 206, - "title": "API", - "color": "#ffffff", - "project_id": 14, - "created_at": "2013-12-03T17:15:43Z", - "updated_at": "2013-12-03T17:15:43Z", - "template": false, - "description": "API related issues", - "type": "ProjectLabel", - "group_id": 41 - }], - "changes": { - "updated_by_id": { - "previous": null, - "current": 1 - }, - "updated_at": { - "previous": "2017-09-15 16:50:55 UTC", - "current": "2017-09-15 16:52:00 UTC" - }, - "labels": { - "previous": [{ - "id": 206, - "title": "API", - "color": "#ffffff", - "project_id": 14, - "created_at": "2013-12-03T17:15:43Z", - "updated_at": "2013-12-03T17:15:43Z", - "template": false, - "description": "API related issues", - "type": "ProjectLabel", - "group_id": 41 - }], - "current": [{ - "id": 205, - "title": "Platform", - "color": "#123123", - "project_id": 14, - "created_at": "2013-12-03T17:15:43Z", - "updated_at": "2013-12-03T17:15:43Z", - "template": false, - "description": "Platform related issues", - "type": "ProjectLabel", - "group_id": 41 - }] - } - } -} -``` +## Test a webhook -NOTE: -`assignee` and `assignee_id` keys are deprecated and now show the first assignee only. +You can trigger a webhook manually, to ensure it's working properly. -### Comment events +For example, to test `push events`, your project should have at least one commit. The webhook uses this commit in the webhook. -Triggered when a new comment is made on commits, merge requests, issues, and code snippets. -The note data is stored in `object_attributes` (for example, `note` or `noteable_type`). The -payload also includes information about the target of the comment. For example, -a comment on an issue includes the specific issue information under the `issue` key. -Valid target types: +To test a webhook: -- `commit` -- `merge_request` -- `issue` -- `snippet` +1. In your project, on the left sidebar, select **Settings > Webhooks**. +1. Scroll down to the list of configured webhooks. +1. From the **Test** dropdown list, select the type of event to test. -#### Comment on commit +![Webhook testing](img/webhook_testing.png) -**Request header**: +## Create an example webhook receiver -```plaintext -X-Gitlab-Event: Note Hook -``` +To test how GitLab webhooks work, you can use +an echo script running in a console session. For the following script to +work you must have Ruby installed. -**Payload example:** - -```json -{ - "object_kind": "note", - "user": { - "id": 1, - "name": "Administrator", - "username": "root", - "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon", - "email": "admin@example.com" - }, - "project_id": 5, - "project":{ - "id": 5, - "name":"Gitlab Test", - "description":"Aut reprehenderit ut est.", - "web_url":"http://example.com/gitlabhq/gitlab-test", - "avatar_url":null, - "git_ssh_url":"git@example.com:gitlabhq/gitlab-test.git", - "git_http_url":"http://example.com/gitlabhq/gitlab-test.git", - "namespace":"GitlabHQ", - "visibility_level":20, - "path_with_namespace":"gitlabhq/gitlab-test", - "default_branch":"master", - "homepage":"http://example.com/gitlabhq/gitlab-test", - "url":"http://example.com/gitlabhq/gitlab-test.git", - "ssh_url":"git@example.com:gitlabhq/gitlab-test.git", - "http_url":"http://example.com/gitlabhq/gitlab-test.git" - }, - "repository":{ - "name": "Gitlab Test", - "url": "http://example.com/gitlab-org/gitlab-test.git", - "description": "Aut reprehenderit ut est.", - "homepage": "http://example.com/gitlab-org/gitlab-test" - }, - "object_attributes": { - "id": 1243, - "note": "This is a commit comment. How does this work?", - "noteable_type": "Commit", - "author_id": 1, - "created_at": "2015-05-17 18:08:09 UTC", - "updated_at": "2015-05-17 18:08:09 UTC", - "project_id": 5, - "attachment":null, - "line_code": "bec9703f7a456cd2b4ab5fb3220ae016e3e394e3_0_1", - "commit_id": "cfe32cf61b73a0d5e9f13e774abde7ff789b1660", - "noteable_id": null, - "system": false, - "st_diff": { - "diff": "--- /dev/null\n+++ b/six\n@@ -0,0 +1 @@\n+Subproject commit 409f37c4f05865e4fb208c771485f211a22c4c2d\n", - "new_path": "six", - "old_path": "six", - "a_mode": "0", - "b_mode": "160000", - "new_file": true, - "renamed_file": false, - "deleted_file": false - }, - "url": "http://example.com/gitlab-org/gitlab-test/commit/cfe32cf61b73a0d5e9f13e774abde7ff789b1660#note_1243" - }, - "commit": { - "id": "cfe32cf61b73a0d5e9f13e774abde7ff789b1660", - "message": "Add submodule\n\nSigned-off-by: Example User \u003cuser@example.com.com\u003e\n", - "timestamp": "2014-02-27T10:06:20+02:00", - "url": "http://example.com/gitlab-org/gitlab-test/commit/cfe32cf61b73a0d5e9f13e774abde7ff789b1660", - "author": { - "name": "Example User", - "email": "user@example.com" - } - } -} -``` +1. Save the following file as `print_http_body.rb`: -#### Comment on merge request + ```ruby + require 'webrick' -**Request header**: + server = WEBrick::HTTPServer.new(:Port => ARGV.first) + server.mount_proc '/' do |req, res| + puts req.body + end -```plaintext -X-Gitlab-Event: Note Hook -``` + trap 'INT' do + server.shutdown + end + server.start + ``` -**Payload example:** - -```json -{ - "object_kind": "note", - "user": { - "id": 1, - "name": "Administrator", - "username": "root", - "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon", - "email": "admin@example.com" - }, - "project_id": 5, - "project":{ - "id": 5, - "name":"Gitlab Test", - "description":"Aut reprehenderit ut est.", - "web_url":"http://example.com/gitlab-org/gitlab-test", - "avatar_url":null, - "git_ssh_url":"git@example.com:gitlab-org/gitlab-test.git", - "git_http_url":"http://example.com/gitlab-org/gitlab-test.git", - "namespace":"Gitlab Org", - "visibility_level":10, - "path_with_namespace":"gitlab-org/gitlab-test", - "default_branch":"master", - "homepage":"http://example.com/gitlab-org/gitlab-test", - "url":"http://example.com/gitlab-org/gitlab-test.git", - "ssh_url":"git@example.com:gitlab-org/gitlab-test.git", - "http_url":"http://example.com/gitlab-org/gitlab-test.git" - }, - "repository":{ - "name": "Gitlab Test", - "url": "http://localhost/gitlab-org/gitlab-test.git", - "description": "Aut reprehenderit ut est.", - "homepage": "http://example.com/gitlab-org/gitlab-test" - }, - "object_attributes": { - "id": 1244, - "note": "This MR needs work.", - "noteable_type": "MergeRequest", - "author_id": 1, - "created_at": "2015-05-17 18:21:36 UTC", - "updated_at": "2015-05-17 18:21:36 UTC", - "project_id": 5, - "attachment": null, - "line_code": null, - "commit_id": "", - "noteable_id": 7, - "system": false, - "st_diff": null, - "url": "http://example.com/gitlab-org/gitlab-test/merge_requests/1#note_1244" - }, - "merge_request": { - "id": 7, - "target_branch": "markdown", - "source_branch": "master", - "source_project_id": 5, - "author_id": 8, - "assignee_id": 28, - "title": "Tempora et eos debitis quae laborum et.", - "created_at": "2015-03-01 20:12:53 UTC", - "updated_at": "2015-03-21 18:27:27 UTC", - "milestone_id": 11, - "state": "opened", - "merge_status": "cannot_be_merged", - "target_project_id": 5, - "iid": 1, - "description": "Et voluptas corrupti assumenda temporibus. Architecto cum animi eveniet amet asperiores. Vitae numquam voluptate est natus sit et ad id.", - "position": 0, - "source":{ - "name":"Gitlab Test", - "description":"Aut reprehenderit ut est.", - "web_url":"http://example.com/gitlab-org/gitlab-test", - "avatar_url":null, - "git_ssh_url":"git@example.com:gitlab-org/gitlab-test.git", - "git_http_url":"http://example.com/gitlab-org/gitlab-test.git", - "namespace":"Gitlab Org", - "visibility_level":10, - "path_with_namespace":"gitlab-org/gitlab-test", - "default_branch":"master", - "homepage":"http://example.com/gitlab-org/gitlab-test", - "url":"http://example.com/gitlab-org/gitlab-test.git", - "ssh_url":"git@example.com:gitlab-org/gitlab-test.git", - "http_url":"http://example.com/gitlab-org/gitlab-test.git" - }, - "target": { - "name":"Gitlab Test", - "description":"Aut reprehenderit ut est.", - "web_url":"http://example.com/gitlab-org/gitlab-test", - "avatar_url":null, - "git_ssh_url":"git@example.com:gitlab-org/gitlab-test.git", - "git_http_url":"http://example.com/gitlab-org/gitlab-test.git", - "namespace":"Gitlab Org", - "visibility_level":10, - "path_with_namespace":"gitlab-org/gitlab-test", - "default_branch":"master", - "homepage":"http://example.com/gitlab-org/gitlab-test", - "url":"http://example.com/gitlab-org/gitlab-test.git", - "ssh_url":"git@example.com:gitlab-org/gitlab-test.git", - "http_url":"http://example.com/gitlab-org/gitlab-test.git" - }, - "last_commit": { - "id": "562e173be03b8ff2efb05345d12df18815438a4b", - "message": "Merge branch 'another-branch' into 'master'\n\nCheck in this test\n", - "timestamp": "2015-04-08T21: 00:25-07:00", - "url": "http://example.com/gitlab-org/gitlab-test/commit/562e173be03b8ff2efb05345d12df18815438a4b", - "author": { - "name": "John Smith", - "email": "john@example.com" - } - }, - "work_in_progress": false, - "assignee": { - "name": "User1", - "username": "user1", - "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon" - } - } -} -``` +1. Choose an unused port (for example, `8000`) and start the script: -#### Comment on issue + ```shell + ruby print_http_body.rb 8000 + ``` -**Request header**: +1. In GitLab, add your webhook receiver as `http://my.host:8000/`. -```plaintext -X-Gitlab-Event: Note Hook -``` +1. Select **Test**. You should see something like this in the console: -**Payload example:** - -```json -{ - "object_kind": "note", - "user": { - "id": 1, - "name": "Administrator", - "username": "root", - "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon", - "email": "admin@example.com" - }, - "project_id": 5, - "project":{ - "id": 5, - "name":"Gitlab Test", - "description":"Aut reprehenderit ut est.", - "web_url":"http://example.com/gitlab-org/gitlab-test", - "avatar_url":null, - "git_ssh_url":"git@example.com:gitlab-org/gitlab-test.git", - "git_http_url":"http://example.com/gitlab-org/gitlab-test.git", - "namespace":"Gitlab Org", - "visibility_level":10, - "path_with_namespace":"gitlab-org/gitlab-test", - "default_branch":"master", - "homepage":"http://example.com/gitlab-org/gitlab-test", - "url":"http://example.com/gitlab-org/gitlab-test.git", - "ssh_url":"git@example.com:gitlab-org/gitlab-test.git", - "http_url":"http://example.com/gitlab-org/gitlab-test.git" - }, - "repository":{ - "name":"diaspora", - "url":"git@example.com:mike/diaspora.git", - "description":"", - "homepage":"http://example.com/mike/diaspora" - }, - "object_attributes": { - "id": 1241, - "note": "Hello world", - "noteable_type": "Issue", - "author_id": 1, - "created_at": "2015-05-17 17:06:40 UTC", - "updated_at": "2015-05-17 17:06:40 UTC", - "project_id": 5, - "attachment": null, - "line_code": null, - "commit_id": "", - "noteable_id": 92, - "system": false, - "st_diff": null, - "url": "http://example.com/gitlab-org/gitlab-test/issues/17#note_1241" - }, - "issue": { - "id": 92, - "title": "test", - "assignee_ids": [], - "assignee_id": null, - "author_id": 1, - "project_id": 5, - "created_at": "2015-04-12 14:53:17 UTC", - "updated_at": "2015-04-26 08:28:42 UTC", - "position": 0, - "branch_name": null, - "description": "test", - "milestone_id": null, - "state": "closed", - "iid": 17, - "labels": [ - { - "id": 25, - "title": "Afterpod", - "color": "#3e8068", - "project_id": null, - "created_at": "2019-06-05T14:32:20.211Z", - "updated_at": "2019-06-05T14:32:20.211Z", - "template": false, - "description": null, - "type": "GroupLabel", - "group_id": 4 - }, - { - "id": 86, - "title": "Element", - "color": "#231afe", - "project_id": 4, - "created_at": "2019-06-05T14:32:20.637Z", - "updated_at": "2019-06-05T14:32:20.637Z", - "template": false, - "description": null, - "type": "ProjectLabel", - "group_id": null - } - ] - } -} -``` + ```plaintext + {"before":"077a85dd266e6f3573ef7e9ef8ce3343ad659c4e","after":"95cd4a99e93bc4bbabacfa2cd10e6725b1403c60",<SNIP>} + example.com - - [14/May/2014:07:45:26 EDT] "POST / HTTP/1.1" 200 0 + - -> / + ``` NOTE: -`assignee_id` field is deprecated and now shows the first assignee only. - -#### Comment on code snippet - -**Request header**: - -```plaintext -X-Gitlab-Event: Note Hook -``` - -**Payload example:** - -```json -{ - "object_kind": "note", - "user": { - "id": 1, - "name": "Administrator", - "username": "root", - "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon", - "email": "admin@example.com" - }, - "project_id": 5, - "project":{ - "id": 5, - "name":"Gitlab Test", - "description":"Aut reprehenderit ut est.", - "web_url":"http://example.com/gitlab-org/gitlab-test", - "avatar_url":null, - "git_ssh_url":"git@example.com:gitlab-org/gitlab-test.git", - "git_http_url":"http://example.com/gitlab-org/gitlab-test.git", - "namespace":"Gitlab Org", - "visibility_level":10, - "path_with_namespace":"gitlab-org/gitlab-test", - "default_branch":"master", - "homepage":"http://example.com/gitlab-org/gitlab-test", - "url":"http://example.com/gitlab-org/gitlab-test.git", - "ssh_url":"git@example.com:gitlab-org/gitlab-test.git", - "http_url":"http://example.com/gitlab-org/gitlab-test.git" - }, - "repository":{ - "name":"Gitlab Test", - "url":"http://example.com/gitlab-org/gitlab-test.git", - "description":"Aut reprehenderit ut est.", - "homepage":"http://example.com/gitlab-org/gitlab-test" - }, - "object_attributes": { - "id": 1245, - "note": "Is this snippet doing what it's supposed to be doing?", - "noteable_type": "Snippet", - "author_id": 1, - "created_at": "2015-05-17 18:35:50 UTC", - "updated_at": "2015-05-17 18:35:50 UTC", - "project_id": 5, - "attachment": null, - "line_code": null, - "commit_id": "", - "noteable_id": 53, - "system": false, - "st_diff": null, - "url": "http://example.com/gitlab-org/gitlab-test/snippets/53#note_1245" - }, - "snippet": { - "id": 53, - "title": "test", - "content": "puts 'Hello world'", - "author_id": 1, - "project_id": 5, - "created_at": "2015-04-09 02:40:38 UTC", - "updated_at": "2015-04-09 02:40:38 UTC", - "file_name": "test.rb", - "expires_at": null, - "type": "ProjectSnippet", - "visibility_level": 0 - } -} -``` - -### Merge request events - -Triggered when a new merge request is created, an existing merge request was updated/merged/closed or a commit is added in the source branch. - -**Request header**: - -```plaintext -X-Gitlab-Event: Merge Request Hook -``` - -**Available `object_attributes.action`:** - -- `open` -- `close` -- `reopen` -- `update` -- `approved` -- `unapproved` -- `merge` - -**Payload example:** - -```json -{ - "object_kind": "merge_request", - "user": { - "id": 1, - "name": "Administrator", - "username": "root", - "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon", - "email": "admin@example.com" - }, - "project": { - "id": 1, - "name":"Gitlab Test", - "description":"Aut reprehenderit ut est.", - "web_url":"http://example.com/gitlabhq/gitlab-test", - "avatar_url":null, - "git_ssh_url":"git@example.com:gitlabhq/gitlab-test.git", - "git_http_url":"http://example.com/gitlabhq/gitlab-test.git", - "namespace":"GitlabHQ", - "visibility_level":20, - "path_with_namespace":"gitlabhq/gitlab-test", - "default_branch":"master", - "homepage":"http://example.com/gitlabhq/gitlab-test", - "url":"http://example.com/gitlabhq/gitlab-test.git", - "ssh_url":"git@example.com:gitlabhq/gitlab-test.git", - "http_url":"http://example.com/gitlabhq/gitlab-test.git" - }, - "repository": { - "name": "Gitlab Test", - "url": "http://example.com/gitlabhq/gitlab-test.git", - "description": "Aut reprehenderit ut est.", - "homepage": "http://example.com/gitlabhq/gitlab-test" - }, - "object_attributes": { - "id": 99, - "target_branch": "master", - "source_branch": "ms-viewport", - "source_project_id": 14, - "author_id": 51, - "assignee_id": 6, - "title": "MS-Viewport", - "created_at": "2013-12-03T17:23:34Z", - "updated_at": "2013-12-03T17:23:34Z", - "milestone_id": null, - "state": "opened", - "merge_status": "unchecked", - "target_project_id": 14, - "iid": 1, - "description": "", - "source": { - "name":"Awesome Project", - "description":"Aut reprehenderit ut est.", - "web_url":"http://example.com/awesome_space/awesome_project", - "avatar_url":null, - "git_ssh_url":"git@example.com:awesome_space/awesome_project.git", - "git_http_url":"http://example.com/awesome_space/awesome_project.git", - "namespace":"Awesome Space", - "visibility_level":20, - "path_with_namespace":"awesome_space/awesome_project", - "default_branch":"master", - "homepage":"http://example.com/awesome_space/awesome_project", - "url":"http://example.com/awesome_space/awesome_project.git", - "ssh_url":"git@example.com:awesome_space/awesome_project.git", - "http_url":"http://example.com/awesome_space/awesome_project.git" - }, - "target": { - "name":"Awesome Project", - "description":"Aut reprehenderit ut est.", - "web_url":"http://example.com/awesome_space/awesome_project", - "avatar_url":null, - "git_ssh_url":"git@example.com:awesome_space/awesome_project.git", - "git_http_url":"http://example.com/awesome_space/awesome_project.git", - "namespace":"Awesome Space", - "visibility_level":20, - "path_with_namespace":"awesome_space/awesome_project", - "default_branch":"master", - "homepage":"http://example.com/awesome_space/awesome_project", - "url":"http://example.com/awesome_space/awesome_project.git", - "ssh_url":"git@example.com:awesome_space/awesome_project.git", - "http_url":"http://example.com/awesome_space/awesome_project.git" - }, - "last_commit": { - "id": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7", - "message": "fixed readme", - "timestamp": "2012-01-03T23:36:29+02:00", - "url": "http://example.com/awesome_space/awesome_project/commits/da1560886d4f094c3e6c9ef40349f7d38b5d27d7", - "author": { - "name": "GitLab dev user", - "email": "gitlabdev@dv6700.(none)" - } - }, - "work_in_progress": false, - "url": "http://example.com/diaspora/merge_requests/1", - "action": "open", - "assignee": { - "name": "User1", - "username": "user1", - "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon" - } - }, - "labels": [{ - "id": 206, - "title": "API", - "color": "#ffffff", - "project_id": 14, - "created_at": "2013-12-03T17:15:43Z", - "updated_at": "2013-12-03T17:15:43Z", - "template": false, - "description": "API related issues", - "type": "ProjectLabel", - "group_id": 41 - }], - "changes": { - "updated_by_id": { - "previous": null, - "current": 1 - }, - "updated_at": { - "previous": "2017-09-15 16:50:55 UTC", - "current":"2017-09-15 16:52:00 UTC" - }, - "labels": { - "previous": [{ - "id": 206, - "title": "API", - "color": "#ffffff", - "project_id": 14, - "created_at": "2013-12-03T17:15:43Z", - "updated_at": "2013-12-03T17:15:43Z", - "template": false, - "description": "API related issues", - "type": "ProjectLabel", - "group_id": 41 - }], - "current": [{ - "id": 205, - "title": "Platform", - "color": "#123123", - "project_id": 14, - "created_at": "2013-12-03T17:15:43Z", - "updated_at": "2013-12-03T17:15:43Z", - "template": false, - "description": "Platform related issues", - "type": "ProjectLabel", - "group_id": 41 - }] - } - } -} -``` - -### Wiki Page events - -Triggered when a wiki page is created, updated or deleted. - -**Request Header**: - -```plaintext -X-Gitlab-Event: Wiki Page Hook -``` - -**Payload example**: - -```json -{ - "object_kind": "wiki_page", - "user": { - "id": 1, - "name": "Administrator", - "username": "root", - "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon", - "email": "admin@example.com" - }, - "project": { - "id": 1, - "name": "awesome-project", - "description": "This is awesome", - "web_url": "http://example.com/root/awesome-project", - "avatar_url": null, - "git_ssh_url": "git@example.com:root/awesome-project.git", - "git_http_url": "http://example.com/root/awesome-project.git", - "namespace": "root", - "visibility_level": 0, - "path_with_namespace": "root/awesome-project", - "default_branch": "master", - "homepage": "http://example.com/root/awesome-project", - "url": "git@example.com:root/awesome-project.git", - "ssh_url": "git@example.com:root/awesome-project.git", - "http_url": "http://example.com/root/awesome-project.git" - }, - "wiki": { - "web_url": "http://example.com/root/awesome-project/-/wikis/home", - "git_ssh_url": "git@example.com:root/awesome-project.wiki.git", - "git_http_url": "http://example.com/root/awesome-project.wiki.git", - "path_with_namespace": "root/awesome-project.wiki", - "default_branch": "master" - }, - "object_attributes": { - "title": "Awesome", - "content": "awesome content goes here", - "format": "markdown", - "message": "adding an awesome page to the wiki", - "slug": "awesome", - "url": "http://example.com/root/awesome-project/-/wikis/awesome", - "action": "create" - } -} -``` - -### Pipeline events - -In [GitLab 13.9](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53159) -and later, the pipeline webhook returns only the latest jobs. - -Triggered on status change of Pipeline. - -**Request Header**: - -```plaintext -X-Gitlab-Event: Pipeline Hook -``` - -**Payload example**: - -```json -{ - "object_kind": "pipeline", - "object_attributes":{ - "id": 31, - "ref": "master", - "tag": false, - "sha": "bcbb5ec396a2c0f828686f14fac9b80b780504f2", - "before_sha": "bcbb5ec396a2c0f828686f14fac9b80b780504f2", - "source": "merge_request_event", - "status": "success", - "stages":[ - "build", - "test", - "deploy" - ], - "created_at": "2016-08-12 15:23:28 UTC", - "finished_at": "2016-08-12 15:26:29 UTC", - "duration": 63, - "variables": [ - { - "key": "NESTOR_PROD_ENVIRONMENT", - "value": "us-west-1" - } - ] - }, - "merge_request": { - "id": 1, - "iid": 1, - "title": "Test", - "source_branch": "test", - "source_project_id": 1, - "target_branch": "master", - "target_project_id": 1, - "state": "opened", - "merge_status": "can_be_merged", - "url": "http://192.168.64.1:3005/gitlab-org/gitlab-test/merge_requests/1" - }, - "user":{ - "id": 1, - "name": "Administrator", - "username": "root", - "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon", - "email": "user_email@gitlab.com" - }, - "project":{ - "id": 1, - "name": "Gitlab Test", - "description": "Atque in sunt eos similique dolores voluptatem.", - "web_url": "http://192.168.64.1:3005/gitlab-org/gitlab-test", - "avatar_url": null, - "git_ssh_url": "git@192.168.64.1:gitlab-org/gitlab-test.git", - "git_http_url": "http://192.168.64.1:3005/gitlab-org/gitlab-test.git", - "namespace": "Gitlab Org", - "visibility_level": 20, - "path_with_namespace": "gitlab-org/gitlab-test", - "default_branch": "master" - }, - "commit":{ - "id": "bcbb5ec396a2c0f828686f14fac9b80b780504f2", - "message": "test\n", - "timestamp": "2016-08-12T17:23:21+02:00", - "url": "http://example.com/gitlab-org/gitlab-test/commit/bcbb5ec396a2c0f828686f14fac9b80b780504f2", - "author":{ - "name": "User", - "email": "user@gitlab.com" - } - }, - "builds":[ - { - "id": 380, - "stage": "deploy", - "name": "production", - "status": "skipped", - "created_at": "2016-08-12 15:23:28 UTC", - "started_at": null, - "finished_at": null, - "when": "manual", - "manual": true, - "allow_failure": false, - "user":{ - "id": 1, - "name": "Administrator", - "username": "root", - "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon", - "email": "admin@example.com" - }, - "runner": null, - "artifacts_file":{ - "filename": null, - "size": null - }, - "environment": { - "name": "production", - "action": "start", - "deployment_tier": "production" - } - }, - { - "id": 377, - "stage": "test", - "name": "test-image", - "status": "success", - "created_at": "2016-08-12 15:23:28 UTC", - "started_at": "2016-08-12 15:26:12 UTC", - "finished_at": null, - "when": "on_success", - "manual": false, - "allow_failure": false, - "user":{ - "id": 1, - "name": "Administrator", - "username": "root", - "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon", - "email": "admin@example.com" - }, - "runner": { - "id": 380987, - "description": "shared-runners-manager-6.gitlab.com", - "active": true, - "runner_type": "instance_type", - "is_shared": true, - "tags": [ - "linux", - "docker", - "shared-runner" - ] - }, - "artifacts_file":{ - "filename": null, - "size": null - }, - "environment": null - }, - { - "id": 378, - "stage": "test", - "name": "test-build", - "status": "success", - "created_at": "2016-08-12 15:23:28 UTC", - "started_at": "2016-08-12 15:26:12 UTC", - "finished_at": "2016-08-12 15:26:29 UTC", - "when": "on_success", - "manual": false, - "allow_failure": false, - "user":{ - "id": 1, - "name": "Administrator", - "username": "root", - "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon", - "email": "admin@example.com" - }, - "runner": { - "id":380987, - "description":"shared-runners-manager-6.gitlab.com", - "active":true, - "runner_type": "instance_type", - "is_shared": true, - "tags": [ - "linux", - "docker" - ] - }, - "artifacts_file":{ - "filename": null, - "size": null - }, - "environment": null - }, - { - "id": 376, - "stage": "build", - "name": "build-image", - "status": "success", - "created_at": "2016-08-12 15:23:28 UTC", - "started_at": "2016-08-12 15:24:56 UTC", - "finished_at": "2016-08-12 15:25:26 UTC", - "when": "on_success", - "manual": false, - "allow_failure": false, - "user":{ - "id": 1, - "name": "Administrator", - "username": "root", - "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon", - "email": "admin@example.com" - }, - "runner": { - "id": 380987, - "description": "shared-runners-manager-6.gitlab.com", - "active": true, - "runner_type": "instance_type", - "is_shared": true, - "tags": [ - "linux", - "docker" - ] - }, - "artifacts_file":{ - "filename": null, - "size": null - }, - "environment": null - }, - { - "id": 379, - "stage": "deploy", - "name": "staging", - "status": "created", - "created_at": "2016-08-12 15:23:28 UTC", - "started_at": null, - "finished_at": null, - "when": "on_success", - "manual": false, - "allow_failure": false, - "user":{ - "id": 1, - "name": "Administrator", - "username": "root", - "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon", - "email": "admin@example.com" - }, - "runner": null, - "artifacts_file":{ - "filename": null, - "size": null - }, - "environment": { - "name": "staging", - "action": "start", - "deployment_tier": "staging" - } - } - ] -} -``` - -### Job events - -Triggered on status change of a job. - -**Request Header**: - -```plaintext -X-Gitlab-Event: Job Hook -``` - -**Payload example**: - -```json -{ - "object_kind": "build", - "ref": "gitlab-script-trigger", - "tag": false, - "before_sha": "2293ada6b400935a1378653304eaf6221e0fdb8f", - "sha": "2293ada6b400935a1378653304eaf6221e0fdb8f", - "build_id": 1977, - "build_name": "test", - "build_stage": "test", - "build_status": "created", - "build_created_at": "2021-02-23T02:41:37.886Z", - "build_started_at": null, - "build_finished_at": null, - "build_duration": null, - "build_allow_failure": false, - "build_failure_reason": "script_failure", - "pipeline_id": 2366, - "project_id": 380, - "project_name": "gitlab-org/gitlab-test", - "user": { - "id": 3, - "name": "User", - "email": "user@gitlab.com", - "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon", - }, - "commit": { - "id": 2366, - "sha": "2293ada6b400935a1378653304eaf6221e0fdb8f", - "message": "test\n", - "author_name": "User", - "author_email": "user@gitlab.com", - "status": "created", - "duration": null, - "started_at": null, - "finished_at": null - }, - "repository": { - "name": "gitlab_test", - "description": "Atque in sunt eos similique dolores voluptatem.", - "homepage": "http://192.168.64.1:3005/gitlab-org/gitlab-test", - "git_ssh_url": "git@192.168.64.1:gitlab-org/gitlab-test.git", - "git_http_url": "http://192.168.64.1:3005/gitlab-org/gitlab-test.git", - "visibility_level": 20 - }, - "runner": { - "active": true, - "runner_type": "project_type", - "is_shared": false, - "id": 380987, - "description": "shared-runners-manager-6.gitlab.com", - "tags": [ - "linux", - "docker" - ] - }, - "environment": null -} -``` - -Note that `commit.id` is the ID of the pipeline, not the ID of the commit. - -### Deployment events - -Triggered when a deployment: - -- Starts ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41214) in GitLab 13.5.) -- Succeeds -- Fails -- Is cancelled - -**Request Header**: - -```plaintext -X-Gitlab-Event: Deployment Hook -``` - -**Payload example**: - -```json -{ - "object_kind": "deployment", - "status": "success", - "status_changed_at":"2021-04-28 21:50:00 +0200", - "deployment_id": 15, - "deployable_id": 796, - "deployable_url": "http://10.126.0.2:3000/root/test-deployment-webhooks/-/jobs/796", - "environment": "staging", - "project": { - "id": 30, - "name": "test-deployment-webhooks", - "description": "", - "web_url": "http://10.126.0.2:3000/root/test-deployment-webhooks", - "avatar_url": null, - "git_ssh_url": "ssh://vlad@10.126.0.2:2222/root/test-deployment-webhooks.git", - "git_http_url": "http://10.126.0.2:3000/root/test-deployment-webhooks.git", - "namespace": "Administrator", - "visibility_level": 0, - "path_with_namespace": "root/test-deployment-webhooks", - "default_branch": "master", - "ci_config_path": "", - "homepage": "http://10.126.0.2:3000/root/test-deployment-webhooks", - "url": "ssh://vlad@10.126.0.2:2222/root/test-deployment-webhooks.git", - "ssh_url": "ssh://vlad@10.126.0.2:2222/root/test-deployment-webhooks.git", - "http_url": "http://10.126.0.2:3000/root/test-deployment-webhooks.git" - }, - "short_sha": "279484c0", - "user": { - "id": 1, - "name": "Administrator", - "username": "root", - "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", - "email": "admin@example.com" - }, - "user_url": "http://10.126.0.2:3000/root", - "commit_url": "http://10.126.0.2:3000/root/test-deployment-webhooks/-/commit/279484c09fbe69ededfced8c1bb6e6d24616b468", - "commit_title": "Add new file" -} -``` - -Note that `deployable_id` is the ID of the CI job. - -### Group member events **(PREMIUM)** - -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/260347) in GitLab 13.7. - -Member events are triggered when: - -- A user is added as a group member -- The access level of a user has changed -- The expiration date for user access has been updated -- A user has been removed from the group - -#### Add member to group - -**Request Header**: - -```plaintext -X-Gitlab-Event: Member Hook -``` - -**Payload example**: - -```json -{ - "created_at": "2020-12-11T04:57:22Z", - "updated_at": "2020-12-11T04:57:22Z", - "group_name": "webhook-test", - "group_path": "webhook-test", - "group_id": 100, - "user_username": "test_user", - "user_name": "Test User", - "user_email": "testuser@webhooktest.com", - "user_id": 64, - "group_access": "Guest", - "group_plan": null, - "expires_at": "2020-12-14T00:00:00Z", - "event_name": "user_add_to_group" -} -``` - -#### Update member access level or expiration date - -**Request Header**: - -```plaintext -X-Gitlab-Event: Member Hook -``` - -**Payload example**: - -```json -{ - "created_at": "2020-12-11T04:57:22Z", - "updated_at": "2020-12-12T08:48:19Z", - "group_name": "webhook-test", - "group_path": "webhook-test", - "group_id": 100, - "user_username": "test_user", - "user_name": "Test User", - "user_email": "testuser@webhooktest.com", - "user_id": 64, - "group_access": "Developer", - "group_plan": null, - "expires_at": "2020-12-20T00:00:00Z", - "event_name": "user_update_for_group" -} -``` - -#### Remove member from group - -**Request Header**: - -```plaintext -X-Gitlab-Event: Member Hook -``` - -**Payload example**: - -```json -{ - "created_at": "2020-12-11T04:57:22Z", - "updated_at": "2020-12-12T08:52:34Z", - "group_name": "webhook-test", - "group_path": "webhook-test", - "group_id": 100, - "user_username": "test_user", - "user_name": "Test User", - "user_email": "testuser@webhooktest.com", - "user_id": 64, - "group_access": "Guest", - "group_plan": null, - "expires_at": "2020-12-14T00:00:00Z", - "event_name": "user_remove_from_group" -} -``` - -### Subgroup events **(PREMIUM)** - -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/260419) in GitLab 13.9. - -Subgroup events are triggered when: - -- A [subgroup is created in a group](#subgroup-created-in-a-group) -- A [subgroup is removed from a group](#subgroup-removed-from-a-group) - -#### Subgroup created in a group - -**Request Header**: - -```plaintext -X-Gitlab-Event: Subgroup Hook -``` - -**Payload example**: - -```json -{ - - "created_at": "2021-01-20T09:40:12Z", - "updated_at": "2021-01-20T09:40:12Z", - "event_name": "subgroup_create", - "name": "subgroup1", - "path": "subgroup1", - "full_path": "group1/subgroup1", - "group_id": 10, - "parent_group_id": 7, - "parent_name": "group1", - "parent_path": "group1", - "parent_full_path": "group1" - -} -``` - -#### Subgroup removed from a group - -**Request Header**: - -```plaintext -X-Gitlab-Event: Subgroup Hook -``` - -**Payload example**: - -```json -{ - - "created_at": "2021-01-20T09:40:12Z", - "updated_at": "2021-01-20T09:40:12Z", - "event_name": "subgroup_destroy", - "name": "subgroup1", - "path": "subgroup1", - "full_path": "group1/subgroup1", - "group_id": 10, - "parent_group_id": 7, - "parent_name": "group1", - "parent_path": "group1", - "parent_full_path": "group1" +You may need to [allow requests to the local network](../../../security/webhooks.md) for this +receiver to be added. -} -``` +## Validate payloads by using a secret token -NOTE: -Webhooks for when a [subgroup is removed from a group](#subgroup-removed-from-a-group) are not triggered when a [subgroup is transferred to a new parent group](../../group/index.md#transfer-a-group) +You can specify a secret token to validate received payloads. +The token is sent with the hook request in the +`X-Gitlab-Token` HTTP header. Your webhook endpoint can check the token to verify +that the request is legitimate. -### Feature Flag events +## Verify an SSL certificate -Triggered when a feature flag is turned on or off. +By default, the SSL certificate of the webhook endpoint is verified based on +an internal list of Certificate Authorities. This means the certificate cannot +be self-signed. -**Request Header**: +You can turn off SSL verification in the [webhook settings](#configure-a-webhook) +in your GitLab projects. -```plaintext -X-Gitlab-Event: Feature Flag Hook -``` +## Filter push events by branch -**Payload example**: - -```json -{ - "object_kind": "feature_flag", - "project": { - "id": 1, - "name":"Gitlab Test", - "description":"Aut reprehenderit ut est.", - "web_url":"http://example.com/gitlabhq/gitlab-test", - "avatar_url":null, - "git_ssh_url":"git@example.com:gitlabhq/gitlab-test.git", - "git_http_url":"http://example.com/gitlabhq/gitlab-test.git", - "namespace":"GitlabHQ", - "visibility_level":20, - "path_with_namespace":"gitlabhq/gitlab-test", - "default_branch":"master", - "ci_config_path": null, - "homepage":"http://example.com/gitlabhq/gitlab-test", - "url":"http://example.com/gitlabhq/gitlab-test.git", - "ssh_url":"git@example.com:gitlabhq/gitlab-test.git", - "http_url":"http://example.com/gitlabhq/gitlab-test.git" - }, - "user": { - "id": 1, - "name": "Administrator", - "username": "root", - "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", - "email": "admin@example.com" - }, - "user_url": "http://example.com/root", - "object_attributes": { - "id": 6, - "name": "test-feature-flag", - "description": "test-feature-flag-description", - "active": true - } -} -``` +> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/20338) in GitLab 11.3. -### Release events +Push events can be filtered by branch using a branch name or wildcard pattern +to limit which push events are sent to your webhook endpoint. By default, +all push events are sent to your webhook endpoint. You can configure branch filtering +in the [webhook settings](#configure-a-webhook) in your project. -Triggered when a release is created or updated. +## HTTP responses for your endpoint -**Request Header**: +If you are writing your own endpoint (web server) to receive +GitLab webhooks, keep in mind the following: -```plaintext -X-Gitlab-Event: Release Hook -``` +- Your endpoint should send its HTTP response as fast as possible. If the response + takes longer than the configured timeout, GitLab assumes the hook failed and retries it. + To customize the timeout, see + [Webhook fails or multiple webhook requests are triggered](#webhook-fails-or-multiple-webhook-requests-are-triggered). +- Your endpoint should ALWAYS return a valid HTTP response. If not, + GitLab assumes the hook failed and retries it. + Most HTTP libraries take care of the response for you automatically but if + you are writing a low-level hook, this is important to remember. +- GitLab ignores the HTTP status code returned by your endpoint. -**Available `object_attributes.action`:** - -- `create` -- `update` - -**Payload example**: - -```json -{ - "id": 1, - "created_at": "2020-11-02 12:55:12 UTC", - "description": "v1.0 has been released", - "name": "v1.1", - "released_at": "2020-11-02 12:55:12 UTC", - "tag": "v1.1", - "object_kind": "release", - "project": { - "id": 2, - "name": "release-webhook-example", - "description": "", - "web_url": "https://example.com/gitlab-org/release-webhook-example", - "avatar_url": null, - "git_ssh_url": "ssh://git@example.com/gitlab-org/release-webhook-example.git", - "git_http_url": "https://example.com/gitlab-org/release-webhook-example.git", - "namespace": "Gitlab", - "visibility_level": 0, - "path_with_namespace": "gitlab-org/release-webhook-example", - "default_branch": "master", - "ci_config_path": null, - "homepage": "https://example.com/gitlab-org/release-webhook-example", - "url": "ssh://git@example.com/gitlab-org/release-webhook-example.git", - "ssh_url": "ssh://git@example.com/gitlab-org/release-webhook-example.git", - "http_url": "https://example.com/gitlab-org/release-webhook-example.git" - }, - "url": "https://example.com/gitlab-org/release-webhook-example/-/releases/v1.1", - "action": "create", - "assets": { - "count": 5, - "links": [ - { - "id": 1, - "external": true, - "link_type": "other", - "name": "Changelog", - "url": "https://example.net/changelog" - } - ], - "sources": [ - { - "format": "zip", - "url": "https://example.com/gitlab-org/release-webhook-example/-/archive/v1.1/release-webhook-example-v1.1.zip" - }, - { - "format": "tar.gz", - "url": "https://example.com/gitlab-org/release-webhook-example/-/archive/v1.1/release-webhook-example-v1.1.tar.gz" - }, - { - "format": "tar.bz2", - "url": "https://example.com/gitlab-org/release-webhook-example/-/archive/v1.1/release-webhook-example-v1.1.tar.bz2" - }, - { - "format": "tar", - "url": "https://example.com/gitlab-org/release-webhook-example/-/archive/v1.1/release-webhook-example-v1.1.tar" - } - ] - }, - "commit": { - "id": "ee0a3fb31ac16e11b9dbb596ad16d4af654d08f8", - "message": "Release v1.1", - "title": "Release v1.1", - "timestamp": "2020-10-31T14:58:32+11:00", - "url": "https://example.com/gitlab-org/release-webhook-example/-/commit/ee0a3fb31ac16e11b9dbb596ad16d4af654d08f8", - "author": { - "name": "Example User", - "email": "user@example.com" - } - } -} -``` +## How image URLs are displayed in the webhook body -## Image URL rewriting +> Introduced in GitLab 11.2. -From GitLab 11.2, simple image references are rewritten to use an absolute URL -in webhooks. So if an image, merge request, comment, or wiki page has this in -its description: +Relative image references are rewritten to use an absolute URL +in the body of a webhook. +For example, if an image, merge request, comment, or wiki page includes the +following image reference: ```markdown ![image](/uploads/$sha/image.png) ``` -It appears in the webhook body as follows assuming that: +If: - GitLab is installed at `gitlab.example.com`. - The project is at `example-group/example-project`. +The reference is rewritten in the webhook body as follows: + ```markdown ![image](https://gitlab.example.com/example-group/example-project/uploads/$sha/image.png) ``` -This doesn't rewrite URLs that already are pointing to HTTP, HTTPS, or -protocol-relative URLs. It also doesn't rewrite image URLs using advanced -Markdown features, like link labels. +Image URLs are not rewritten if: -## Testing webhooks +- They already point to HTTP, HTTPS, or + protocol-relative URLs. +- They use advanced Markdown features like link labels. -You can trigger the webhook manually. Sample data from the project is used. -For example, for triggering `Push Events` your project should have at least one commit. +## Events -![Webhook testing](img/webhook_testing.png) +For more information about supported events for Webhooks, go to [Webhook events](webhook_events.md). ## Troubleshoot webhooks -GitLab stores each perform of the webhook. -You can find records for last 2 days in "Recent Deliveries" section on the edit page of each webhook. +GitLab records the history of each webhook request. +You can view requests made in the last 2 days in the **Recent events** table. -![Recent deliveries](img/webhook_logs.png) +To view the table: -In this section you can see: +1. In your project, on the left sidebar, select **Settings > Webhooks**. +1. Scroll down to the webhooks. +1. Select **Edit** for the webhook you want to view. -- HTTP status code (green for `200-299` codes, red for the others, `internal error` for failed deliveries). -- Triggered event. -- A time when the event was called. -- Elapsed time of the request. +The table includes the following details about each request: -If you need more information about execution, you can click `View details` link. -On this page, you can see data that GitLab sends (request headers and body) and data that it received (response headers and body). +- HTTP status code (green for `200`-`299` codes, red for the others, and `internal error` for failed deliveries) +- Triggered event +- Elapsed time of the request +- Relative time for when the request was made -From this page, you can repeat delivery with the same data by clicking `Resend Request` button. +![Recent deliveries](img/webhook_logs.png) NOTE: -This history is unavailable for Group-level webhooks. For more information, read +The **Recent events** table is unavailable for group-level webhooks. For more information, read [issue #325642](https://gitlab.com/gitlab-org/gitlab/-/issues/325642). +Each webhook event has a corresponding **Details** page. This page details the data that GitLab sent (request headers and body) and received (response headers and body). +To view the **Details** page, select **View details** for the webhook event. + +To repeat the delivery with the same data, select **Resend Request**. + NOTE: -If URL or secret token of the webhook were updated, data is delivered to the new address. +If you update the URL or secret token of the webhook, data is delivered to the new address. ### Webhook fails or multiple webhook requests are triggered -When GitLab sends a webhook, it expects a response in 10 seconds by default. If it does not receive -one, it retries the webhook. If the endpoint doesn't send its HTTP response within those 10 seconds, -GitLab may decide the hook failed and retry it. +When GitLab sends a webhook, it expects a response in 10 seconds by default. +If the endpoint doesn't send an HTTP response in those 10 seconds, +GitLab may assume the webhook failed and retry it. -If your webhooks are failing or you are receiving multiple requests, you can try changing the -default value. You can do this by uncommenting or adding the following setting to your -`/etc/gitlab/gitlab.rb` file: +If your webhooks are failing or you are receiving multiple requests, +you can try changing the default timeout value. +In your `/etc/gitlab/gitlab.rb` file, uncomment or add the following setting: ```ruby gitlab_rails['webhook_timeout'] = 10 @@ -1809,48 +233,11 @@ gitlab_rails['webhook_timeout'] = 10 ### Unable to get local issuer certificate -When SSL verification is enabled, this error indicates that GitLab isn't able to verify the SSL certificate of the webhook endpoint. -Typically, this is because the root certificate isn't issued by a trusted certification authority as +When SSL verification is enabled, you might get an error that GitLab cannot +verify the SSL certificate of the webhook endpoint. +Typically, this error occurs because the root certificate isn't +issued by a trusted certification authority as determined by [CAcert.org](http://www.cacert.org/). -Should that not be the case, consider using [SSL Checker](https://www.sslshopper.com/ssl-checker.html) to identify faults. -Missing intermediate certificates are a common point of verification failure. - -## Example webhook receiver - -If you want to see GitLab webhooks in action for testing purposes you can use -a simple echo script running in a console session. For the following script to -work you need to have Ruby installed. - -Save the following file as `print_http_body.rb`: - -```ruby -require 'webrick' - -server = WEBrick::HTTPServer.new(:Port => ARGV.first) -server.mount_proc '/' do |req, res| - puts req.body -end - -trap 'INT' do - server.shutdown -end -server.start -``` - -Pick an unused port (for example, `8000`) and start the script: `ruby print_http_body.rb -8000`. Then add your server as a webhook receiver in GitLab as -`http://my.host:8000/`. - -When you press 'Test' in GitLab, you should see something like this in the -console: - -```plaintext -{"before":"077a85dd266e6f3573ef7e9ef8ce3343ad659c4e","after":"95cd4a99e93bc4bbabacfa2cd10e6725b1403c60",<SNIP>} -example.com - - [14/May/2014:07:45:26 EDT] "POST / HTTP/1.1" 200 0 -- -> / -``` - -NOTE: -You may need to [allow requests to the local network](../../../security/webhooks.md) for this -receiver to be added. +If that is not the case, consider using [SSL Checker](https://www.sslshopper.com/ssl-checker.html) to identify faults. +Missing intermediate certificates are common causes of verification failure. |