1. 程式人生 > >在Python Web專案中使用Jenkins進行持續整合

在Python Web專案中使用Jenkins進行持續整合

在一個專案的開發過程中,往往會有一些需要反覆執行的操作,比如編譯、測試、部署。具體於Flask專案,我一般使用nose執行單元測試、fabric進行部署、pylint執行程式碼質量檢測等。這些頻繁需要執行的步驟,是非常枯燥的,那何不交給機器來自動執行呢?最近,我參與的一個校內團隊也遇到了類似的問題,於是打算調研一下相關的工具。

還是習慣性地查閱了下Kenneth Reitz大神的python-guide,果然找到了關於CI的章節。選來選去,最終沒有選擇Python Stack的Buildbot,而是更加成熟的Jenkins。Jenkins基於Java開發,是業界使用得最多的一款持續整合系統,市場份額佔到了

70%

關於Jenkins,官方的介紹如下:

monitors executions of repeated jobs, such as building a software project or jobs run by cron。

文件中也說目前Jenkins專注於以下2個點:

  • Building/testing software projects continuously
  • Monitoring executions of externally-run jobs

其實Jenkins能夠做的遠不止這兩點,你可以把它理解成可以自動執行任務(類似cron)並收集報告的基礎工具。再加上它有著非常豐富的外掛庫,所以使用起來應該是很靈活的。

下面記錄一些在Python Web專案中應用Jenkins的經驗。

安裝

需要提的一點是Jenkins比較耗記憶體,不執行任何構建任務的情況下就吃掉了300多M,再加上構建任務時會佔用更多,所以建議伺服器的記憶體至少有1G,512M的話很可能在執行構建任務的時候記憶體不夠用。

訪問控制

外掛清單

下面是我用到的一些外掛:

  • Git Plugin:使用Git作為原始碼管理
  • SSH plugin:遠端ssh登入server執行命令
  • Parameterized Trigger Plugin:觸發其他的job
  • Cobertura Plugin:程式碼測試覆蓋率報告
  • Task Scanner Plugin:檢測程式碼中出現的特殊標記(如TODO等)
  • Violations:程式碼質量檢測,支援pylint、jslint等
  • ThinBackup:用於備份Jenkins
  • SCM Sync configuration plugin:將Jenkens的配置變更同步到SCM中

這裡只是集中地列舉一下,具體的使用會在下面穿插介紹。

測試、Staging部署、Production部署流程

根據本專案的需要,在Jenkins中建立了3個任務:

  • tm_test:用於執行測試、程式碼質量檢測等
  • tm_staging_deploy:用於在staging伺服器上deploy程式碼
  • tm_deploy:用於在production伺服器上deploy程式碼

Image Title

其中staging伺服器用於進行線上測試,staging伺服器和production伺服器的環境必須保持完全相同(當然,staging伺服器配置可以低一些)。

具體的開發、測試、部署流程是:

  • 在開發新功能/修復bug的時候,一般是開新分支;但如果是那種很小的修改,則直接在master上改,這樣比較省事兒
  • 新功能開發完成/bug修復後,進行單元測試+人工測試,如果通過,合併到master
  • 每次master有變動後,觸發tm_test任務,執行整合的單元測試和程式碼質量檢測,如果OK,則自動觸發tm_staging_deploy,部署到staging伺服器上
  • 若tm_staging_deploy成功,則登陸到執行在staging伺服器的測試網站上,人工測試新功能是否OK/bug是否已修復;若tm_staging_deploy失敗,檢查失敗原因,進行修復,直至成功
  • 若staging人工測試通過,則手動觸發tm_deploy,部署到生產伺服器上
  • 登入到生產伺服器上進行人工測試,若出現問題,進行修復;同時密切關注Sentry傳送的告警郵件,爭取在第一時間修復錯誤

比較簡單,沒有采用Git-Flow/GitHub-Flow,單元測試寫得很淺,也沒有做程式碼審查。不過團隊規模小,從目前來看,上面的流程是夠用的。

下面對這三個任務做較為詳細的介紹。

tm_test

該任務用於執行測試、程式碼質量檢測等。

push觸發構建

每當專案倉庫的master分支有變動時,即會觸發tm_test。要做這一點,需要如下步驟:

  • 設定tm_test的Build Triggers為Poll SCM,但不填Schedule
  • 為專案倉庫新增Web Hook,URL填寫http://<Jenkins URL>/git/notifyCommit?url=<URL of the Git repository>

使用virtualenv配置測試環境

執行測試之前,需要確定Python版本(一般是2.7),然後根據此版本初始化virtualenv。

在構建中新增Execute shell項:

if [ ! -d "venv" ]; then
virtualenv -p /usr/bin/python2.7 venv
fi

. venv/bin/activate
pip install -i http://pypi.douban.com/simple -r requirements.txt

測試與報告

