WebHook

Webhook 允许第三方应用监听 CODING 上的特定事件,在这些事件发生时通过 HTTP POST 方式通知(超时 5 秒)到第三方应用指定的 Web URL。 例如项目有新的内容 Push,或是 Merge Request 有更新等。基于 WebHook 可方便实现自动部署,自动测试,自动打包,监控项目变化等。

新建 WebHook

在【设置】->【开发者选项】->【 WebHook 】页面,点击右上角【新建 WebHook 】按钮。

目前支持的监听事件具体如下图所示,包括代码仓库的 Push 事件、 MR 事件、敏捷管理相关事件、持续集成任务相关、制品库变动等等。

填写 WebHook 配置相关信息:

  1. 填写 URL,WebHook 会将事件内容发送这个地址。
  2. 内容格式:默认为 coding,可选择钉钉。
  3. WebHook 发布的内容可以选择不同的类型:

    选择 application/json,发布时会直接装载 JSON 数据到 POST 的 body 中。

    选择 application/x-www-form-urlencoded,发布时会把 JSON 数据作为一个称为 “payload” 的表格参数。

    选择最适合您的那个类型,默认的 application/json 内容类型就很合适。

  4. 填写令牌,非必填项。
  5. 按需勾选您要监听的事件,默认勾选 Push 和 MR 事件。
  6. 默认勾选开启事件开关,事件触发时发送请求。

数据结构说明

每个事件类型都具有与该事件相关的数据结构。 不同事件的数据结构有所不同,但是都会包含事件的执行者(sender)以及事件发生所属的项目(repository)。

发送 Headers 说明

Header 说明
X-Coding-Event 事件名(例如: push, merge request)
X-Coding-Signature 通过 HMAC SHA1 加密算法、使用令牌作为 KEY 将发送内容加密后的值以十六进制显示(需要配置令牌),并包含前缀 sha1=
X-Coding-Delivery 标识此次发送的唯一 ID
User-Agent Coding.net Hook

发送的具体内容示例

POST /payload HTTP/1.1

Host: localhost:4567
Request method: POST
User-Agent: Coding.net Hook
X-Coding-Event: push
X-Coding-Delivery: bf3f043a-3883-433c-8e20-312b04c49b46

{
  "ref": "refs/heads/master",
  "before": "1b4d2b060ef9e9a32f86be8c416a84a24806b575",
  "after": "860385d69eda49a4af9379c844701163d19c8d6b",
  "compare": "https://test.coding.net//p/test-webhook/git/compare/1b4d2b060ef9e...860385d69eda4",
  ...
  "repository": {
    "id": 4021,
    "name": "test-webhook",
    "full_name": "test/test-webhook",
    "owner": {
      "id": 652,
      "login": "crystal",
      "url": "https://test.coding.net/user/key/crystal",
      "html_url": "https://test.coding.net//u/crystal"
    },
    ...
  },
  ...
  "sender": {
    "id": 613,
    "login": "jiong",
    ...
  }
}

签名解析 Demo

每个事件都包含的属性

Key Value
sender 事件触发者
repository 当前项目

Node.js 示例代码

var express = require('express');
var bodyParser = require('body-parser');
var multer = require('multer');
var process = require('child_process');
var bodyParser = require('body-parser');
var multer = require('multer');
var app = express();

