1. 授权认证
  2. 获取用户个人信息
  3. 项目协同
  4. 代码托管
  5. 持续集成
  6. 制品仓库
  7. 测试管理
  8. 文档管理
  1. 项目协同
  2. 代码仓库
  3. DevOps 实践之旅
  4. 一分钟开始持续集成之旅
  5. 持续部署
  6. 制品库

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
X-Coding-WebHook-Version: v2
X-Coding-Signature: sha1=561d0f6d8762ebddc09e10f83c7aaad18a622121

{
  "ref": "refs/heads/master",
  "before": "0000000000000000000000000000000000000000",
  "after": "9853d6bd3032c71413bd7914bb0696e186ea9d04",
  "created": true,
  "deleted": false,
  "compare": "https://my-team.coding.net/p/demo/git/compare/0000000000000...9853d6bd3032c",
  "head_commit": {
    "id": "9853d6bd3032c71413bd7914bb0696e186ea9d04",
    "distinct": false,
    "message": "Initial commit\n",
    "timestamp": 1587958379000,
    "url": "https://my-team.coding.net/api/team/my-team/project/demo/git/commit/9853d6bd3032c71413bd7914bb0696e186ea9d04",
    "author": {
      "name": "tom",
      "email": "tom@example.com",
      "username": "tom"
    },
    "committer": {
      "name": "tom",
      "email": "tom@example.com",
      "username": "tom"
    },
    "added": [
      ".gitignore",
      "README.md"
    ],
    "removed": [],
    "modified": []
  },
  "pusher": {
    "name": "tom",
    "email": "tom@example.com",
    "username": "KMRnIKgzbV"
  },
  "sender": {
    "id": 183478,
    "login": "KMRnIKgzbV",
    "avatar_url": "https://coding-net-production-static-ci.codehub.cn/2cb665a3-bebc-4b09-aa00-2b6df3e33edc.jpg?imageMogr2/auto-orient/format/jpeg/cut/400x400x0x0",
    "url": "https://my-team.coding.net/api/user/key/KMRnIKgzbV",
    "html_url": "https://my-team.coding.net/u/KMRnIKgzbV",
    "name": "tom",
    "name_pinyin": "tom"
  },
  "repository": {
    "id": 7510657,
    "name": "hello-world",
    "full_name": "my-team/demo/hello-world",
    "owner": {
      "id": 183478,
      "login": "KMRnIKgzbV",
      "avatar_url": "https://coding-net-production-static-ci.codehub.cn/2cb665a3-bebc-4b09-aa00-2b6df3e33edc.jpg?imageMogr2/auto-orient/format/jpeg/cut/400x400x0x0",
      "url": "https://my-team.coding.net/api/user/key/KMRnIKgzbV",
      "html_url": "https://my-team.coding.net/u/KMRnIKgzbV",
      "name": "tom",
      "name_pinyin": "tom"
    },
    "private": true,
    "html_url": "https://my-team.coding.net/p/demo",
    "description": "",
    "fork": false,
    "url": "https://my-team.coding.net/api/team/my-team/project/demo",
    "created_at": 1572178283000,
    "updated_at": 1572178283000,
    "clone_url": "https://e.coding.net/my-team/demo/hello-world.git",
    "ssh_url": "git@e.coding.net:my-team/demo/hello-world.git",
    "default_branch": "master"
  }
}

签名解析 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' + 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['token']
        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 示例代码

< ?php
$input = json_decode(file_get_contents("php://input"), true);

$message = '';
switch ($_SERVER['HTTP_X_CODING_EVENT']) {
    case 'ping':
        $message = 'pong';
        break;
    case 'push':
        $tmp = sys_get_temp_dir();
        $path = "$tmp/{$input['repository']['name']}";
        $cmd = "rm -rf $path; cd $tmp; git clone {$input['repository']['clone_url']}";

        $message = shell_exec($cmd);
        break;
}

header('Content-Type: application/json');
echo json_encode(compact('message'));

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

上一篇项目基本设置
最近更新
感谢反馈有用
感谢反馈没用