測試中需要2個庫:nose用於執行單元測試,coverage用於統計測試覆蓋率。

需要在Jenkins中安裝Cobertura Plugin外掛,用於生成程式碼測試覆蓋率報告。

然後在構建中新增Execute shell項,輸入:

nosetests --with-xunit --with-coverage --cover-package=tm && coverage xml

其中--with-xunit告訴nose輸出JUnit形式的測試報告,--with-coverage表示同時執行coverage(這個功能相當贊),--cover-package=tm表示僅對指定的package執行測試覆蓋率檢測,後面的coverage xml表示輸出xml格式的coverage報告。

然後在構建後操作中,新增如下2項:

  • Publish JUnit test result report:填寫nosetests.xml
  • Publish Cobertura Coverage Report:填寫coverage.xml

這樣一來,就可以執行測試,並得到測試報告和測試覆蓋率報告啦:

Image Title

上面的圖表都是可點選的,點進去後有程式碼級的詳細報告,非常贊:

Image Title

綠色的程式碼行表示已經覆蓋到,紅色則沒有。

程式碼質量檢測

Jenkins有一個蠻不錯的程式碼質量報告外掛:Violations,支援非常多的程式碼測試工具。目前專案中使用Pylint做Python程式碼質量檢測,使用JSHint做JavaScript程式碼質量檢測。

在安裝好Pylint後,執行pylint --generate-rcfile > pylintrc生成配置檔案,並將其中的output-format項的值改為parseable

然後在構建中新增2項Execute shell項,

pylint:

pylint tm2 > pylint.xml || exit 0

jshint:

jshint --reporter=jslint $WORKSPACE/tm2/static/js/ > jslint.xml || exit 0

其中的exit 0是為了告訴Jenkins該命令執行成功。對於jshint來說,report選擇jslint,然後需要使用$WORKSPACE組成絕對路徑,否則無法看到原始碼級的分析報告(是不是一個bug?)。

然後在構建後步驟中新增Violations Report,在對應位置輸入jslint.xml和pylint.xml。

最終的圖形報告如下,可以看到趨勢走向:

Image Title

原始碼級別的分析也有:

Image Title

檢測程式碼中的特殊標註(如TODO)

團隊中約定,在程式碼未完成的地方使用TODO進行標記,因為PyCharm有一個很好的功能就是可以檢測出程式碼中的所有TODO資訊:

Image Title

Jenkins中也有一個非常棒的外掛Task Scanner Plugin用於檢測程式碼中出現的特殊標記,當然,這些特殊標記完全是可以自定義的。

安裝完該外掛後,在構建後操作中新增一項Scan workspace for open tasks,根據需要填寫配置:

Image Title

然後報告就可以出來啦:

Image Title

郵件告警

如果構建後狀態是unstable或failed,則可以傳送郵件告警,及時通知相關負責人進行處理。Jenkins自帶SMTP功能,不過需要你提供SMTP伺服器。

我使用的是qq郵箱SMTP伺服器,挺好用的,目前沒有發現拒發的情況。有一點需要注意的是,在配置好SMTP的賬戶資訊後,還需填寫系統管理員郵件地址,否則會發送失敗,這也是比較容易忽略的地方。

配置好SMTP後,然後在構建後操作中新增E-mail Notification項,填寫負責人的郵箱即可。

觸發下游任務

如果tm_test構建成功,則需要自動觸發tm_staging_deploy任務,這個觸發過程是通過外掛Parameterized Trigger Plugin來完成的。

在構建後操作中新增Trigger parameterized build on other projects項,選擇觸發條件為stable,然後填寫待出發的任務名稱即可。

最後的tm_test任務面板如下:

Image Title

介面是挺out的,不過很實用。

tm_staging_deploy

這一個job用於將最新程式碼部署到staging伺服器上,我採用的部署方法是通過ssh遠端登陸伺服器執行命令的方式,需要一個外掛SSH plugin。

然後在構建中新增Shell項:

cd /var/www/tm
export MODE=PRODUCTION
git reset --hard HEAD
git pull -f
source venv/bin/activate
pip install -r requirements.txt
python manage.py db upgrade
supervisorctl restart tm

tm_deploy

此任務和tm_staging_deploy基本差不多,不同的地方有2個:(1)目標伺服器不同(2)觸發方式是手動觸發

備份

使用thinBackup進行備份,可設定備份週期。

配置變更同步

除此之外,我還用到了一個很有用的外掛SCM Sync configuration plugin,就是把Jenkins的配置(全域性配置+各job配置)同步到一個Git倉庫中。這樣的話,每次配置有變動,都會形成一個commit推送到Git倉庫。

這相當於把配置的歷史變遷都記錄下來,如果哪天Jenkins任務掛了,可以看看配置變更進行排錯。

就這些,如果你好的建議,歡迎反饋!

參考

· EOF ·