點擊上方“中興開發人員社區”,關注我們
每天讀一篇一線開發人員原創好文
問題描述
Jenkins2.0 Pipeline架構iPipeline(即plll庫)對MergeCI的觸發條件的設定為Change merged模式且固定不變,即需要由代碼走查者+2分後,再由Core成員點擊Submit按鈕來將代碼推入庫,然後才來觸發MergeCI流程,該過程的VerifyCI和MergeCI流程如下圖所示:
結合上圖我們可以發現,這裡有個問題是 一旦代碼走查通過(+2分),然後Core成員通過(Submit)後,代碼立即入庫,然後觸發MergeCI流程,此時若MergeCI運行出錯,那錯誤此時已經入庫並且影響後續開發人員合入代碼。
再結合本項目協議開發自身的實際特點,很有可能VerifyCI通過後的MergeCI會和他人產生互相影響,這樣便可能導致主幹分支代碼有錯,開發人員之間互相影響,最終影響代碼提交合入的效率。
基於此種情況,我們提出的一種模式是,MergeCI由代碼審查人員在Gerrit上打出+2分來觸發,只有到MergeCI運行通過,代碼才會被推入庫中,此種方式帶來的一個最直接的好處就是主幹分支上的代碼永遠正確的,而且不會因為MergeCI報錯而影響他人合代碼,而且該方法帶來的另外一個好處便是無需設定關鍵角色來負責Submit代碼入庫,僅僅需要的是代碼走查人員即可,這樣也提高了自動化程度,節省人力。將該流程可以示意如下圖:
因此plll庫的這種MergeCI的設定方式並不滿足本項目,因此我們決定擴充plll庫對於MergeCI運行模式的支援。 最佳化實踐
通過重載了plll庫的屬性設定函數,加入了根據CI類型來完成MergeCI不同觸發條件的設定:
/**
* 工具名稱:set_default_properties
* 工具描述:設定預設的參數
* 參數說明:
* - citype : CI類型
* - args : 參數列表
**/
def set_default_properties(citype, args) {
def buildParameters = []
def buildTriggers = []
set_parameters_properties(buildParameters, args)
set_cron_properties(buildTriggers, args)
set_gerrit_properties(citype, buildParameters, buildTriggers, args)
/* --------參數------- */
properties([
[$class: 'GitLabConnectionProperty', gitLabConnection: ''],
[$class: 'RebuildSettings', autoRebuild: false, rebuildDisabled: false],
buildDiscarder(logRotator(artifactDaysToKeepStr: '', artifactNumToKeepStr: '', daysToKeepStr: '14', numToKeepStr: '100')),
parameters(buildParameters),
pipelineTriggers(buildTriggers)
])
/* 清空臨時變數 */
buildParameters=null
buildTriggers=null
return
}
/**
* 函數名稱:設定gerrit屬性
**/
def set_gerrit_properties(citype, buildParameters, buildTriggers, args)
{
// ...此處代碼省略...
if( "verifyci" == "${citype}" ){
gerritEvents = [
patchsetCreated(
excludeDrafts: false,
excludeNoCodeChange: true,
excludeTrivialRebase: false
),
draftPublished()
]
// 如果CI類型是MergeCI,則設定器觸發條件為Code-Review +2方式來觸發
}else if( "mergeci" == "${citype}" ){
gerritEvents = [
commentAdded(commentAddedTriggerApprovalValue: '+2', verdictCategory: 'Code-Review')
]
}
// ...此處代碼省略...
}
由代碼可知,在set_gerrit_properties函數中,做了特殊判斷,若是MergeCI,則單獨將其觸發條件設定為Code-Review +2,這樣便可以滿足需求
使用舉例:
在MergeCI的Jenkinsfile中調用plll.set_default_properties設定項目屬性時明確指定mergeci類型即可,以本項目的Jenkinsfile代碼中設定預設屬性參數為例:
def set_default_properties() {
plll.set_default_properties("mergeci", [
/* 關聯gerrit */
gerrit:[
server:"${env.GERRIT_SERVER_NAME}",
projects:[[project:"${env.GERRIT_PROJECT}", branch:"${plll.getJobBaseName()}"]]
],
/* 自訂參數 */
parameters:[
choice(choices: 'yes\nno', description: '清空編譯環境', name: 'CLEAN_ALL'),
string(defaultValue: "${plll.getJobBaseName()}", description: '觸發分支',name: 'BRANCH_TAG')
],
]);
}
除此之外,還需要在Jenkins系統管理中MergeCI的Gerrit Trigger設定中作如下圖所示的配置即可:
優缺點分析 1. 優點:
開發人員互相獨立,別人錯誤的代碼無法入庫,不影響他人
主幹分支代碼永遠正確,不影響別人拉代碼驗證和正常合入代碼
無需小組核心成員進行submit操作,MergeCI一旦運行正確,代碼則自動入庫
2. 缺點:
原理決定了其無法並行,所以需要根據不同的項目情況酌情考慮。但是從本項目實際實踐的整局來看,本項目VerifyCI支援數個任務同時並發執行,而MergeCI排隊執行,但由於MergeCI執行較快,而且衝突很少,因此MergeCI的代碼都能逐個順利地合入,幸福感較以前有很大提升 推廣建議
本文章相關最佳化改進點可推廣至MergeCI可能經常衝突出錯導致開發人員代碼無法合入的項目。
拓展閱讀
乾貨 | Jenkins2.0 Pipeline架構(iPipeline)最佳化實踐之路(一)乾貨 | Jenkins2.0 Pipeline架構(iPipeline)最佳化實踐之路(二)