# Webhooks

> 原文：[https://docs.gitlab.com/ee/user/project/integrations/webhooks.html](https://docs.gitlab.com/ee/user/project/integrations/webhooks.html)

*   [Overview](#overview)
*   [Use-cases](#use-cases)
*   [Webhook endpoint tips](#webhook-endpoint-tips)
*   [Secret token](#secret-token)
*   [SSL verification](#ssl-verification)
*   [Branch filtering](#branch-filtering)
*   [Events](#events)
    *   [Push events](#push-events)
    *   [Tag events](#tag-events)
    *   [Issue events](#issue-events)
    *   [Comment events](#comment-events)
        *   [Comment on commit](#comment-on-commit)
        *   [Comment on merge request](#comment-on-merge-request)
        *   [Comment on issue](#comment-on-issue)
        *   [Comment on code snippet](#comment-on-code-snippet)
    *   [Merge request events](#merge-request-events)
    *   [Wiki Page events](#wiki-page-events)
    *   [Pipeline events](#pipeline-events)
    *   [Job events](#job-events)
*   [Image URL rewriting](#image-url-rewriting)
*   [Testing webhooks](#testing-webhooks)
*   [Troubleshoot webhooks](#troubleshoot-webhooks)
    *   [Receiving duplicate or multiple webhook requests triggered by one event](#receiving-duplicate-or-multiple-webhook-requests-triggered-by-one-event)
    *   [Troubleshooting: “Unable to get local issuer certificate”](#troubleshooting-unable-to-get-local-issuer-certificate)
*   [Example webhook receiver](#example-webhook-receiver)

# Webhooks[](#webhooks "Permalink")

> **注意：**从 GitLab 8.5 开始：
> 
> *   不推荐使用`repository`密钥，而推荐使用`project`密钥
> *   不推荐使用`project.ssh_url`密钥，而推荐使用`project.git_ssh_url`密钥
> *   不推荐使用`project.http_url`键，而推荐使用`project.git_http_url`键
> 
> **注意：**从 GitLab 11.1 开始，一个月后会自动删除 Webhooks 的日志.
> 
> **注意：**从 GitLab 11.2 开始：
> 
> *   重写问题，合并请求，评论和 Wiki 页面的`description`字段，以便简单的 Markdown 图像引用（如`![](/uploads/...)` ）将其目标 URL 更改为绝对 URL. 有关更多详细信息，请参见[图像 URL 重写](#image-url-rewriting) .

通过项目 webhooks，您可以在例如推送新代码或创建新问题时触发 URL. 您可以将 webhook 配置为侦听特定事件，例如推送，问题或合并请求. GitLab 会将带有数据的 POST 请求发送到 webhook URL.

在大多数情况下，您需要设置自己的[Webhook 接收器](#example-webhook-receiver)以从 GitLab 接收信息，然后根据需要将其发送到另一个应用程序. 我们已经有一个[内置接收器，](slack.html)用于*每个项目*发送[Slack](https://api.slack.com/incoming-webhooks)通知.

## Overview[](#overview "Permalink")

[Webhooks](https://en.wikipedia.org/wiki/Webhook)是" *用户定义的 HTTP 回调* ". 它们通常是由某些事件触发的，例如将代码推送到存储库或将评论发布到博客. 发生该事件时，源应用程序向为 Webhook 配置的 URI 发出 HTTP 请求. 采取的措施可能是任何事情. 常见用途是触发具有持续集成系统的构建或通知错误跟踪系统.

Webhooks 可用于更新外部问题跟踪器，触发 CI 作业，更新备份镜像，甚至部署到您的生产服务器. 他们**每个项目**可以 GitLab 社区版，以及**每个项目和每个组** **GitLab 企业版** .

通过转到项目的**设置➔Webhooks**导航到 webhooks 页面.

**注意：**在 GitLab.com 上，每个项目和每个组的[最大 Webhooks 数量](../../../user/gitlab_com/index.html#maximum-number-of-webhooks)是有限的.

## Use-cases[](#use-cases "Permalink")

*   您可以在 GitLab 中设置一个 Webhook，以在每次作业失败时向[Slack](https://api.slack.com/incoming-webhooks)发送通知.
*   每当在 GitLab 中为特定项目或组创建问题时，您都可以[与 Twilio 集成以通过 SMS 收到通知](https://www.datadoghq.com/blog/send-alerts-sms-customizable-webhooks-twilio/)
*   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[](#webhook-endpoint-tips "Permalink")

如果您正在编写自己的将接收 GitLab webhooks 的端点（Web 服务器），请记住以下几点：

*   您的端点应尽快发送其 HTTP 响应. 如果等待时间太长，GitLab 可能会确定挂钩失败并重试.
*   您的端点应始终返回有效的 HTTP 响应. 如果您不这样做，则 GitLab 会认为挂钩失败并重试. 大多数 HTTP 库会自动为您处理此问题，但是如果您正在编写低级钩子，记住这一点很重要.
*   GitLab 会忽略端点返回的 HTTP 状态代码.

## Secret token[](#secret-token "Permalink")

如果您指定一个秘密令牌，它将与挂钩请求一起在`X-Gitlab-Token` HTTP 标头中发送. 您的 webhook 端点可以检查以验证请求是否合法.

## SSL verification[](#ssl-verification "Permalink")

默认情况下，将基于证书颁发机构的内部列表来验证 webhook 端点的 SSL 证书，这意味着该证书无法进行自签名.

您可以在 GitLab 项目的 webhook 设置中将其关闭.

[![SSL Verification](img/e7d35854d0a726fbc4756cca4de4bf77.png)](img/webhooks_ssl.png)

## Branch filtering[](#branch-filtering "Permalink")

在 GitLab 11.3 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/20338) .

可以使用分支名称或通配符模式按分支过滤推送事件，以限制将哪些推送事件发送到您的 Webhook 端点. 默认情况下，该字段为空白，导致所有推送事件都发送到您的 Webhook 端点.

## Events[](#events "Permalink")

下面介绍了受支持的事件.

### Push events[](#push-events "Permalink")

当您推送到存储库时（推送标签时除外）触发.

**注意：**一次推送超过 20 个提交时，出于性能原因， `commits` webhook 属性将仅包含前 20 个. 加载详细的提交数据非常昂贵. 请注意，尽管`commits`属性中仅存在 20 个提交，但`total_commits_count`属性将包含实际总数.

另外，如果单个推送包含三个以上分支的更改（默认情况下，取决于[`push_event_hooks_limit`设置](../../../api/settings.html#list-of-settings-that-can-be-accessed-via-api-calls) ），则不会执行此挂钩.

**请求标头**:

```
X-Gitlab-Event: Push Hook 
```

**要求正文：**

```
{  "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  } 
```

### Tag events[](#tag-events "Permalink")

在创建（或删除）存储库标签时触发.

**注意：**如果单个推送包含三个以上的更改（默认情况下，取决于[`push_event_hooks_limit`设置](../../../api/settings.html#list-of-settings-that-can-be-accessed-via-api-calls) ），则不会执行此挂钩.

**请求标头**:

```
X-Gitlab-Event: Tag Push Hook 
```

**要求正文：**

```
{  "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  } 
```

### Issue events[](#issue-events "Permalink")

在创建新问题或更新/关闭/重新打开现有问题时触发.

**请求标头**:

```
X-Gitlab-Event: Issue Hook 
```

**要求正文：**

```
{  "object_kind":  "issue",  "event_type":  "issue",  "user":  {  "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,  "human_total_time_spent":  null,  "human_time_estimate":  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  }]  }  }  } 
```

> **注意** ：不赞成使用`assignee`和`assignee_id`键，现在仅显示第一个受让人.

### Comment events[](#comment-events "Permalink")

在对提交，合并请求，问题和代码段进行新注释时触发. 音符数据将被存储在`object_attributes` （如`note` ， `noteable_type` ）. 有效负载还将包括有关注释目标的信息. 例如，对问题的评论将在`issue`密钥下包括特定的问题信息. 有效的目标类型：

*   `commit`
*   `merge_request`
*   `issue`
*   `snippet`

#### Comment on commit[](#comment-on-commit "Permalink")

**Request header**:

```
X-Gitlab-Event: Note Hook 
```

**要求正文：**

```
{  "object_kind":  "note",  "user":  {  "name":  "Administrator",  "username":  "root",  "avatar_url":  "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon"  },  "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"  }  }  } 
```

#### Comment on merge request[](#comment-on-merge-request "Permalink")

**请求标头**:

```
X-Gitlab-Event: Note Hook 
```

**要求正文：**

```
{  "object_kind":  "note",  "user":  {  "name":  "Administrator",  "username":  "root",  "avatar_url":  "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon"  },  "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"  }  }  } 
```

#### Comment on issue[](#comment-on-issue "Permalink")

**请求标头**:

```
X-Gitlab-Event: Note Hook 
```

**要求正文：**

```
{  "object_kind":  "note",  "user":  {  "name":  "Administrator",  "username":  "root",  "avatar_url":  "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon"  },  "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  }  ],  }  } 
```

> **注意** ：不建议使用`assignee_id`字段，现在仅显示第一个受让人.

#### Comment on code snippet[](#comment-on-code-snippet "Permalink")

**请求标头**:

```
X-Gitlab-Event: Note Hook 
```

**要求正文：**

```
{  "object_kind":  "note",  "user":  {  "name":  "Administrator",  "username":  "root",  "avatar_url":  "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon"  },  "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[](#merge-request-events "Permalink")

在创建新的合并请求，更新/合并/关闭现有合并请求或在源分支中添加提交时触发.

**请求标头**:

```
X-Gitlab-Event: Merge Request Hook 
```

**要求正文：**

```
{  "object_kind":  "merge_request",  "user":  {  "name":  "Administrator",  "username":  "root",  "avatar_url":  "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon"  },  "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[](#wiki-page-events "Permalink")

在创建，更新或删除 Wiki 页面时触发.

**请求标题**:

```
X-Gitlab-Event: Wiki Page Hook 
```

**请求正文**:

```
{  "object_kind":  "wiki_page",  "user":  {  "name":  "Administrator",  "username":  "root",  "avatar_url":  "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon"  },  "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[](#pipeline-events "Permalink")

在管道状态更改时触发.

**请求标题**:

```
X-Gitlab-Event: Pipeline Hook 
```

**请求正文**:

```
{  "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":{  "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":{  "name":  "Administrator",  "username":  "root",  "avatar_url":  "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"  },  "runner":  null,  "artifacts_file":{  "filename":  null,  "size":  null  }  },  {  "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":{  "name":  "Administrator",  "username":  "root",  "avatar_url":  "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"  },  "runner":  {  "id":380987,  "description":"shared-runners-manager-6.gitlab.com",  "active":true,  "is_shared":true  },  "artifacts_file":{  "filename":  null,  "size":  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":{  "name":  "Administrator",  "username":  "root",  "avatar_url":  "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"  },  "runner":  {  "id":380987,  "description":"shared-runners-manager-6.gitlab.com",  "active":true,  "is_shared":true  },  "artifacts_file":{  "filename":  null,  "size":  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":{  "name":  "Administrator",  "username":  "root",  "avatar_url":  "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"  },  "runner":  {  "id":380987,  "description":"shared-runners-manager-6.gitlab.com",  "active":true,  "is_shared":true  },  "artifacts_file":{  "filename":  null,  "size":  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":{  "name":  "Administrator",  "username":  "root",  "avatar_url":  "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"  },  "runner":  null,  "artifacts_file":{  "filename":  null,  "size":  null  }  }  ]  } 
```

### Job events[](#job-events "Permalink")

在工作状态更改时触发.

**请求标题**:

```
X-Gitlab-Event: Job Hook 
```

**请求正文**:

```
{  "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_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,  "is_shared":  false,  "id":  380987,  "description":  "shared-runners-manager-6.gitlab.com"  }  } 
```

请注意， `commit.id`是管道的 ID，而不是提交的 ID.

## Image URL rewriting[](#image-url-rewriting "Permalink")

从 GitLab 11.2 开始，简单的图像引用被重写为在 webhooks 中使用绝对 URL. 因此，如果图像，合并请求，评论或维基页面的描述中包含以下内容：

```
![image](/uploads/$sha/image.png) 
```

它将显示在 webhook 主体中，如下所示（假设 GitLab 安装在`gitlab.example.com` ，并且该项目位于`example-group/example-project` ）：

```
![image](https://gitlab.example.com/example-group/example-project/uploads/$sha/image.png) 
```

这不会重写已经指向 HTTP，HTTPS 或协议相对 URL 的 URL. 它还不会使用链接标记之类的高级 Markdown 功能重写图像 URL.

## Testing webhooks[](#testing-webhooks "Permalink")

您可以手动触发 Webhook. 将使用项目中的样本数据. >例如：要触发" `Push Events`您的项目应至少提交一次.

[![Webhook testing](img/cee9b8bcba36170c0ae5df4747bb8c44.png)](img/webhook_testing.png)

## Troubleshoot webhooks[](#troubleshoot-webhooks "Permalink")

manbetx 客户端打不开存储 webhook 的每个执行. 您可以在每个 Webhook 的编辑页面上的"最近发送"部分中找到最近 2 天的记录.

[![Recent deliveries](img/78dac22706dcca5ce3855d23987289ea.png)](img/webhook_logs.png)

在本部分中，您可以看到 HTTP 状态代码（绿色表示 200-299 代码，红色表示其他代码，传递失败的`internal error` ），触发的事件，事件被调用的时间，请求的经过时间.

如果需要有关执行的更多信息，可以单击`View details`链接. 在此页面上，您可以查看 GitLab 发送的数据（请求标头和正文）和收到的数据（响应标头和正文）.

在此页面上，您可以通过单击" `Resend Request`按钮以相同的数据重复`Resend Request` .

> **注意：**如果已更新 Webhook 的 URL 或秘密令牌，则数据将被传递到新地址.

### Receiving duplicate or multiple webhook requests triggered by one event[](#receiving-duplicate-or-multiple-webhook-requests-triggered-by-one-event "Permalink")

当 GitLab 发送一个 Webhook 时，它期望在 10 秒内响应（设置默认值）. 如果没有收到，它将重试网络挂钩. 如果端点在这 10 秒钟内未发送 HTTP 响应，则 GitLab 可能会确定挂钩失败并重试.

如果接收到多个请求，可以通过取消注释或将以下设置添加到`/etc/gitlab/gitlab.rb`来尝试增加发送`/etc/gitlab/gitlab.rb`之后的默认值，以等待 HTTP 响应：

```
gitlab_rails['webhook_timeout'] = 10 
```

### Troubleshooting: “Unable to get local issuer certificate”[](#troubleshooting-unable-to-get-local-issuer-certificate "Permalink")

启用 S​​SL 验证后，此错误表明 GitLab 无法验证 Webhook 端点的 SSL 证书. 通常，这是因为根证书不是由[CAcert.org](http://www.cacert.org/)确定的受信任的证书颁发机构[颁发的](http://www.cacert.org/) .

如果不是这种情况，请考虑使用[SSL Checker](https://www.sslshopper.com/ssl-checker.html)来识别故障. 缺少中间证书是验证失败的常见原因.

## Example webhook receiver[](#example-webhook-receiver "Permalink")

如果您希望通过测试了解 GitLab 的 webhooks，可以使用在控制台会话中运行的简单回显脚本. 为了使以下脚本正常工作，您需要安装 Ruby.

将以下文件另存为`print_http_body.rb` ：

```
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 
```

选择一个未使用的端口（例如 8000）并启动脚本： `ruby print_http_body.rb 8000` . 然后，将您的服务器作为 Webhook 接收器添加到 GitLab 中，作为`http://my.host:8000/` .

在 GitLab 中按"测试"时，您应该在控制台中看到以下内容：

```
{"before":"077a85dd266e6f3573ef7e9ef8ce3343ad659c4e","after":"95cd4a99e93bc4bbabacfa2cd10e6725b1403c60",<SNIP>}
example.com - - [14/May/2014:07:45:26 EDT] "POST / HTTP/1.1" 200 0
- -> / 
```

**注意：**您可能需要[允许向本地网络](../../../security/webhooks.html)发送[请求，](../../../security/webhooks.html)以便添加此接收器.