app.use(bodyParser.json()); // for parsing application/json
app.use(bodyParser.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded
app.use(multer()); // for parsing multipart/form-data


app.post('/webhook', function(req,res){
    console.log('print', req.body);
    console.info(req.body["token"]);
    if('xxx' === req.body['token'] ){

    console.info(process);
    process.exec('git pull', {'cwd':'/home/coding/workspace'},
            function (error, stdout, stderr) {
                console.log('stdout========================\n' + stdout);
                console.log('stderr========================\n' + stderr);
                if (error !== null) {
                    res.send('
fail!!!\n' + stdout + error + '
'); } else { res.send('
done!!!\n' + stdout + '
'); } }); } else { console.log(' failed token ') res.send('
token不正确?
'); } }); app.set('port', 8080); var server = app.listen( 8080, function() { console.log('Listening on port %d', server.address().port); })

Ruby 示例代码

基于 sinatra 框架实现的 webhook 处理。

#!/usr/bin/env ruby

require "sinatra"
require "json/stream"

  get "/" do
    'Hello world!'
  end
  post "/hook" do
    @text = request.body.read
    @data = JSON::Stream::Parser.parse(@text)
    puts @data['token']
    puts @data['ref']
    puts @data['token']
    puts @data['zen']
    puts @data['commits']
    puts @data['repository']
    puts @data['url']

    if "123" == @data['tokne']
        puts `cd workspace`
        puts `git pull `
    end
  end
  get "/env" do
    content_type :text/plain
    html = ""
    html << "System Environment:\n\n"
    ENV.each do |key, value|
        html << "#{key}: #{value}\n"
    end
    html
  end

PHP 示例代码

Ping 事件接口说明

当您创建一个新的 WebHook 时,我们将向您发送一个简单的 ping 事件,让您知道 WebHook 是否能够成功发送。您可以在 WebHooks 列表中,通过点击 ping 按钮再次触发 ping。

事件名: ping

Key Value
zen Coding! 让开发更简单
hook_id 当前 WebHook 的 ID
hook 当前 WebHook 的配置数据

Push 事件接口说明

当您向您的仓库推送新的代码时,我们将向您发送一个的 Push 事件。

事件名: push

Key Value
hook_id 当前 WebHook 的 ID
hook 当前 WebHook 的配置数据
ref 推送的 commit sha
before 该分支之前的 commit sha
after 该分支新的 commit sha
compare compare 的 url 地址
commits 更新的 commits 内容
head_commit 最新的 commit 内容
pusher 推送者

MR 事件接口说明

当您进行一个代码合并相关操作时,我们将向您发送的 MR 事件。

事件名: merge request

Key Value
action (“synchronize”, “create”, “merge”)
number 项目内资源 id
mergeRequest 合并请求内容

Task 事件接口说明

当您进行任务相关操作时,我们将向您发送 Task 事件。

事件名: task

Key Value
action (“assigned”, “labeled”, “opened”, “edited”, “closed”, “reopened”, “deleted”)
task 任务内容

Document 事件接口说明

当您进行文件相关操作时,我们将向您发送 Document 事件。

事件名: document

Key Value
action (“create_file”, “create_dir”, “delete_file”, “delete_dir”, “update_file”, “update_dir”, “upload_file”, “move_file”, “delete_file_history”, “rename”, “move_folder”, “move_files_or_folders”, “share_file”, “stop_share_file”)
document 文件内容

Member 事件接口说明

当您新增或者删除项目成员时,我们将向您发送 Member 事件。

事件名: member

Key Value
action (“added”, “deleted”)
member member 内容

持续集成事件接口说明

持续集成提供持续集成任务创建、触发、停止、完成、删除等接口的 WebHook。

数据结构 - 钉钉&企业微信格式

Header

Request URL: [hook url]
Request method: POST
User-Agent: Coding.net Hook

Body

{
  "markdown": {
    "title": "alexli 触发了 job job11, 构建号:8",
    "text": "###### 项目 [ci-demo](https://alexli.coding.net/p/ci-demo)\n[alexli](https://alexli.coding.net/u/NeayPucMAz) 触发了 job \n> [job11](https://alexli.coding.net/p/ci-demo/ci/job/47379) 构建号:[8](https://alexli.coding.net/p/ci-demo/ci/job/47379/build/8/pipeline)"
  },
  "msgtype": "markdown"
}

数据结构 - coding 格式

Header

Header 说明
X-Coding-Event WebHook Event 的类型 ci
X-Coding-Delivery 唯一标识 GUID
X-Coding-WebHook-Version Coding WebHook : v2
Request URL: [hook url]
Request method: POST
User-Agent: Coding.net Hook

Body

Body 说明
action ci 动态描述:{trigger_build, update_job, delete_build, complete_build, delete_job}
ci ci 构建详情,详见示例
sender 发送者详情,详见示例
repository 仓库详情,详见示例

示例

{
  "action": "trigger_build",
  "ci": {
    "id": 47379,
    "name": "job1",
    "branch_regex": "",
    "cron_spec": "",
    "creator_id": 134556,
    "project_id": 185439,
    "depot_id": 181722,
    "execute_in": "CVM",
    "jenkins_file_path": "Jenkinsfile",
    "created_at": 1565143387000,
    "updated_at": 1570504872000,
    "trigger_method": "",
    "branch_selector": "",
    "hook_type": "DEFAULT",
    "trigger_remind": "ALWAYS",
    "build": {
      "id": 257665,
      "number": 7,
      "cci_id": "cci-264261-576675",
      "cause": "alexli 手动触发",
      "commit_id": "ec107f22a99a3a850c55702ad06175850f114cfa",
      "branch": "",
      "uuid": "dacd59f1-aaaa-4c3d-b387-74d06df55aed",
      "job_id": 47379,
      "trigger_user_id": 134556,
      "created_at": 1571377790000,
      "updated_at": 1571377790000,
      "pre_status": "NORMAL",
      "failed_message": "",
      "duration": 0,
      "status": "QUEUED"
    }
  },
  "sender": {
    "id": 134556,
    "login": "NeayPucMAz",
    "avatar_url": "https://coding-net-production-static-ci.codehub.cn/bceaa53a-6a01-436d-b470-c90dfc92e478.jpg?imageMogr2/auto-orient/format/jpeg/cut/200x200x0x0",
    "url": "https://alexli1.coding.net/api/user/key/NeayPucMAz",
    "html_url": "https://alexli1.coding.net/u/NeayPucMAz",
    "name": "alexli",
    "name_pinyin": "alexli"
  },
  "repository": {
    "id": 185439,
    "name": "ci-demo",
    "full_name": "alexli1/ci-demo",
    "owner": {
      "id": 134556,
      "login": "NeayPucMAz",
      "avatar_url": "https://coding-net-production-static-ci.codehub.cn/bceaa53a-6a01-436d-b470-c90dfc92e478.jpg?imageMogr2/auto-orient/format/jpeg/cut/200x200x0x0",
      "url": "https://alexli1.coding.net/api/user/key/NeayPucMAz",
      "html_url": "https://alexli1.coding.net/u/NeayPucMAz",
      "name": "alexli",
      "name_pinyin": "alexli"
    },
    "private": true,
    "html_url": "https://alexli1.coding.net/p/ci-demo",
    "description": "",
    "fork": false,
    "url": "https://alexli1.coding.net/api/team/alexli1/project/ci-demo",
    "created_at": 1565143382000,
    "updated_at": 1567398344000,
    "clone_url": "https://e.coding.net/alexli1/ci-demo.git",
    "ssh_url": "git@e.coding.net:alexli1/ci-demo.git",
    "default_branch": "master"
  }
}

制品库事件接口说明

制品库提供制品发布、更新版本的 WebHook。

数据结构 - 钉钉&企业微信格式

Header

Request URL: [hook url]
Request method: POST
User-Agent: Coding.net Hook

Body

{
  "markdown": {
    "title": "制品库动态",
    "text": "###### 项目 [Test](https://test.coding.net/p/test)\n[Test](https://test.coding.net/u/testproject)  在```Docker```类型制品库 ```test-repo``` 中发布了制品 ```test``` 的版本 ```1.0.0```",
    "content": "###### 项目 [Test](https://test.coding.net/p/test)\n[Test](https://test.coding.net/u/testproject)  在```Docker```类型制品库 ```test-repo``` 中发布了制品 ```test``` 的版本 ```1.0.0```"
  },
  "msgtype": "markdown"
}

数据结构 - coding 格式

Header

Header 说明
X-Coding-Event WebHook Event 的类型 artifact
X-Coding-Delivery 唯一标识 GUID
X-Coding-WebHook-Version Coding WebHook : v2
Request URL: [hook url]
Request method: POST
User-Agent: Coding.net Hook

Body

Body 说明
action 制品动态描述:create 或者 update
artifact 制品详情,详见示例
sender 发送者详情,详见示例
repository 仓库详情,详见示例

示例

{
  "action": "update",
  "artifact": {
    "projectId": 872359,
    "artifactRepoId": 21,
    "artifactPkgId": 148135,
    "artifactVersionId": 943729,
    "userId": 571222,
    "size": 7622367,
    "artifactRepoName": "testRepo",
    "artifactPkgName": "testPkg",
    "artifactVersionName": "1.0.0",
    "action": "update",
    "artifactType": "docker",
    "projectName": "xxx",
    "userName": "xxx"
  },
  "sender": {
    "id": 57122,
    "login": "User Global Key",
    "avatar_url": "https://coding-net-production-static-ci.codehub.cn/WM-TEXT-AVATAR-nYJfjngwaMZsAZXhgfcN.jpg",
    "url": "https://codingcorp.coding.net/api/user/key/xxx",
    "html_url": "https://codingcorp.coding.net/u/xxx",
    "name": "Test User",
    "name_pinyin": "Test User"
  },
  "repository": {
    "id": 87239,
    "name": "xxx",
    "full_name": "xxx",
    "owner": {
      "id": 57122,
      "login": "User Global Key",
      "avatar_url": "https://coding-net-production-static-ci.codehub.cn/WM-TEXT-AVATAR-nYJfjngwaMZsAZXhgfcN.jpg",
      "url": "https://codingcorp.coding.net/api/user/key/xxx",
      "html_url": "https://codingcorp.coding.net/u/xxx",
      "name": "xxx",
      "name_pinyin": "xxx"
    },
    "private": true,
    "html_url": "https://codingcorp.coding.net/p/xxx",
    "description": "项目描述",
    "fork": false,
    "url": "https://codingcorp.coding.net/api/team/mai/project/xxx",
    "created_at": 1554781241000,
    "updated_at": 1567397098000,
    "clone_url": "https://e.coding.net/xxx/xxx.git",
    "ssh_url": "git@e.coding.net:xxx/xxx.git",
    "default_branch": "master"
  }
}
上一篇Markdown 语法介绍
文档是否对您有用?
感谢反馈有用
感谢反馈没用