天天看點

使用Generic Webhook Trigger插件實作Jenkins+WebHooks(碼雲)持續內建--指定具體項目和分支進行內建

上一篇:

使用Generic Webhook Trigger插件實作Jenkins+WebHooks(碼雲)持續內建

介紹了如何使用Jenkins通用插件Generic Webhook Trigger 來實作碼雲WebHooks持續內建,但是有一個問題就是,如果項目是多分支的情況下,每一個分支的送出都會觸發Jenkins運作,這一點肯定是我們不想看到的,下邊我們就解決一下這個問題。

知識背景

1、使用碼雲WebHooks進行持續內建的時候,我們首先應該明白,他的原理大緻是這樣的:當我們每一次送出代碼到碼雲的時候,碼雲會幫我們發送一個關于Push的Post請求到我們的Jenkins伺服器,然後Jenkins持續內建插件Generic Webhook Trigger會接收到請求的參數,對于碼雲平台,Push 的資料格式是這樣子的:

{
    "before": "fb32ef5812dc132ece716a05c50c7531c6dc1b4d", 
    "after": "ac63b9ba95191a1bf79d60bc262851a66c12cda1", 
    "ref": "refs/heads/master", 
    "user_name": "123", 
    "user": {
        "email": "[email protected]", 
        "name": "123", 
        "time": "2016-12-09T17:28:02 08:00"
    }, 
    "repository": {
        "name": "webhook", 
        "url": "http://git.oschina.net/oschina/webhook", 
        "description": "", 
        "homepage": "http://git.oschina.net/oschina/webhook"
    }, 
    "commits": [
        {
            "id": "ac63b9ba95191a1bf79d60bc262851a66c12cda1", 
            "message": "1234 bug fix", 
            "timestamp": "2016-12-09T17:28:02 08:00", 
            "url": "http://git.oschina.net/oschina/webhook/commit/ac63b9ba95191a1bf79d60bc262851a66c12cda1", 
            "author": {
                "name": "123", 
                "email": "[email protected]", 
                "time": "2016-12-09T17:28:02 08:00"
            }
        }
    ], 
    "total_commits_count": , 
    "commits_more_than_ten": false, 
    "project": {
        "name": "webhook", 
        "path": "webhook", 
        "url": "http://git.oschina.net/oschina/webhook", 
        "git_ssh_url": "[email protected]:oschina/webhook.git", 
        "git_http_url": "https://git.oschina.net/oschina/webhook.git", 
        "git_svn_url": "svn://git.oschina.net/oschina/webhook", 
        "namespace": "oschina", 
        "path_with_namespace": "oschina/webhook", 
        "default_branch": "master"
    }, 
    "hook_name": "push_hooks", 
    "password": "pwd"
}
           

