Hudson擴充之插件開發
from:http://qa.taobao.com/?p=4925
上周寫了一篇關于Hudson擴充的文章,介紹的是使用API 的方式來對Hudson運作過程中産生的資料進行增删改查的操作,也可以對其運作情況進行控制,但是對Hudson進行擴充,目前最流行的還是進行插件開發,使用插件可以獲得更詳細的資料,也可以更緊密的與其運作過程結合起來。下面我通過開發旺旺插件的過程,簡單分享一下Hudson插件開發的過程和方法。
準備工作:
要開發Hudson插件,有以下幾個方面的準備工作需要首先做好:
1、 maven2
2、 JDK6.0或者更新的版本
如果現在我們已經安裝了合适版本的maven(2.0.9或者更新版本),下面需要做的就是修改setting.xml,如果你對maven不是很熟悉,你可以在你maven安裝目錄下的conf目錄下找到這個檔案,在找到setting.xml後,需要其中加入以下這些資訊:
<settings> … <pluginGroups> <pluginGroup>org.jvnet.hudson.tools</pluginGroup> </pluginGroups> </settings>
加入這一行資訊可以在我們使用Hudson的maven插件時使用縮略名(比如.使用hpi:create代替org.jvnet.hudson.tools:maven-hpi-plugin:1.23:create)
官網上說明如果使用2.0.9以前版本的maven時,可能需要一些 額外步驟.
建立Hudson的旺旺插件工程
建立Hudson插件的方法很簡單,就像我們平時使用maven建立一個工程一樣,我們需要運作下面的指令:
$ mvn -cpu hpi:create
運作這個指令後,控制台會讓你輸入一些資訊,比如groupId,artifactId。如果你對這兩個概念不是很熟悉,可以去先了解一下maven。在輸入這些資訊以後,maven就會幫我們生成Hudson插件的原型項目,接下來進入剛才生成的項目的目錄,首先保證可以對這個什麼都沒有的項目進行打包。比如:
$ cd newly-created-directory $ mvn package
這裡對剛才在指令行的幾個概念做一下解釋:
-cpu:會告訴maven去更新所有相關的maven插件
hpi: 這是Hudson自己開發的用來進行插件開發的maven插件,hpi是Hudson HPI插件名字的字首,就像大家經常用的mvn eclipse:eclipse中的前面一個eclipse
create:這是Hudson HPI插件用來生成Hudson插件原型項目的goal
最後将工程導入到eclipse中,就像我們平時導入maven工程一樣,官方建議使用3.3以後的版本,據說3.2會有bug (檢視官網的解釋.),下面簡單看一下目錄結構:
插件入口
一般來說每個插件都會有一個繼承自Plugin的 類PluginImpl,Hudson會通過Plugin類的繼承關系來擷取到你的插件類,進而建立插件執行個體,并調用相應的方法。PluginImpl相當與這個插件的入口,但如何嵌入到Hudson的各個活動中呢?比如我如何讓發送旺旺消息的功能在建構完了之後開始運作呢?這裡會提到一個概念,叫做extension points,我們可以稱作為“擴充點”,最近我也在看eclipse的插件開發,同樣也有這樣的概念。在這裡由于我們是需要在建構完成後開展某項工作,是以我們需要選用相應的擴充點,從extension points的官網上可以看到各個擴充點的功能,這裡我選用了Notifier,與Hudson自身的郵件插件所選用的擴充點一樣。于是,我們建立一個類WangWangMessenger繼承Notifier(實際上現在每個插件已經不需要擁有一個繼承Plugin的類了,隻需要在相應擴充點的實作類上打上@Extension标簽):
public class WangWangMessenger extends Notifier { @DataBoundConstructor public WangWangMessenger(String wangwang_recipients, boolean wangwang_failureOnly) { super(); this.recipients = wangwang_recipients; this.failureOnly = wangwang_failureOnly; } /** * recipients 存放旺旺通知需要發送的旺旺id */ private String recipients; * failureOnly 是否隻在建構失敗時發送通知 private boolean failureOnly; public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException { return new HudsonWangwangMessageBuilder(recipients, failureOnly) { }.execute(build, listener);
這裡recipients 表示旺旺接收者的Id,如果有多個人的話,可以按照一定的規則分隔,比如逗号分隔。failureOnly 表示是否隻在失敗的時候才發送消息,perform方法是覆寫Notifier中的方法,這個方法會在建構完成之後調用,就這樣我們就可以擷取本次建構相應的資訊,然後根據需要發送我們的旺旺消息。這裡我将這一職責交給自己定義的HudsonWangwangMessageBuilder執行個體去執行。下面來看看構造函數,可以看到在構造函數上,我加上了@DataBoundConstructor這樣一個标簽,當頁面請求産生後,會識别這樣的構造器來将頁面資料綁定到這個實體類。這樣當我們在頁面上填寫完旺旺接收者的ID和是否失敗時才發送消息的辨別,并且儲存頁面後,這些資料就可以綁定到這個實體類。下面我們先來看一下頁面上該如何處理。
頁面和資料存儲
想要讓Hudson插件在頁面上擷取一些資訊,我們需要定制化一些頁面。遺憾的是,Hudson并沒有使用我們常用的jsp或者html這些熟悉的元素來建構其頁面,而是使用了我們了解甚少的jelly腳本。
Hudson插件一般會使用兩個jelly腳本,就像剛才在生成的工程中看到的一樣:config.jelly和global.jelly,前者會自動嵌入到項目配置的頁面中,後者會嵌入到Hudson系統或者稱為全局配置的頁面中去,在頁面中具體的位置根據每個插件所實作的擴充點的不同而不同。這樣任意一個插件都不用關心其他部分是怎麼工作的,也不會對其他部分産生幹擾,進而真正達到插件的效果。在旺旺插件的應用中,我們需要知道接受消息的人的旺旺ID,是以我們需要對每個項目都進行不同的設定,是以我們可以修改config.jelly,将我們需要使用者填寫的資訊給出輸入框:
<j:jelly xmlns:j=”jelly:core” xmlns:st=”jelly:stapler” xmlns:d=”jelly:define” xmlns:l=”/lib/layout” xmlns:t=”/lib/hudson” xmlns:f=”/lib/form”> <f:entry title=”users” help=”/plugin/wangwang/help-recipients.html”> <f:textbox name=”wangwang_recipients” type=”text” value=”${instance.recipients}” /> </f:entry> <f:entry title=”failureOnly” help=”/plugin/wangwang/help-failonly.html”> <f:checkbox name=”wangwang_failureOnly” checked=”${instance.failureOnly}”/> </j:jelly>
我們先不去關心jelly腳本的文法,實際上也不需要了解的非常清楚,我們可以先了解為類似jstl和jsp的組合使用方式。每個jelly檔案這裡會對應一個實體類,根據它所在的包名而不同,在這裡會對應到我們的config.jelly會放在com.wangwang.hudson.
WangWangMessenger包下,是以這個jelly會對應到我們的WangWangMessenger類上,在jelly腳本中我們使用名字為“users”的一個entry包含一個文本輸入框f:textbox,這個輸入框的名字叫做“wangwang_recipients”用來填寫接收者的旺旺ID,另外還有一個checkbox用來勾選是否失敗時才發送。這部分在頁面上會展示成下面的樣子:
當我們最後點選“save”的時候,這些資訊會随着項目資訊一起被儲存到一個config.xml檔案中去,這個檔案會存放在你的“Hudson-home”所在位置job子目錄中的相應的項目檔案夾下。當然你也可以手動修改這個檔案以達到修改配置的目的,不過這通常需要在頁面上整個重新加載一遍。
消息發送
其實到這個時候,怎麼樣發送旺旺消息已經不是這個插件開發介紹所需要的核心内容了,當我們建構完成後,Hudson會自動調用目前項目中所有Notifier(實際上應該是Pulisher)子類的的perform方法,就像我們剛才看到的WangWangMessenger的perform方法一樣,我們隻需要将旺旺接收者Id和是否失敗才發送的标志發送過去即可,從pefrom的參數可以看到,我們可以擷取目前建構的示例對象:build,通過這個示例我們能夠擷取目前建構是否成功的标志,以及目前建構的URL,如果在配置時選擇了列印junit報告,也可以得到這個URL,那麼在我們最後調用HudsonWangwangMessageBuilder類的excute方法時就可以按照我們制定的方式拼裝相應的資訊,并且最終調用旺旺消息發送接口來将我們想要的資訊發送出來,達到存在測試失敗的情況下及時通知的效果
後記
到這裡為止,我其實已經簡單介紹了一下Hudson的插件開發的主要過程。當然,還有很多是我這裡沒有提到的,因為要講的東西實在是太多了,每個不同的擴充點最終所需要做的事情都不一樣,對于Hudson的jelly腳本也有很多可以需要去了解的,甚至對于其請求轉發的原理,對于插件測試,對于debug,也還有很多我都不了解的話題,都需要去讨論,這裡由于篇幅的限制,沒有辦法一篇文章面面俱到,僅希望以這篇文章來打開大家Hudson插件開發的大門,讓大家一起來共同學習研究,讓我們大家以後都可以按照自己的實際工作需要開發出自己想要的插件。
更多資訊,請關注:http://wiki.hudson-ci.org/display/HUDSON/Extend+Hudson