Gitlab CI 持續集成的完整實踐python
本着公司團隊初創,又在空檔期想搞點事情,搭建了私有Gitlab的契機,順便把持續集成搭建起,實現了對Python服務端代碼的單元測試、靜態代碼分析和接口測試的持續集成。整體架構以下:git
執行過程:github
-
開發提交代碼後,自動觸發gitlab-runner拉取executor鏡像執行單元測試,單元測試代碼中包含上傳測試結果到x-utest測試平臺;redis
-
單元測試經過後,gitlab-runner拉取sonar-scanner鏡像執行靜態代碼分析,分析結果評論在commit中或保存於sonarqube;docker
-
靜態代碼分析結束,執行分發操做,將代碼分發至灰度測試服務器,並運行;數據庫
-
執行接口測試,執行完成後上傳測試結果到x-utest測試平臺。後端
四個任務相互依賴,只在前一個任務狀態爲成功狀況下才會執行。api
Gitlab CI 基本配置
針對某個須要作CI/CD的項目,須要將代碼庫的該設置打開,併爲其配置 gitlab-runner。服務器
gitlab runner
gitlab-runner不只能夠運行在物理機,還能夠運行在容器中。考慮到gitlab-runner消耗的資源少,使用容器更合適。架構
拉取gitlab-runner Docker 鏡像:
sudo docker pull gitlab/gitlab-runner
啓動容器:
sudo docker run -d --name gitlab-runner --restart always \
-v /srv/gitlab-runner/config:/etc/gitlab-runner \
-v /var/run/docker.sock:/var/run/docker.sock \
gitlab/gitlab-runner:latest
在容器中執行register操做,將gitlab上的項目註冊到gitlab-runner中:
sudo docker exec -it gitlab-runner gitlab-ci-multi-runner register
輸入上述命令後會有一系列的配置須要輸入,固然也能夠設置完後進行更改 按照提示輸入便可,前兩項能夠在指定項目設置中CI/CD選項裏的Runners settings選項中的Specific Runners裏看到,tags是gitlab-ci.yml文件中所要用到的,executor選擇docker 配置成功後,咱們能夠在設置中CI/CD選項裏的Runners settings選項中的Specific Runners裏看到runner信息
本地executor鏡像
爲了部署與測試,須要一個鏡像用於執行。當選用本地鏡像時,可能會出現拉取鏡像失敗。
拉取鏡像失敗
報錯的緣由在於,gitlab-runner嘗試去官方的docker hub倉庫拉取鏡像。經過修改gitlab-runner中的配置,設置只拉取本地鏡像:
修改 /etc/gitlab-runner/config.toml ,在 [runners.docker]
下,添加:
pull_policy = never # 該配置默認always,即只在線上拉取鏡像
若是有須要添加一些hosts映射,仍然在 [runners.docker]
下,添加:
extra_hosts = ["hostname:ip"]
另外爲了加快單元測試執行速度,將服務端代碼的依賴提早安裝至executor鏡像中:
COPY requirement.txt .
RUN pip install -r requirement.txt
編寫 .gitlab-ci.yaml
單元測試部分
用nose執行測試
對於Python,nosetest工具能夠嗅探與執行你寫的全部測試用例,並輸出結果。在執行測試前,使用nose須要使用pip安裝
pip install nose
安裝完成後,使用 nosetests
執行。
nosetests
自寫測試入口
另外一個執行測試的選擇,是自寫測試入口,不依賴nose。好處是可以將測試結果上傳至x-utest。 對測試結果作判斷,若是所有用例經過(即wasSuccessful爲True),則sys.exit(0),不然sys.exit(1)
redis與mongo服務化
對於redis與mongo這種外部服務,有兩種解決方式,一是mock對數據庫的讀寫,二是使用服務化的redis與mongo,保證外部環境的一致性。(更推薦第一種方式,此處介紹第二種。)
因爲設置了不從docker hub拉取鏡像,所以須要先拉取redis與mongo服務鏡像到本地
docker pull redis:2.8
docker pull mongo:3.2
在gitlab-ci.yaml中添加services:
services:
- redis:2.8
- mongo:3.2
修改代碼的local_config配置文件中的mongo與redis鏈接URL,指向「mongo」與「redis」
靜態代碼分析
sonarqube搭建
製作了一個docker-compose項目能夠一鍵部署SonarQube平臺,使用postgres做爲後端數據庫,並將數據持久化在宿主機本地。
git clone https://github.com/ityoung/sonarqube-docker.git
pip install docker-compose
cd sonarqube-docker
docker-compose up
sonar scanner配置
同時針對Python開源了sonar-scanner鏡像的Dockerfile ,該鏡像已經安裝pylint,方便作Python的靜態代碼分析。
git clone https://github.com/ityoung/sonar-scanner-docker.git
cd sonar-scanner-docker
docker build -t sonar-scanner .
YAML添加執行命令
啓動SonarQube後,進入IP:9000到SonarQube管理頁面,登陸admin/admin,新建一個項目,按步驟執行完成
建立一個project
建立完成後,獲取到執行代碼,複製這段代碼,添加到yaml中,可以實現分析結果上傳到SonarQube。
獲取sonar-scanner執行腳本
注意:若是yaml中用到了兩個鏡像,儘可能不要有before_script,不然可能兩個鏡像,觸發錯誤。
Sonar分析後評論
對於develop分支,能夠不保存分析結果,而改成將分析結果評論在當次commit下。
在yaml腳本中添加以下參數:
- sonar-scanner
-Dsonar.analysis.mode=preview
-Dsonar.gitlab.commit_sha=$CI_BUILD_REF
-Dsonar.gitlab.ref_name=$CI_BUILD_REF_NAME
-Dsonar.gitlab.project_id=$CI_PROJECT_ID
注意:無新issue時默認不會評論,須要在SonarQube修改gitlab配置纔會每次都評論。
持續交付
這部分交由對服務端部署更熟悉的運維操做。
接口測試
接口測試代碼在另外一個倉庫,這就涉及到從另外一個倉庫clone測試代碼時的權限問題。
給倉庫URL添加token可以實現跨倉庫clone代碼:
git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.xxx.com/yx/apitest.git
附一:完整的.gitlab-ci.yml
image: pro1_executor stages: - unittest - analyze - deploy - apitest variables: SONAR_HOST: "http://192.168.0.29:9000" SONAR_PROJ: "pro_1" SONAR_LOGIN: "b3135dd602b61ce7ff5f4202a3ec2ec0865fa7f5" services: - redis:3 - mongo:3.2 UnitTest: stage: unittest script: - pip install nose - python -m runtest xtest Sonar_Preview: image: sonar-scanner stage: analyze script: - sonar-scanner -Dsonar.analysis.mode=preview -Dsonar.gitlab.commit_sha=$CI_BUILD_REF -Dsonar.gitlab.ref_name=$CI_BUILD_REF_NAME -Dsonar.gitlab.project_id=$CI_PROJECT_ID -Dsonar.projectKey=$SONAR_PROJ -Dsonar.sources=. -Dsonar.host.url=$SONAR_HOST -Dsonar.login=$SONAR_LOGIN except: - master Sonar_Analyze: image: sonar-scanner stage: analyze script: - sonar-scanner -Dsonar.projectKey=$SONAR_PROJ -Dsonar.sources=. -Dsonar.host.url=$SONAR_HOST -Dsonar.login=$SONAR_LOGIN only: - master Deploy_TestServer: stage: deploy script: echo "deploy" API_Test: stage: apitest script: - cd / - git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.xxx.com/yx/apitest.git - cd apitest - pip install -r requirements.txt - python runtest.py
參考:
[1] https://mp.weixin.qq.com/s/fJPNg8jPkLAd0y8-D7xBYw