這一點可以在碼雲WebHooks介紹文檔(http://git.mydoc.io/?t=154711)詳細的看到。

2、如果我們想自己根據不同的分支的送出情況來觸發Jenkins建構,那麼我們就應該知道,上述的Post資料哪一個屬性代表了不同的分支情況。

3、結果是,Post資料的第三行:

"ref": "refs/heads/master", 
           

代表了不同的分支,我是根據具體的實驗資料得到的,實驗過程如下:

判斷分支标志位的實驗過程

1、準備工作

在碼雲-項目管理-WebHooks下設定:

使用Generic Webhook Trigger插件實作Jenkins+WebHooks(碼雲)持續內建--指定具體項目和分支進行內建

這裡把Post的位址指定為: http://xuliugen.vicp.io:8030/api/jenkins

(這個位址,我是通過 花生殼和路由器 進行内網端口映射的位址,友善請求到達本地伺服器的時候友善Debug)

在8030端口啟動一個簡單的Web服務(SSM項目),代碼如下:

使用Generic Webhook Trigger插件實作Jenkins+WebHooks(碼雲)持續內建--指定具體項目和分支進行內建

這裡的GitOSPostBean 是根據上述碼雲Push 的JSON資料格式生成的Bean,(插件是IDEA的GsonFormat 這裡不再介紹)

2、在1準備工作中,可以看出我實驗操作的項目是 jenkins-test , Git分支如下:

使用Generic Webhook Trigger插件實作Jenkins+WebHooks(碼雲)持續內建--指定具體項目和分支進行內建

3、首先,修改分支develop(全稱為:refs/remotes/origin/develop)代碼,然後送出代碼,檢視結果:

使用Generic Webhook Trigger插件實作Jenkins+WebHooks(碼雲)持續內建--指定具體項目和分支進行內建

可以看到ref的值為:refs/heads/develop

4、然後,修改分支20170727-webhooks(全稱為:refs/heads/feature/liugen.xu/20170727-webhooks)代碼,然後送出代碼,檢視結果:

使用Generic Webhook Trigger插件實作Jenkins+WebHooks(碼雲)持續內建--指定具體項目和分支進行內建

5、可以檢視其他資料,最後得出,ref 可以很好的區分不同的分支。

配置Jenkins

配置結果如下:

使用Generic Webhook Trigger插件實作Jenkins+WebHooks(碼雲)持續內建--指定具體項目和分支進行內建

1、配置就是如此簡單,上一篇: http://blog.csdn.net/xlgen157387/article/details/72852428隻是勾選了Generic Webhook Trigger,什麼都沒有配置,是以造成任何分支的每一次送出都會觸發Jenkins的建構。

Generic Webhook Trigger主要有: Post content parameters、 Header parameters、Request parameters和Optional filter這幾個組成。

其中,Post content parameters是對POST請求資料的處理,其他 Header parameters、Request parameters類似,這些都是比對請求資料中的param,他會判斷是否具有指定的這個參數,具體介紹如下:

If you want "param1" in post content { "param1": "value1" } posted to http://JENKINS_URL/generic-webhook-trigger/invoke to be contributed, you need to add "$.param1" here.
           

雖然如此,但是真正能夠按照指定分支或參數進行觸發的是Optional filter。

Optional filter的介紹是:This is an optional feature. If specified, this job will only trigger when given expression matches given text.

2、對于,上圖中(1)(2)(3)(4)解釋如下:

(1)篩選參數的變量名,這裡是ref;

(2)表達式

Expression

,使用‘$.ref’表示請求資料中的ref屬性,注意這裡有一個點;

(3)

Optional filter

Expression

表示,在

Post content parameters

Expression

中比對到的資料的格式是否比對,既是與‘$.ref’比對的資料。這裡應該是先确定觸發器的名稱,就是(4)中指定的變量;

(4)指定觸發器的名字;

總的來說,通過(1)(2)(3)(4)的設定,将請求中的‘ref’屬性的值和Optional filter的表達式Expression進行比較,如果比對則觸發Jenkins建構,如果不比對則不觸發。如果隻指定(1)(2)而沒有(3)(4)的話,他隻會在Jenkins建構界面顯示比對到的值和屬性,不會按照指定分支進行觸發的,如下:

使用Generic Webhook Trigger插件實作Jenkins+WebHooks(碼雲)持續內建--指定具體項目和分支進行內建

還有一點需要注意的是,(3)中的值是一個正規表達式,我這裡配置的是:

^(refs/heads/develop)$

意思就是去比對字元串:refs/heads/develop,測試結果如下:

使用Generic Webhook Trigger插件實作Jenkins+WebHooks(碼雲)持續內建--指定具體項目和分支進行內建

是以,如果比對其它分支,替換内容即可,例如:

、比對分支refs/heads/master,正則為:^(refs/heads/master)$ ;
、比對分支refs/heads/feature/liugen.xu/-webhooks,正則為:^(refs/heads/feature/liugen\.xu/-webhooks)$,這裡注意下,我這裡liugen\.xu因為有一個點,是以進行了轉義;
           

3、測試結果

結果我這裡測試的是正确的,可以檢視Jenkins日志:

使用Generic Webhook Trigger插件實作Jenkins+WebHooks(碼雲)持續內建--指定具體項目和分支進行內建

第一行是指定分支的送出,可以看出是SUCCESS:

[Handling POST /generic-webhook-trigger/invoke from  : http-apr--exec-] org.jenkinsci.plugins.gwt.GenericWebHookRequestReceiver.doInvoke Triggering jenkins-test
[Executor #1 for master : executing jenkins-test #23] hudson.model.Run.execute jenkins-test #23 main build action completed: SUCCESS
           

第一行不是指定分支的送出,可以看出未正确比對,是以不會觸發建構:

[Handling POST /generic-webhook-trigger/invoke from  : http-apr--exec-] org.jenkinsci.plugins.gwt.GenericWebHookRequestReceiver.doInvoke Triggering jenkins-test

[Handling POST /generic-webhook-trigger/invoke from  : http-apr--exec-] org.jenkinsci.plugins.gwt.GenericTrigger.isMatching Not triggering "^(refs/heads/develop)$" not matching "refs/heads/feature/liugen.xu/20170727-webhooks".
           

多個項目同時存在的問題

如果你的Jenkins配置了多個Job的話,例如下邊所示:

使用Generic Webhook Trigger插件實作Jenkins+WebHooks(碼雲)持續內建--指定具體項目和分支進行內建

你可能會發現,使用上邊的配置觸發指定分支進行自動建構的時候,如果這兩個項目都滿足了

ref

條件,也就是說都有這個分支的話,那麼這兩個項目都會進行觸發!這肯定是不正确的,是以要進行相應的修改,其實Generic Webhook Trigger插件的Post content parameters可以配置多個參數的,是以,我們需要從Git Post Data裡邊找出來一個可以辨別項目的參數名。

具體的Post資料關于project的部分如下:

使用Generic Webhook Trigger插件實作Jenkins+WebHooks(碼雲)持續內建--指定具體項目和分支進行內建

這裡的項目由于使用的是另一個測試的,是以顯示的是ufind-server而不是上述的jenkins-demo,可以去看出不同的項目确實是不同的,是以可以用來作為辨別。

檢視具體的project參數資料,可以看出一下有幾個參數可以作為辨別唯一項目的,這裡使用git_ssh_url(),是以我們需要把第一個參數指定為某一個分支,第二個參數指定為具體的某一個項目git位址,具體的設定需要改成如下所示:

使用Generic Webhook Trigger插件實作Jenkins+WebHooks(碼雲)持續內建--指定具體項目和分支進行內建
使用Generic Webhook Trigger插件實作Jenkins+WebHooks(碼雲)持續內建--指定具體項目和分支進行內建

可以看出中間的分隔符是“-”(橫線)!注意:這裡邊的sshUrl要換成你自己的url!

總結

到此,基本的實驗過程已經完成,從确定分支标志位到設定Generic Webhook Trigger,因為Generic Webhook Trigger相對小衆,更多是使用GitHub(GitHub的操作很簡單、很簡單)或者是自己寫腳本觸發,但是自己使用碼雲,一步步踩到這些坑,慢慢去解決,這應該是全網第一次關于此問題的讨論,當時遇到此類需求的時候特意抱着試試的态度去GitHub問了該插件的作者,很幸運的是作者及時回複,給了類似問題的位址(https://github.com/jenkinsci/generic-webhook-trigger-plugin/issues/14),但是看得雲裡霧裡,後邊慢慢研究了一下,最終實驗出結果,總的來說,是一個過程,希望對大家有所幫助。