持續(xù)集成(CI)對于軟件工程來說非常重要,它的意義在于產(chǎn)品快速迭代的同時,還能夠讓代碼保持高質(zhì)量,所以編寫高質(zhì)量的單元測試代碼也顯得十分重要。Travis可以免費做開源軟件的持續(xù)集成,但是對于閉源軟件來說,它的費用非常高昂。另外一款持續(xù)集成軟件叫Jenkins,它是Java實現(xiàn)的一款開源持續(xù)集成工具,對于Java程序的持續(xù)集成支持特別好,網(wǎng)上也有很多這方面的文章。本文主要講述怎么運用它來做Python 項目的持續(xù)集成。
這里假設(shè)大家都比較熟悉Git開發(fā)流程了。這里所講的工作流是Git+Jenkins。首先,我們在持續(xù)集成服務(wù)器上安裝JDK1.8、Git和Python3(非Python項目無需安裝),并且把Python3設(shè)置為默認(rèn)Python解釋器。由于篇幅限制,這里就不展開講了。然后我們通過pip3 install virtualenv
安裝虛擬環(huán)境,安裝虛擬環(huán)境的目的是,在進行持續(xù)集成測試的時候,各個項目構(gòu)建使用不同的虛擬環(huán)境,因為項目不同可能相同依賴的版本會有沖突。
然后,在Jenkins官網(wǎng)上下載Jenkins并將其安裝到持續(xù)集成服務(wù)器上。可以直接下載.war
文件,通過java -jar jenkins.war
啟動。我用的是CentOS,直接使用它自帶的包管理器yum
安裝。首先,需要添加jenkins源,可以在官網(wǎng)相關(guān)頁面查看
sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo
sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key
然后便可以使用yum install jenkins
安裝了。安裝完成后,我們通過
sudo service jenkins start
啟動jenkins,如果啟動失敗,按照錯誤提示進行修改,比如我這里是
[root@weibo1 ~]# service jenkins start
Starting Jenkins bash: /usr/bin/java: No such file or directory
[FAILED]
那么可以先使用which java
查看java所在路徑,我這里是/usr/jdk1.8.0_131/bin/java,再通過
ln -s /usr/jdk1.8.0_131/bin/java /usr/bin/java
建立軟連接,再通過service jenkins start
就不會報錯了。這個時候輸入http://your_jenkins_ip:8080/
便可以進入jenkins初始化頁面,如下圖
圖中提示了密碼所在文件,通過
cat /var/lib/jenkins/secrets/initialAdminPassword
可查詢到密碼,將其填入密碼框即可。
之后,Jenkins會提示我們安裝插件,我們選擇自定義安裝。除了它默認(rèn)勾選安裝的插件之外,我們還需要安裝Cobertura Plugin
、JUnit Plugin
,前者是和代碼覆蓋率相關(guān)的插件,后者是單元測試相關(guān)插件,其他暫時不用安裝,然后我們點擊install進行安裝。在安裝進度條走完之后,Jenkins會讓我們填入登錄用戶的用戶名和密碼,提示如下圖
填入之后,我們便可以使用剛才創(chuàng)建的用戶登入系統(tǒng)了。除了在這個時候可以創(chuàng)建用戶,還可以使用超級管理員賬號(賬號為admin
,密碼可以通過cat /var/lib/jenkins/secrets/initialAdminPassword
查看)來創(chuàng)建普通用戶,操作路徑是Jenkins主頁=>系統(tǒng)管理=>管理用戶=>新建用戶
。還可以通過讓用戶自行注冊的方式來添加用戶,不過這個功能默認(rèn)是關(guān)閉的,需要通過Jenkins主頁=>系統(tǒng)管理=>Configure Global Security=>勾選允許用戶注冊
來開啟該功能,這個時候所有用戶都具有讀寫權(quán)限,如果Jenkins暴露在公網(wǎng),會很不安全。我們需要為不同用戶設(shè)置不同權(quán)限,目前Jenkins支持5種訪問控制策略,我們通過Jenkins主頁=>系統(tǒng)管理=>Configure Global Security=>授權(quán)策略
選擇其中的一種,它們的區(qū)別,由于篇幅有限,就不贅述了,推薦選擇安全矩陣
策略,在添加用戶/組
添加需要進行訪問控制的用戶和用戶組。如下是我的設(shè)置:
如果我們想進行Python程序的持續(xù)集成,還可能需要安裝Python Plugin
(很奇怪的是,我在CentOS服務(wù)器上不安裝它也可以進行持續(xù)集成,而在我的MacBook上不安裝卻無法進行Python項目持續(xù)集成,所以為了保險起見,還是安裝吧),它的安裝路徑是Jenkins 主頁=>系統(tǒng)管理=>插件管理=>可選插件=>Python Plugin
。除此之外,這個時候還可以安裝Violations plugin
,它的作用是分析代碼行數(shù)。該插件依賴sloccount
,因此我們這時候可以通過yum install sloccount
安裝。安裝完成后,勾選空閑時重啟Jenkins
。重啟之后,我們便可以進行項目構(gòu)建和持續(xù)集成測試了。
首先講公開項目的持續(xù)集成。公開項目的持續(xù)集成,操作比較簡單。我們首先通過下面的目錄結(jié)構(gòu)創(chuàng)建一個Python程序
py_jenkins/
readme.md
.gitignore
tests/
__init__.py
auth_tests.py
py_jenkins/
__init__.py
auth.py
該程序放在github上,引用的這篇博客的代碼,我改成了Python3的語法。
進入正題,我們點擊新建
開始創(chuàng)建項目,這里我命名為py_jenkins
,選擇“構(gòu)建一個自由風(fēng)格的軟件項目”,如下圖
然后點擊"OK",進入另一個頁面,如下圖
接下來是源碼管理,我們只需要輸入需要構(gòu)建的項目的git地址,這里是
注意,如果持續(xù)集成服務(wù)器上沒安裝Git客戶端,那么這一步會報錯。接下來是構(gòu)建觸發(fā)器,如下圖
這里H/3 * * * *
表示每三分鐘,Jenkins就會去檢查一下Git服務(wù)器代碼是否有變化,有的話就會觸發(fā)構(gòu)建操作。
接下來是構(gòu)建環(huán)境,如下圖:
再是構(gòu)建的時候的具體操作,這里選擇Execute shell
,如果你還有別的需求,可選擇適當(dāng)進行增加選項,如下圖
我們再填入構(gòu)建的腳本,內(nèi)容如下
/usr/local/bin/virtualenv env
. env/bin/activate
pip install --quiet nosexcover
pip install --quiet mock
nosetests --with-xcoverage --with-xunit --cover-package=py_jenkins --cover-erase
/usr/local/bin/pylint -f parseable py_jenkins / | tee pylint.out
/usr/bin/sloccount --duplicates --details py_jenkins > sloccount.sc
注意Execute Shell
的命令的執(zhí)行路徑需要寫絕對路徑或在Jenkins中為該命令設(shè)置環(huán)境變量。pylint不能用虛擬環(huán)境的pylint,否則可能報錯。對于路徑問題,可以通過which virtualenv
來找到virtualenv
在持續(xù)集成服務(wù)器具體的路徑,然后在Jenkins設(shè)置環(huán)境變量,設(shè)置路徑是Jenkins主頁=>系統(tǒng)管理=>系統(tǒng)設(shè)置=>全局屬性
,然后點擊增加,如下圖
最后增加構(gòu)建后操作。--with-xunit
選項會生成nosetests.xml
文件,--with-xcoverage
選項會生成coverage.xml
文件。這里我們選擇Publish JUnit test result report
和Publish Cobertura Coverage Report
,前者會生成本次構(gòu)建的結(jié)果,后者會顯示代碼測試覆蓋率。
pylint生成的語法檢查報告pylint.out
需要配合Violations plugin
插件使用,然后在構(gòu)建后操作中勾選Report Violations
,找到pylint的配置并填寫"**/pylint.out",如下圖:
最后點擊“保存”。
之后,我們回到首頁,在新建的構(gòu)建名中,點擊“立即構(gòu)建”,如下圖
然后,左下方會出現(xiàn)如下所示進度條
如果構(gòu)建步驟比較類似,可以在新建構(gòu)建項目的時候,可以以已有構(gòu)建流程為模版新建構(gòu)建,如下圖所示
構(gòu)建結(jié)果如下
我們可以點擊“太陽”或者“烏云”圖標(biāo),進入查看構(gòu)建的詳細(xì)信息。其中我們重點關(guān)注的是Console Output
、Coverage Report
、Violations
和Test Result
這幾項
再說說私有項目的持續(xù)集成。還是以github為例進行講解。賬號和密碼的方式,我始終未試驗成功,這里我采用的是ssh的方式。先做準(zhǔn)備工作:在Jenkins服務(wù)器上使用
ssh-keygen -t rsa -C "xx@email.com"
來生成公私鑰,在輸入該命令的時候,需要輸入公私鑰的位置,如下
Enter file in which to save the key (/root/.ssh/id_rsa): /root/.ssh/id_rsa
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
這里在輸入密碼的時候,我直接回車,即空密碼。然后,我們使用cat ~/.ssh/id_rsa.pub
查看生成的公鑰,如下
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA5s2HOPlRuEmR8GsAJECFkipgeuuww7qtK6UaURPzCUsXwp9BZ73spNG7fxgu5fj4mkPRsnfWBvKS+0UrEjznNLFQ39/v0TlPohPRcj6a8F4aWx5m7i4PACVmOPLWLjmE8neUDioetw1zWFkPexLprQiQnIKeN3EIa0CVx2+74fJVXYhc+Txk6phsu4Q3kZwUpvnkzQPCysx2c8iKESgkzvr12qWDM10ytZ9X6UaIakzJF00tUSvETEHWbEs8OTv8jbHDtiU64gyZkEyW/vjID/+997JbQa3EvoEJgtziRCjloGy40VQbJ77uI0m/3URv2ar7EiKSV8mJIKrIjSIItw== 1796246076@qq.com
我們需要把上述內(nèi)容復(fù)制到Github上,操作是"點擊個人頭像=>Settings=>SSH and GPG keys=>New ssh key",再把上述內(nèi)容粘貼進去。
之后,可以通過在持續(xù)集成服務(wù)器上使用
ssh -T git@github.com
確認(rèn)公私鑰匹配是否成功,比如我的
Hi ResolveWang! You've successfully authenticated, but GitHub does not provide shell access.
表示可以通過ssh連到github。
這一步完成之后,我們再通過Jenkins主頁=>Credentials=>System=>Global credentials=>add credentials
來進行添加剛生成的私鑰(通過cat ~/.ssh/id_rsa
查看)和Github登錄用戶名,示意圖如下
然后,在構(gòu)建項目的時候,注意不能填寫項目的https地址了,需要填它的ssh地址,并且選擇前面我們保存的證書,如下所示
再說說項目變更如何觸發(fā)Jenkins的構(gòu)建。這個可以采用webhook的方式,比如各個git服務(wù)器的插件,我用的gogs,那么需要安裝gogs plugin
,然后在gogs的對應(yīng)項目的webhook中添加一個鉤子
在構(gòu)建的時候Poll SCM
留空,如圖
這樣會在每次push的時候觸發(fā)構(gòu)建。
最后說說怎么在Github、Gogs或者Gitlab等頁面端如何查看每次的自動化測試結(jié)果。
我們可以安裝一個名為Embeddable Build Status
的插件,安裝之后重啟Jenkins,再進行項目構(gòu)建,構(gòu)建結(jié)果可以查看Embeddable Build Status
,如下圖
這里我們把省略具體構(gòu)建序號,即
那么默認(rèn)就是最新一次構(gòu)建的狀態(tài),我們可以在項目的readme中展示出來。當(dāng)然,除了這種方式之外,還可以在構(gòu)建后設(shè)置,如果構(gòu)建失敗,那么就發(fā)郵件通知相關(guān)人員。
文章最后部分補充一下Jenkins的重要配置。
- 通過
yum
安裝Jenkins,那么Jenkins的安裝目錄為cd /var/lib/jenkins/
- Jenkins配置文件位置為
/etc/sysconfig/jenkins
,比如我們可以在這個文件修改Jenkins web server的默認(rèn)監(jiān)聽端口和地址。除此之外,還有兩個參數(shù)很重要:JENKINS_HOME
、JENKINS_USER
。JENKINS_HOME
是Jenkins的主目錄,Jenkins工作的目錄都放在這里,Jenkins儲存文件的地址,Jenkins的插件,生成的文件都在這個目錄下,JENKINS_USER
是Jenkins的用戶,擁有$JENKINS_HOME
和/var/log/jenkins
的權(quán)限。
還有一點,如果我們修改了JENKINS_HOME
所在目錄,那么一定要設(shè)置JENKINS_HOME
的權(quán)限為jenkins用戶可以讀寫,或把所有者換成jenkins用戶,否則持續(xù)集成的時候可能會報權(quán)限錯誤。
如果對本文還有疑惑,可以留言,也可以閱讀本文的參考文章