簡介
從 GitLab 8.0 開始,GitLab CI 就已經(jīng)集成在 GitLab 中,我們只要在項(xiàng)目中添加一個(gè) .gitlab-ci.yml 文件,然后添加一個(gè) Runner,即可進(jìn)行持續(xù)集成。 而且隨著 GitLab 的升級(jí),GitLab CI 變得越來越強(qiáng)大,本文將介紹如何使用 GitLab CI 進(jìn)行持續(xù)集成。
一些概念
在介紹 GitLab CI 之前,我們先看看一些持續(xù)集成相關(guān)的概念。
Pipeline
一次 Pipeline 其實(shí)相當(dāng)于一次構(gòu)建任務(wù),里面可以包含多個(gè)流程,如安裝依賴、運(yùn)行測試、編譯、部署測試服務(wù)器、部署生產(chǎn)服務(wù)器等流程。
任何提交或者 Merge Request 的合并都可以觸發(fā) Pipeline,如下圖所示:

Stages
Stages 表示構(gòu)建階段,說白了就是上面提到的流程。
我們可以在一次 Pipeline 中定義多個(gè) Stages,這些 Stages 會(huì)有以下特點(diǎn):
- 所有 Stages 會(huì)按照順序運(yùn)行,即當(dāng)一個(gè) Stage 完成后,下一個(gè) Stage 才會(huì)開始
- 只有當(dāng)所有 Stages 完成后,該構(gòu)建任務(wù) (Pipeline) 才會(huì)成功
- 如果任何一個(gè) Stage 失敗,那么后面的 Stages 不會(huì)執(zhí)行,該構(gòu)建任務(wù) (Pipeline) 失敗
因此,Stages 和 Pipeline 的關(guān)系就是:

Jobs
Jobs 表示構(gòu)建工作,表示某個(gè) Stage 里面執(zhí)行的工作。
我們可以在 Stages 里面定義多個(gè) Jobs,這些 Jobs 會(huì)有以下特點(diǎn):
- 相同 Stage 中的 Jobs 會(huì)并行執(zhí)行
- 相同 Stage 中的 Jobs 都執(zhí)行成功時(shí),該 Stage 才會(huì)成功
- 如果任何一個(gè) Job 失敗,那么該 Stage 失敗,即該構(gòu)建任務(wù) (Pipeline) 失敗
所以,Jobs 和 Stage 的關(guān)系圖就是:

GitLab Runner
簡介
理解了上面的基本概念之后,有沒有覺得少了些什么東西 —— 由誰來執(zhí)行這些構(gòu)建任務(wù)呢?
答案就是 GitLab Runner 了!
想問為什么不是 GitLab CI 來運(yùn)行那些構(gòu)建任務(wù)?
一般來說,構(gòu)建任務(wù)都會(huì)占用很多的系統(tǒng)資源 (譬如編譯代碼),而 GitLab CI 又是 GitLab 的一部分,如果由 GitLab CI 來運(yùn)行構(gòu)建任務(wù)的話,在執(zhí)行構(gòu)建任務(wù)的時(shí)候,GitLab 的性能會(huì)大幅下降。
GitLab CI 最大的作用是管理各個(gè)項(xiàng)目的構(gòu)建狀態(tài),因此,運(yùn)行構(gòu)建任務(wù)這種浪費(fèi)資源的事情就交給 GitLab Runner 來做拉!
因?yàn)?GitLab Runner 可以安裝到不同的機(jī)器上,所以在構(gòu)建任務(wù)運(yùn)行期間并不會(huì)影響到 GitLab 的性能~
安裝
安裝 GitLab Runner 太簡單了,按照著 官方文檔 的教程來就好拉!
下面是 Debian/Ubuntu/CentOS 的安裝方法,其他系統(tǒng)去參考官方文檔:
# For Debian/Ubuntu
$ curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-ci-multi-runner/script.deb.sh | sudo bash
$ sudo apt-get install gitlab-ci-multi-runner
# For CentOS
$ curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-ci-multi-runner/script.rpm.sh | sudo bash
$ sudo yum install gitlab-ci-multi-runner
注冊(cè) Runner
安裝好 GitLab Runner 之后,我們只要啟動(dòng) Runner 然后和 CI 綁定就可以了:
- 打開你 GitLab 中的項(xiàng)目頁面,在項(xiàng)目設(shè)置中找到 runners
- 運(yùn)行
sudo gitlab-ci-multi-runner register - 輸入 CI URL
- 輸入 Token
- 輸入 Runner 的名字
- 選擇 Runner 的類型,簡單起見還是選 Shell 吧
- 完成
當(dāng)注冊(cè)好 Runner 之后,可以用 sudo gitlab-ci-multi-runner list 命令來查看各個(gè) Runner 的狀態(tài):
$ sudo gitlab-runner list
Listing configured runners ConfigFile=/etc/gitlab-runner/config.toml
my-runner Executor=shell Token=cd1cd7cf243afb47094677855aacd3 URL=http://mygitlab.com/ci
.gitlab-ci.yml
簡介
配置好 Runner 之后,我們要做的事情就是在項(xiàng)目根目錄中添加 .gitlab-ci.yml 文件了。
當(dāng)我們添加了 .gitlab-ci.yml 文件后,每次提交代碼或者合并 MR 都會(huì)自動(dòng)運(yùn)行構(gòu)建任務(wù)了。
還記得 Pipeline 是怎么觸發(fā)的嗎?Pipeline 也是通過提交代碼或者合并 MR 來觸發(fā)的!
那么 Pipeline 和 .gitlab-ci.yml 有什么關(guān)系呢?
其實(shí) .gitlab-ci.yml 就是在定義 Pipeline 而已拉!
基本寫法
我們先來看看 .gitlab-ci.yml 是怎么寫的:
# 定義 stages
stages:
- build
- test
# 定義 job
job1:
stage: test
script:
- echo "I am job1"
- echo "I am in test stage"
# 定義 job
job2:
stage: build
script:
- echo "I am job2"
- echo "I am in build stage"
寫起來很簡單吧!用 stages 關(guān)鍵字來定義 Pipeline 中的各個(gè)構(gòu)建階段,然后用一些非關(guān)鍵字來定義 jobs。
每個(gè) job 中可以可以再用 stage 關(guān)鍵字來指定該 job 對(duì)應(yīng)哪個(gè) stage。
job 里面的 script 關(guān)鍵字是最關(guān)鍵的地方了,也是每個(gè) job 中必須要包含的,它表示每個(gè) job 要執(zhí)行的命令。
回想一下我們之前提到的 Stages 和 Jobs 的關(guān)系,然后猜猜上面例子的運(yùn)行結(jié)果?
I am job2
I am in build stage
I am job1
I am in test stage
根據(jù)我們?cè)?stages 中的定義,build 階段要在 test 階段之前運(yùn)行,所以 stage:build 的 jobs 會(huì)先運(yùn)行,之后才會(huì)運(yùn)行 stage:test 的 jobs。
常用的關(guān)鍵字
下面介紹一些常用的關(guān)鍵字,想要更加詳盡的內(nèi)容請(qǐng)前往 官方文檔
stages
定義 Stages,默認(rèn)有三個(gè) Stages,分別是 build, test, deploy。
types
stages 的別名。
before_script
定義任何 Jobs 運(yùn)行前都會(huì)執(zhí)行的命令。
after_script
要求 GitLab 8.7+ 和 GitLab Runner 1.2+
定義任何 Jobs 運(yùn)行完后都會(huì)執(zhí)行的命令。
variables && Job.variables
要求 GitLab Runner 0.5.0+
定義環(huán)境變量。
如果定義了 Job 級(jí)別的環(huán)境變量的話,該 Job 會(huì)優(yōu)先使用 Job 級(jí)別的環(huán)境變量。
cache && Job.cache
要求 GitLab Runner 0.7.0+
定義需要緩存的文件。
每個(gè) Job 開始的時(shí)候,Runner 都會(huì)刪掉 .gitignore 里面的文件。
如果有些文件 (如 node_modules/) 需要多個(gè) Jobs 共用的話,我們只能讓每個(gè) Job 都先執(zhí)行一遍 npm install。
這樣很不方便,因此我們需要對(duì)這些文件進(jìn)行緩存。緩存了的文件除了可以跨 Jobs 使用外,還可以跨 Pipeline 使用。
具體用法請(qǐng)查看 官方文檔。
Job.script
定義 Job 要運(yùn)行的命令,必填項(xiàng)。
Job.stage
定義 Job 的 stage,默認(rèn)為 test。
Job.artifacts
定義 Job 中生成的附件。
當(dāng)該 Job 運(yùn)行成功后,生成的文件可以作為附件 (如生成的二進(jìn)制文件) 保留下來,打包發(fā)送到 GitLab,之后我們可以在 GitLab 的項(xiàng)目頁面下下載該附件。
注意,不要把 artifacts 和 cache 混淆了。
實(shí)用例子
下面給出一個(gè)我自己在用的例子:
stages:
- install_deps
- test
- build
- deploy_test
- deploy_production
cache:
key: ${CI_BUILD_REF_NAME}
paths:
- node_modules/
- dist/
# 安裝依賴
install_deps:
stage: install_deps
only:
- develop
- master
script:
- npm install
# 運(yùn)行測試用例
test:
stage: test
only:
- develop
- master
script:
- npm run test
# 編譯
build:
stage: build
only:
- develop
- master
script:
- npm run clean
- npm run build:client
- npm run build:server
# 部署測試服務(wù)器
deploy_test:
stage: deploy_test
only:
- develop
script:
- pm2 delete app || true
- pm2 start app.js --name app
# 部署生產(chǎn)服務(wù)器
deploy_production:
stage: deploy_production
only:
- master
script:
- bash scripts/deploy/deploy.sh
上面的配置把一次 Pipeline 分成五個(gè)階段:
- 安裝依賴(
install_deps) - 運(yùn)行測試(
test) - 編譯(
build) - 部署測試服務(wù)器(
deploy_test) - 部署生產(chǎn)服務(wù)器(
deploy_production)
設(shè)置 Job.only 后,只有當(dāng) develop 分支和 master 分支有提交的時(shí)候才會(huì)觸發(fā)相關(guān)的 Jobs。
注意,我這里用 GitLab Runner 所在的服務(wù)器作為測試服務(wù)器。
轉(zhuǎn)載自 https://scarletsky.github.io/2016/07/29/use-gitlab-ci-for-continuous-integration/