CI是敏捷和DevOps關(guān)鍵性的一步屯阀,數(shù)人云最近給大家分享了《致:正在選擇CI平臺的你(10大要素需把控)》今天的文章將討論如何使用CI服務(wù)器創(chuàng)建高質(zhì)量產(chǎn)品以及相關(guān)擴展插件和指標度量娃殖。最后針對業(yè)內(nèi)標準規(guī)則進行了自我思考衰粹。
CI服務(wù)器
擁有自動化的構(gòu)建系統(tǒng),是實現(xiàn)CI唯一強制性要求踪危。但在實踐中蔬浙,除了自動化構(gòu)建系統(tǒng)外,還可以安裝和配置“CI服務(wù)器”贞远。
概述
CI服務(wù)器是大腦畴博,在幕后工作,無縫地將各種行業(yè)標準實踐整合到CI實現(xiàn)過程中蓝仲。
下圖是個典型的CI工作流俱病,包含6個階段,從代碼檢入開始袱结,直到向企業(yè)內(nèi)不同的人員提供反饋信息庶艾。
啟動過程
通常,開發(fā)人員將代碼簽入源存儲庫時擎勘,CI流程就會啟動咱揍。
CI工作流也可以通過其他方式觸發(fā),下面列舉幾個方法——
- 手動:用戶通過CI服務(wù)器管理控制臺或腳本手動執(zhí)行時棚饵。
- 計劃:預(yù)先配置的時間表煤裙,如某個夜間構(gòu)建。
- 觸發(fā):每次提交到源代碼版本控制系統(tǒng)噪漾。
夜間構(gòu)建通常會對代碼執(zhí)行更大檢查和更久時間硼砰。
獲取最新代碼
流程的第二步,CI服務(wù)器從源控件獲取最新代碼欣硼,可以通過輪詢或推送機制實現(xiàn)题翰。
在輪詢機制中,CI服務(wù)器配置為源控制服務(wù)器,不斷地在固定時間間隔內(nèi)對給定的位置進行輪詢豹障,檢測任何新的代碼更改冯事,一旦檢測到,會從源控制服務(wù)器下載最新的代碼副本到磁盤上血公。
推送機制中昵仅,源控制系統(tǒng)由一個:“鉤子”提供給CI服務(wù)器,當(dāng)開發(fā)者向提交更改時累魔,調(diào)用“鉤子”摔笤,并讓CI服務(wù)器了解更改是可用的。
構(gòu)建
源代碼一般獨立于構(gòu)建垦写,即必要的構(gòu)建腳本與源代碼共存吕世,最新的代碼在前面步驟中被詳細地獲取,綁定的腳本會觸發(fā)構(gòu)建梯投。
對于Java項目命辖,通常構(gòu)建自動化腳本使用Maven或分級。使用不支持內(nèi)置依賴管理的構(gòu)建系統(tǒng)并不常見晚伙,在不需要依賴管理的情況下,Make 使用了在Unix系統(tǒng)中廣泛使用的構(gòu)建機制俭茧。
有很多構(gòu)建工具可以使用咆疗,Wiki列出了一些:(https://en.wikipedia.org/wiki/List_of_build_automation_software)
執(zhí)行測試
在此過程中執(zhí)行單元測試和集成測試,這些測試和代碼一般捆綁在一起母债。
基于Java的系統(tǒng)午磁,測試使用類似于Junit的測試框架執(zhí)行,允許對測試依賴項進行簡單的模擬毡们。
某些編程技術(shù)自帶測試運行器框架迅皇,如Spring的Spring Junit運行器、Java EE中的Arquillian等衙熔。
在CI服務(wù)器上運行測試有以下幾點:
曾經(jīng)遇到過測試在一臺機器上傳遞登颓,但在另一臺上失效的情況嗎?通過在集中的服務(wù)器上運行測試红氯,消除了測試環(huán)境的問題框咙。
測試會立即執(zhí)行每個更改,若有代碼破壞預(yù)期行為能被快速發(fā)現(xiàn)痢甘。
很多團隊并行處理特性喇嘱,甚至團隊成員在全球范圍內(nèi)分布,每次開發(fā)者向存儲庫提交代碼塞栅,任何故障都能即刻識別和修復(fù)者铜。
結(jié)果
CI過程的最后有兩種結(jié)果:構(gòu)建和測試失敗或通過。
每個嵌入都是經(jīng)過驗證的,并且確保不會破壞現(xiàn)有的代碼作烟,代碼被合并到主干中愉粤,會被構(gòu)建和測試,允許減少主線代碼被破壞的時間俗壹。
一般情況下科汗,CI服務(wù)器失敗會發(fā)送電子郵件(給整體團隊或只負責(zé)以前簽入的人),可以快速看到失敗的狀況绷雏,并且盡快采取糾正措施头滔。
CI服務(wù)器還凸顯了最近構(gòu)建的狀態(tài),以及最近幾個構(gòu)建在紅-綠-琥珀光指示器上的狀態(tài)涎显,例如坤检,Jenkins使用了下面的構(gòu)建指示器:
CI服務(wù)器插件
上一節(jié)介紹了CI的基本工作流程,但大多數(shù)企業(yè)會使用它完成更多任務(wù)期吓,通過安裝各種插件擴展CI服務(wù)器早歇,開拓行為,下面介紹一些常用的擴展:
技術(shù)債務(wù)與代碼質(zhì)量
在應(yīng)用中引入的任何變化都會增加系統(tǒng)復(fù)雜和無序性被稱之為“技術(shù)債務(wù)”讨勤,當(dāng)新代碼引入系統(tǒng)時會增加技術(shù)債務(wù)箭跳,如果被忽視太久,越來越多的新功能被緊湊的最后期限所填滿潭千,此時想要在可控范圍內(nèi)幾乎不可能谱姓,這將對應(yīng)用的生產(chǎn)效率和可維護性造成負面影響。
迭代開發(fā)刨晴、自動化檢測屉来、和CI的使用來監(jiān)控每個簽入技術(shù)債務(wù)是控制技術(shù)債務(wù)的唯一方法。
如SonarQube工具狈癞,采用識別代碼質(zhì)量和跟蹤技術(shù)債務(wù)的開源平臺茄靠,可以輕松地集成到任何CI服務(wù)器中,為技術(shù)債務(wù)提供實時數(shù)據(jù)蝶桶。
其不僅僅衡量技術(shù)債務(wù)慨绳,也度量并涵蓋了代碼質(zhì)量的7個核心:
SonarQube在簡單的WEB中展現(xiàn)分析結(jié)果,是非常有用的工具真竖,不僅是開發(fā)者儡蔓,對于管理其他非技術(shù)的人也是如此。
了解更多請參考:
語義
對于開發(fā)者來說疼邀,引入CI在另一個重要的方面非常具有價值——可以衡量代碼質(zhì)量——語義及常見的反模式喂江。
靜態(tài)代碼工具可以作為CI過程的一部分,以深入了解代碼的健康度旁振,歷史數(shù)據(jù)也可以存儲获询,從而在一段時間內(nèi)提供質(zhì)量度量涨岁。可以為兩個提交作比較吉嚣,確定每個提交的債務(wù)度量標準梢薪。
很多工具可以靜態(tài)地分析代碼并計算質(zhì)量度量的多樣性,同時可以被集成到CI服務(wù)器中自動運行尝哆,例如:
- Checkstyle
- Findbugs
- Sonar
代碼評審
開發(fā)者在特性分支上工作秉撇,并盡可能頻繁地提交代碼。
代碼分析工具(如:Sonar)可以在CI服務(wù)器中執(zhí)行自動代碼檢測秋泄,然后每個開發(fā)者負責(zé)處理提交時生成的評論注釋琐馆。
自動代碼審查基于一組預(yù)定義的規(guī)則,是發(fā)現(xiàn)潛在技術(shù)問題很好的方法恒序,這些規(guī)則可以從主流的開發(fā)語言中下載瘦麸。
解決了自動化評審意見,會進行同行代碼評審歧胁,捕捉那些不能用自動化審查的問題滋饲,如驗證業(yè)務(wù)需求、體系結(jié)構(gòu)問題喊巍、代碼易讀性屠缭、擴展性等。
如果有一定數(shù)量的人沒對代碼進行審查崭参,CI服務(wù)器可以配置成阻止對主線分支任何的提交呵曹,常見辦法是在主線分支中強制要求每個提交至少2個審核員,Java的項目中阵翎,常見工具是Gerrit逢并。
Headless Testing
若想在CI服務(wù)器上運行UI測試之剧,必須依賴于Headless(Headless:在缺少顯示屏郭卫、鍵盤或者鼠標時的系統(tǒng)配置)測試,因為瀏覽器沒有顯示背稼,這意味著要在沒有圖形用戶界面的情況下運行UI測試贰军,需要類似于流行WEB瀏覽器的Headless瀏覽器,通過命令行界面執(zhí)行蟹肘,并具有UI元素的內(nèi)存模式词疼。內(nèi)存中的模型用于模擬UI交互,如帘腹,在UI中單擊一個按鈕即可模擬內(nèi)存中的模型對象贰盗。
Selenium測試工具可以用于無頭測試,如Phantom JS的Headless瀏覽器也被廣泛應(yīng)用阳欲,在構(gòu)建中引入這些測試舵盈,CI服務(wù)器能夠驗證失敗的UI陋率。
安裝CI服務(wù)器
CI服務(wù)器主要有三種:
- 獨立
- 托管
- 私有云
獨立的CI服務(wù)器安裝在一臺機器上進行,通常用于小型項目或少于10人的開發(fā)團隊秽晚。
托管的CI服務(wù)器可以在公有云上使用瓦糟,大多數(shù)情況下,都與CI服務(wù)器可以訪問的基于云的源控制系統(tǒng)相連接赴蝇。這些公司都不希望維護CI或無法維護的公司使用菩浙,對于中等規(guī)模的團隊,是非尘淞妫可行的選擇劲蜻。
私有云是想要完全控制和基于安全考慮的大公司使用的,多個CI服務(wù)器代理配置在高性能服務(wù)器的集合中熄阻,以支持數(shù)百個開發(fā)者繁重工作負載斋竞。
一些被廣泛使用的CI服務(wù)器:
- Jenkins
- Travis CI
- TeamCity
- CruiseControl
CI最佳實踐
Martin Fowler(國際著名面向?qū)ο蠓治鲈O(shè)計、UML秃殉、模式等方面的專家坝初,敏捷開發(fā)方法的創(chuàng)始人之一)在他關(guān)于CI的白皮書中提到了為任何CI設(shè)置的一些關(guān)鍵實踐。這些建議已經(jīng)成為多年來CI的最佳實踐钾军。
這里將根據(jù)文章作者的見解來審視每一種最佳實踐鳄袍。
維護單個源存儲庫
“提倡使用版本控制系統(tǒng)實現(xiàn)項目的源代碼,所有與構(gòu)建項目相關(guān)的都應(yīng)存放在存儲庫中吏恭,在此實踐中拗小,約定系統(tǒng)應(yīng)該從一個新的簽出中構(gòu)建,不需要額外依賴項樱哼,極限開發(fā)倡導(dǎo)者Martin Fowler提到哀九,在使用工具支持分支的情況下,應(yīng)盡量減少分支的使用搅幅,更傾向于進行集成而不是同時維護多個版本的應(yīng)用阅束,主線(或主干),應(yīng)該是應(yīng)用的工作版本茄唐∠⒙悖”
提示
原則并非一定按照字面上只需一個單一的存儲庫,關(guān)鍵是擁有在存儲庫中構(gòu)建項目所需的所有相關(guān)工件沪编,該項目應(yīng)該從一個新的簽出中進行構(gòu)建呼盆,而不需要額外的依賴項或手動步驟。
“項目”的定義取決于自身蚁廓,如果代碼庫很小访圃,或者代碼所構(gòu)建的邏輯模塊組件,那么就意味著是完整可交付的產(chǎn)品相嵌。
觀點
實踐中建議不要在版本控制系統(tǒng)中使用分支腿时,相反克胳,建議只開發(fā)項目的某個分支,且讓其一直處于開發(fā)階段圈匆。
本文作者不同意這種說法漠另,在多數(shù)企業(yè)中,有許多分支需要同時并行開發(fā)跃赚,企業(yè)需要支持產(chǎn)品的前一個版本笆搓,修復(fù)BUG,而其他團隊成員則開始著手下一個版本的工作纬傲,所以需要在代碼庫中使用多個分支满败。
自動化構(gòu)建
“單個命令應(yīng)該具備構(gòu)建系統(tǒng)的能力,許多構(gòu)建工具如Make叹括,已經(jīng)存在多年算墨,其他近期的工具經(jīng)常用于CI環(huán)境中,構(gòu)建的自動化應(yīng)該包括自動化集成汁雷,包括部署到類似產(chǎn)品的環(huán)境中净嘀,在許多情況下構(gòu)建本本不僅編譯二進制文件,還生成文檔侠讯、網(wǎng)站頁面挖藏、統(tǒng)計信息和分發(fā)介質(zhì)(如Debian DEB、Red Hat RPM或Windows MSI文件)”
提示
構(gòu)建的自動化應(yīng)該包括:編譯代碼厢漩、執(zhí)行單元測試和集成測試膜眠,以及許多工具——代碼質(zhì)量檢測、語義檢測溜嗜、測量技術(shù)債務(wù)等宵膨,多數(shù)現(xiàn)代構(gòu)建工具都支持這些額外集成,并且用于開發(fā)CI環(huán)境炸宵。
在實際項目中辟躏,不同的團隊負責(zé)開發(fā)系統(tǒng)不同部分,都有自己的存儲庫焙压,因此這種情況幾乎不可能發(fā)生鸿脓,將整個產(chǎn)品進行自動化構(gòu)建沒有必要抑钟,為系統(tǒng)單獨部分開發(fā)構(gòu)建自動化就足夠涯曲。
觀點
定義CI的目的除了自動化構(gòu)建過程外,是否還有投資CI的意思在塔?作為CI的一部分幻件,打算度量哪些標準?很多人將CI設(shè)置看做開發(fā)者的工具蛔溃。
CI不是敏捷或DevOps绰沥,只是整體過程的工具之一篱蝇,敏捷或DevOps已經(jīng)超越了開發(fā)技術(shù)層面,升華成一種文化徽曲。
構(gòu)建自測
“構(gòu)建代碼后零截,所有測試都應(yīng)運行以確認它如開發(fā)者的預(yù)期一樣⊥撼迹”
提示
代碼至少要包含單元測試涧衙,如Junit框架可以模擬依賴關(guān)系。
特定組件與其他模塊是不應(yīng)該交互的奥此,要確保獨立運行弧哎。
觀點
單元測試應(yīng)該測試行為,而不是實現(xiàn)細節(jié)稚虎,例如撤嫩,不要去在乎如何計算汽車的速度,只要使用的方法和工具是正確的即可蠢终。
許多測試框架允許斷言模擬對象序攘,如測試模擬對象是否被調(diào)用,是否在特定的參數(shù)中傳遞等寻拂,除非測試實現(xiàn)本身是主要關(guān)注點两踏,否則應(yīng)將其弱化。
保持快速構(gòu)建
“構(gòu)建需要快速完成兜喻,因此如果集成有問題梦染,會很快被識別∑咏裕”
提示
- 應(yīng)該以更快地執(zhí)行測試為目標帕识,所以需要做比其他類型更多的單元測試。
- 避免在單元測試中使用數(shù)據(jù)庫遂铡,如果可以肮疗,也要必滿在集成測試中使用醋旦。通常需要集成測試使用另一種數(shù)據(jù)源馏谨,指向內(nèi)存中的數(shù)據(jù)庫。如果不可避免踩官,每次測試前都需刷新數(shù)據(jù)庫钾怔,確保數(shù)據(jù)處于已知狀態(tài)碱呼,并且測試會以一致的數(shù)據(jù)開始。
注意
不要依賴大量的UI測試宗侦,其非常脆弱愚臀,需要大量維護,建議使用如Selenium類似的UI測試框架來緩解UI測試的一些問題矾利,如屏幕上更改UI元素的位置姑裂、處理UI事件等馋袜。
自動化部署
“很多CI系統(tǒng)允許在構(gòu)建完成后運行腳本,可以編寫一個腳本將應(yīng)用部署到每個人都可以查看的實時測試服務(wù)器上舶斧,此種思維方式進一步發(fā)展是CD(持續(xù)部署)欣鳖,要求將應(yīng)用直接部署到生產(chǎn)中,需要額外的自動化防止BUG和回滾茴厉」厶茫”
觀點
不是所有的項目都需要自動化部署,如果生產(chǎn)站點是由同一家公司托管呀忧,那么在CD中投資更加有利师痕,CD是CI的下一個邏輯步驟。
不是所有提交的結(jié)果都是可交付的產(chǎn)品而账,在敏捷社區(qū)中每個構(gòu)建都是可交付的產(chǎn)品是常見的誤解胰坟,可交付的產(chǎn)品與工作應(yīng)用是不同的概念。
原文作者:Deepak Karanth
原文鏈接:https://dzone.com/articles/continuous-integration-part-3-best-practices