簡介
從 GitLab 8.0 開始,GitLab CI 就已經集成在 GitLab 中,我們只要在項目中添加一個 .gitlab-ci.yml
文件,然后添加一個 Runner,即可進行持續集成。 而且隨着 GitLab 的升級,GitLab CI 變得越來越強大,本文將介紹如何使用 GitLab CI 進行持續集成。
一些概念
在介紹 GitLab CI 之前,我們先看看一些持續集成相關的概念。
Pipeline
一次 Pipeline 其實相當於一次構建任務,里面可以包含多個流程,如安裝依賴、運行測試、編譯、部署測試服務器、部署生產服務器等流程。
任何提交或者 Merge Request 的合並都可以觸發 Pipeline,如下圖所示:
+------------------+ +----------------+ |
Stages
Stages 表示構建階段,說白了就是上面提到的流程。
我們可以在一次 Pipeline 中定義多個 Stages,這些 Stages 會有以下特點:
- 所有 Stages 會按照順序運行,即當一個 Stage 完成后,下一個 Stage 才會開始
- 只有當所有 Stages 完成后,該構建任務 (Pipeline) 才會成功
- 如果任何一個 Stage 失敗,那么后面的 Stages 不會執行,該構建任務 (Pipeline) 失敗
因此,Stages 和 Pipeline 的關系就是:
+--------------------------------------------------------+ |
Jobs
Jobs 表示構建工作,表示某個 Stage 里面執行的工作。
我們可以在 Stages 里面定義多個 Jobs,這些 Jobs 會有以下特點:
- 相同 Stage 中的 Jobs 會並行執行
- 相同 Stage 中的 Jobs 都執行成功時,該 Stage 才會成功
- 如果任何一個 Job 失敗,那么該 Stage 失敗,即該構建任務 (Pipeline) 失敗
所以,Jobs 和 Stage 的關系圖就是:
+------------------------------------------+ |
GitLab Runner
簡介
理解了上面的基本概念之后,有沒有覺得少了些什么東西 —— 由誰來執行這些構建任務呢?
答案就是 GitLab Runner 了!
想問為什么不是 GitLab CI 來運行那些構建任務?
一般來說,構建任務都會占用很多的系統資源 (譬如編譯代碼),而 GitLab CI 又是 GitLab 的一部分,如果由 GitLab CI 來運行構建任務的話,在執行構建任務的時候,GitLab 的性能會大幅下降。
GitLab CI 最大的作用是管理各個項目的構建狀態,因此,運行構建任務這種浪費資源的事情就交給 GitLab Runner 來做拉!
因為 GitLab Runner 可以安裝到不同的機器上,所以在構建任務運行期間並不會影響到 GitLab 的性能~
安裝
安裝 GitLab Runner 太簡單了,按照着 官方文檔 的教程來就好拉!
下面是 Debian/Ubuntu/CentOS 的安裝方法,其他系統去參考官方文檔:
# For Debian/Ubuntu |
注冊 Runner
安裝好 GitLab Runner 之后,我們只要啟動 Runner 然后和 CI 綁定就可以了:
- 打開你 GitLab 中的項目頁面,在項目設置中找到 runners
- 運行
sudo gitlab-ci-multi-runner register
- 輸入 CI URL
- 輸入 Token
- 輸入 Runner 的名字
- 選擇 Runner 的類型,簡單起見還是選 Shell 吧
- 完成
當注冊好 Runner 之后,可以用 sudo gitlab-ci-multi-runner list
命令來查看各個 Runner 的狀態:
$ sudo gitlab-runner list |
.gitlab-ci.yml
簡介
配置好 Runner 之后,我們要做的事情就是在項目根目錄中添加 .gitlab-ci.yml
文件了。
當我們添加了 .gitlab-ci.yml
文件后,每次提交代碼或者合並 MR 都會自動運行構建任務了。
還記得 Pipeline 是怎么觸發的嗎?Pipeline 也是通過提交代碼或者合並 MR 來觸發的!
那么 Pipeline 和 .gitlab-ci.yml
有什么關系呢?
其實 .gitlab-ci.yml
就是在定義 Pipeline 而已拉!
基本寫法
我們先來看看 .gitlab-ci.yml
是怎么寫的:
# 定義 stages |
寫起來很簡單吧!用 stages
關鍵字來定義 Pipeline 中的各個構建階段,然后用一些非關鍵字來定義 jobs。
每個 job 中可以可以再用 stage
關鍵字來指定該 job 對應哪個 stage。
job 里面的 script
關鍵字是最關鍵的地方了,也是每個 job 中必須要包含的,它表示每個 job 要執行的命令。
回想一下我們之前提到的 Stages 和 Jobs 的關系,然后猜猜上面例子的運行結果?
I am job2 |
根據我們在 stages
中的定義,build
階段要在 test
階段之前運行,所以 stage:build
的 jobs 會先運行,之后才會運行 stage:test
的 jobs。
常用的關鍵字
下面介紹一些常用的關鍵字,想要更加詳盡的內容請前往 官方文檔
stages
定義 Stages,默認有三個 Stages,分別是 build
, test
, deploy
。
types
stages
的別名。
before_script
定義任何 Jobs 運行前都會執行的命令。
after_script
要求 GitLab 8.7+ 和 GitLab Runner 1.2+
定義任何 Jobs 運行完后都會執行的命令。
variables && Job.variables
要求 GitLab Runner 0.5.0+
定義環境變量。
如果定義了 Job 級別的環境變量的話,該 Job 會優先使用 Job 級別的環境變量。
cache && Job.cache
要求 GitLab Runner 0.7.0+
定義需要緩存的文件。
每個 Job 開始的時候,Runner 都會刪掉 .gitignore
里面的文件。
如果有些文件 (如 node_modules/
) 需要多個 Jobs 共用的話,我們只能讓每個 Job 都先執行一遍 npm install
。
這樣很不方便,因此我們需要對這些文件進行緩存。緩存了的文件除了可以跨 Jobs 使用外,還可以跨 Pipeline 使用。
具體用法請查看 官方文檔。
Job.script
定義 Job 要運行的命令,必填項。
Job.stage
定義 Job 的 stage,默認為 test
。
Job.artifacts
定義 Job 中生成的附件。
當該 Job 運行成功后,生成的文件可以作為附件 (如生成的二進制文件) 保留下來,打包發送到 GitLab,之后我們可以在 GitLab 的項目頁面下下載該附件。
注意,不要把 artifacts
和 cache
混淆了。
實用例子
下面給出一個我自己在用的例子:
stages: |
上面的配置把一次 Pipeline 分成五個階段:
- 安裝依賴(
install_deps
) - 運行測試(
test
) - 編譯(
build
) - 部署測試服務器(
deploy_test
) - 部署生產服務器(
deploy_production
)
設置 Job.only
后,只有當 develop 分支和 master 分支有提交的時候才會觸發相關的 Jobs。
注意,我這里用 GitLab Runner 所在的服務器作為測試服務器。
參考資料
https://about.gitlab.com/gitlab-ci/
http://docs.gitlab.com/ce/ci/yaml/README.html
http://docs.gitlab.com/ce/ci/variables/README.html
https://gitlab.com/gitlab-org/gitlab-ci-multi-runner
https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/issues/1232
http://stackbox.cn/2016-02-gitlab-ci-conf/