系列目錄 <https://www.cnblogs.com/tylerzhou/p/11204826.html>
WebHook近些年來變得越來越流行,github,gitlab等代碼托管平臺(tái)都提供webhook功能.關(guān)于webhook這里不做詳細(xì)介紹,大家可以參閱讀相關(guān)互聯(lián)網(wǎng)書籍或者材料來更深了解.可以把它簡單理解為某一事件完成以后的一個(gè)回調(diào).
在持續(xù)集成環(huán)境里,我們可以使用Sonarqube的webhook功能來實(shí)現(xiàn)持續(xù)發(fā)布和發(fā)布包歸檔功能.大致思路是當(dāng)項(xiàng)目構(gòu)建成功后我們可以通過webhook通知服務(wù)器構(gòu)建任務(wù)已完成,接下來web
服務(wù)器可以根據(jù)webhook傳遞的參數(shù)決定要處理的包是哪個(gè)項(xiàng)目的包(通過項(xiàng)目的key來判斷),如何對(duì)包進(jìn)行歸檔以及如何把包發(fā)布到遠(yuǎn)程服務(wù)器(通過http,ftp等方式).
Web服務(wù)器搭建
要想實(shí)現(xiàn)webhook,必須有一個(gè)預(yù)先設(shè)計(jì)好的web服務(wù)器供回調(diào).我們預(yù)先建好了一個(gè)web項(xiàng)目(新建一個(gè)mvc項(xiàng)目即可)
由于是測試,我們這里就用Visual的模板生成一個(gè)mvc項(xiàng)目,然后在Home控制器下新建一個(gè)Action,代碼如下:
public IActionResult HookTest([FromBody]SonarQubeVm sonar) { return new
EmptyResult(); }
由于Sonarqube webhook是通過post方式提交,因此action必須支持Post方式請(qǐng)求.
參數(shù)sonar是SonarQubeVm類型的參數(shù),是根據(jù)Sonarqube請(qǐng)求規(guī)格文檔構(gòu)建的,代碼如下:
public class SonarQubeVm { public DateTime? AnalysedAt { get; set; } public
SonarProjectInfo project { get; set; } public string ServerUrl { get; set; }
public string Status { get; set; } public string TaskId { get; set; } } public
class SonarProjectInfo { public string Key { get; set; } public string Name {
get; set; } }
注意以上參數(shù)并不完全包含Sonarqube返回的所有參數(shù),我們只取了部分.關(guān)于Sonarqube webhook完整請(qǐng)求參數(shù)請(qǐng)查看
http://localhost:9000/documentation/webhooks
,localhost:9000是默認(rèn)的服務(wù)器的端口號(hào),如果你更改了端口號(hào)或者從外網(wǎng)請(qǐng)求,則要更改為實(shí)際的ip地址(或者域名)加上指定的端口號(hào).
WebHook調(diào)用
在Sonarqube里可以通過兩種方式調(diào)用webhook,全局模式和項(xiàng)目模式.全局模式每當(dāng)一個(gè)構(gòu)建成功后就會(huì)觸發(fā).項(xiàng)目模式則只有指定的項(xiàng)目構(gòu)建以后才會(huì)觸發(fā).
全局模式
如上圖示,我們點(diǎn)擊全局Administration然后點(diǎn)擊configuration在出現(xiàn)的下拉列表里選擇WebHooks,此時(shí)右上角有一個(gè)create
按鈕,點(diǎn)擊后出現(xiàn)一個(gè)彈出框,要求輸入名稱和url,然后點(diǎn)擊確定.
我們以調(diào)試模式啟動(dòng)web項(xiàng)目,然后執(zhí)行一個(gè)Sonarqube項(xiàng)目構(gòu)建,執(zhí)行完成后看看是否有請(qǐng)求到達(dá)web服務(wù)器.
MSBuild.SonarQube.Runner.exe begin /k:"mytest" /n:"mytest" /v:"v3.0"
/d:sonar.cs.opencover.reportsPaths="%CD%\testcover.xml" msbuild.exe
"E:\personalproject\newTest2018\ConsoleApp1\packages\OpenCover.4.6.519\tools\OpenCover.Console.exe"
-output:"%CD%\testcover.xml" -register:user -target:"C:\Program Files
(x86)\Microsoft Visual
Studio\2017\Enterprise\Common7\IDE\CommonExtensions\Microsoft\TestWindow\vstest.console.exe"
-targetargs:"%CD%\bin\Debug\NunitTest.dll" MSBuild.SonarQube.Runner.exe end
以上是我們上一節(jié)講單元測試的時(shí)候執(zhí)行的代碼只修改了版本號(hào).我們執(zhí)行它.
等等以上代碼都執(zhí)行完成,稍等片刻我們就可以看到http請(qǐng)求擊中斷點(diǎn)
通過serverurl是來自localhost:9000,我們可以確定是Sonarqube發(fā)來的請(qǐng)求.項(xiàng)目的key和name都是我們?cè)O(shè)定的mytest
以上僅是個(gè)示例程序,沒有有用代碼,實(shí)際項(xiàng)目中我們可以根據(jù)webhook請(qǐng)求的key來獲取到構(gòu)建的是哪個(gè)項(xiàng)目,然后根據(jù)預(yù)先設(shè)定的邏輯決定把它歸檔到哪里,以及把它發(fā)布到哪些web服務(wù)器下的哪些目錄里(前面我們講過通過ftt方式發(fā)布web項(xiàng)目,可以在這里使用)
項(xiàng)目模式
項(xiàng)目模式與全局模式設(shè)置完全一樣,只是入口不同,項(xiàng)目模式需要進(jìn)入項(xiàng)目的Administration
標(biāo)簽里進(jìn)行設(shè)置.仍然以mytest項(xiàng)目為例子,我們打開mytest項(xiàng)目,進(jìn)入到Administration標(biāo)簽里選擇webhooks即可.
設(shè)置和全局設(shè)置一樣,這里不再贅述.
請(qǐng)求認(rèn)證
通過以上配置,我們成功搞好了webhook功能,然而以上代碼根本無法使用到生產(chǎn)環(huán)境中,因?yàn)闆]有對(duì)請(qǐng)求進(jìn)行認(rèn)證,如果任何人都可以調(diào)用構(gòu)建服務(wù)器地址則后果不堪設(shè)想.我們必須對(duì)請(qǐng)求進(jìn)行認(rèn)證,然后再?zèng)Q定是否執(zhí)行相應(yīng)邏輯.
由于sonaqube不支持設(shè)置header,因此我們無法使用復(fù)雜的請(qǐng)求認(rèn)證.只能使用基本的http認(rèn)證
我們?cè)诜?wù)端增加以下類
public class BasicAuthenticationAttribute: ActionFilterAttribute { protected
string Username { get; set; } = "sto"; protected string Password { get; set; }
= "sto"; public override void OnActionExecuting(ActionExecutingContext
filterContext) { var req = filterContext.HttpContext.Request; var auth =
req.Headers["Authorization"].ToString(); if (!String.IsNullOrEmpty(auth)) { var
cred =
System.Text.Encoding.ASCII.GetString(Convert.FromBase64String(auth.Substring(6))).Split(':');
var user = new { Name = cred[0], Pass = cred[1] }; if (user.Name == Username &&
user.Pass == Password) return; } filterContext.Result = new
UnauthorizedResult(); } }
以上代碼中,我們通過硬編碼方式指定了用戶名和密碼,實(shí)際生產(chǎn)環(huán)境中我們可以通過查詢數(shù)據(jù)庫來獲取用戶名和密碼. 在OnActionExecuting
重寫方法中我們通過頭信息Authorization獲取加密的Base64字符串,然后通過:分割獲取到用戶名和密碼.然后和真實(shí)用戶名密碼做對(duì)比然后決定下一步動(dòng)作.
我們把這個(gè)filter加到請(qǐng)求方法上.
改造后的代碼如下:
[BasicAuthentication] public IActionResult HookTest([FromBody]SonarQubeVm
sonar) { return new EmptyResult(); }
我們把webhook的url更新為如下:
http://sto:sto1@localhost:49442/home/HookTest
實(shí)際上服務(wù)端邏輯要求賬戶和密碼都必須是sto能請(qǐng)求,我們故意把密碼改為sto1看看請(qǐng)求是否能成功.
我們?nèi)匀粓?zhí)行前面的構(gòu)建代碼,只是把版本號(hào)增加一下.
我們?cè)龠M(jìn)入webhook管理界面,可以看到請(qǐng)求失敗了
我們點(diǎn)擊失日期后面的四框圖標(biāo),可以看到失敗的狀態(tài)是401
我們把請(qǐng)求地址更改為如下
http://sto:sto@localhost:49442/home/HookTest
這里sto1改為服務(wù)器期待的sto,請(qǐng)求就能成功了.
熱門工具 換一換