CI/CD Pipeline 需要持續維護,並非建立一次就天下太平了,今天讓我們繼續跟著假想團隊的進度往下走,看看 CI Pipeline 將會做出哪些改變。
隨著自動化測試案例的增加,CI 在執行自動化測試的時間越來越長,另外因為目前的 CI Pipeline 的規劃是先 deploy 至 dev 或 stg 環境,接著在其上執行自動化測試,因此效率又更差了,並且也比較難擴展為並行同步執行測試。因此團隊決定調整 CI Pipeline,並開始引入 Container 技術。
既然要引入 Container,首先要準備一個能夠操控 Container 的 GitLab Runner。還記得我們在 Day 9 的文章中是如何安裝 GitLab Runner 的嗎?那時是在 Server 上以 apt-get
的方式安裝,這次我們要換一個作法,不僅要讓 Runner 可以控制 Container,連 Runner 本身都是以 Container 架設。
首先第一步,要在 Server 上先安裝好 Docker。Docker 的安裝與使用方式本文就不詳述了,還請自己參閱 Docker 官方文件。
接著透過 Docker 來架設 GitLab Runner,並且將 host 上的 docker 分享至 container 內,讓 Runner 能夠控制 Docker,藉此能夠以 container 來執行 CI Job。(這種讓 Container 裡面可以操作 host 的 docker 的做法,又稱為 Docker in Docker。)
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
Runner 架設完畢後,記得一樣要註冊,才算是真正的架設完畢。這次註冊 Runner 的時候,要注意 executor
要選擇 Docker
,以及要給 Runner 一個合適的 tags
與其他非操控 Container 的 Runner 區隔。
(這次是在 Container 內執行 gitlab-runner register
,記得要選擇 docker 作為 executor
,並指定預設使用的 docker image。)
接著就來調整 CI Pipeline,首先回憶一下目前的.gitlab-ci.yml
。
stages:
- build
- deploy
- test
laravel-build:
stage: build
tags:
- "build"
script:
- composer install
- npm install
- npm run production
artifacts:
paths:
- ./
deploy-for-testing:
stage: deploy
tags:
- "shell"
script:
- ansible-playbook deploy-for-testing.yml
testing:
stage: test
tags:
- "shell"
script:
- ansible-playbook unit-testing.yml
- ansible-playbook service-testing.yml
- ansible-playbook gui-testing.yml
接著我們調整 Unit testing,將其改成 Container 取代,調整後的 .gitlab-ci.yml
會類似下面的模樣。
stages:
- build
- unit-test
- deploy
- test
laravel-build:
stage: build
tags:
- "build"
script:
- composer install
- npm install
- npm run production
artifacts:
paths:
- ./
unit-test:
image: phpunit/phpunit
stage: unit-test
tags:
- "container"
script:
- /usr/bin/phpunit -c phpunit.xml --coverage-text --colors-never
dependencies:
- laravel-build
deploy-for-testing:
stage: deploy
tags:
- "shell"
script:
- ansible-playbook deploy-for-testing.yml
testing:
stage: test
tags:
- "shell"
script:
- ansible-playbook service-testing.yml
- ansible-playbook gui-testing.yml
上面調整的是將原本 testing
中的 Unit testing 的動作 ansible-playbook unit-testing.yml
移除,改為一個獨立的 stage
與 CI Job unit-test
。在 CI Job unit-test
中特別之處有三個:
image: phpunit/phpunit
是指我們要使用 phpunit/phpunit 這個 docker image 作為執行 Unit testing 的環境。tags:
則指定為 container
,即是前面我們架設新的 GitLab Runner 時為 Runner 指定的 tags。dependencies:
則是這項 CI Job 相依於哪一個 CI Job 產生的 Artifacts,在執行 script 之前,Runner 會先把指定的 Artifacts 下載到 Container 內。當 GitLab Runner 在執行此 CI Job 時,會自動運行一個 Container 並且將 Source code 或 Artifacts 放進 Container 內,因此只要你選用的 Docker image 及 script:
內的指令撰寫都正確,就可以順利完成自動化測試,畢竟你總不可能要執行的是 php 的 unit testing 卻找一個 java 環境的 docker image 來執行 phpunit。
透過這樣的調整,原本我們必須先有一個 deploy-for-testing
的 CI Job,先將程式部署至 dev 或 stg 環境後才能執行下一個 CI Job testing
。但現在則直接由一個 unit-test
取代。
(如上圖,在 CI Job 的紀錄中有 Using docker image
的動作,這即是以 Container 運行的 CI 環境。)
今天我們將 Unit testing 獨立改用 Container 環境來執行自動化測試。相較於 Service testing、GUI testing,Unit testing 應該是最容易被獨立轉換成 Container 環境的一種測試,正常來說 unit testing 在開發者的 local 就應該先被執行過一次,都能順利通過之後,程式碼才能被允許送進版控。
當然有些開發者的 local 環境可能欠缺執行測試的環境與相依 Packages,但這項問題在 Container 盛行的現在已不再是難解的問題。(甚至不用到 Container,以 Virtual Machine 就已經足夠方便解決。)
因為 Container 具備的封裝性、可攜性與便利性,讓開發者的 local 環境、CI Service 執行 CI Job 的環境,甚至是 Production 環境都能更便捷的保持一致。過去開發者與維運人員經常容易在環境架設及組態設定上起爭執而搞不定的狀況,現在藉助 Container 也更容易解決了。對於自動化測試及 CI/CD 而言,學習如何善用 Container 幾乎是一項先決條件了。
最後,針對今天的內容提幾個問題:
自 2021 年 12 月 12 日開始,我就一直想要將原發佈在 iT 邦幫忙的鐵人賽系列文章搬移至 https://gitlab-book.tw 並補充說明文章內容已有過期之處。
因為當初參加 iThome 鐵人賽時,GitLab 仍在 12 版,但如今 GitLab 已更新好幾版了,需要提醒大家注意一下。
本文已完成搬遷