iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 26
2
DevOps

CI 從入門到入坑系列 第 26

功能強大的 -- GitLab CI

GitLab 本身功能非常豐富,加上它又是開源可以自行架設的,通常會是企業選擇版控的首選。後來又追加 GitLab CIPipeline 功能,讓它的戰場跨越到 CI ,並成為一個企業內部管理開發流程的好選擇。

CI Server 跟版控通常會是不一樣的 server , CI 會執行 Build ,並通知版控說,目前提交是否成功。那 GitLab CI 與 GitLab 的概念也一樣,它是另外獨立且可選的元件。打個比方, Bitbucket 之於 Circle CI ,就類似 GitLab 之於 GitLab CI 一樣。

以下將使用 GitLab.com 服務當作範例。

注意,如果是自己架設 GitLab 的話, 8.0 之後才支援 GitLab CI 。另外功能會參考目前最新版介紹,使用之前記得確認自己家的版本是否有支援。

設定專案

之前用的專案都是在 GitHub 上執行,要換到 GitLab 有很多種方法,那這邊示範比較簡單的 Mirror Repository 。如果想直接用 GitLab 上的專案直接開始的可以跳過這一小節。

首先先登入 GitLab 帳號,建立一個空的新專案。

day26 step1-1

接著在右上角的齒輪,選擇 Mirror Repository

day26 step1-2

這裡要填的是可以 git clone 下來的地方,那因為專案是 public ,直接使用 https 會單純許多。

如果是 private 可參考 Mirror Repository 文件說明

day26 step1-3

記得下面 Trigger builds for mirror updates 要打勾,因為我們是要靠 GitHub 的更新來觸發 GitLab CI 執行 Build 。

day26 step1-4

再來進到專案抬頭的右下角,會有個 Set up CI

day26 step1-5

點下去就會進入編輯界面,這裡就是要編輯 CI 的設定檔 .gitlab-ci.yml 了。


因為 Mirror Repository 每小時才會同步,這樣做可以立即觸發並看到結果,但同步可能就會有問題,建議是在 GitLab 另外開 branch 測試會比較好。

首先專案抬頭的中間偏左,有個 Branches 的連結。點下去後,右上角會有 New Branch 的按鈕,按下去後,在 branch name 打上想叫的名字,再按 Create Branch

day26 step1-6

接著會被導到如下面的檔案列表頁面,點中間的 + 代表要新增檔案,接著打檔名 .gitlab-ci.yml 即可在不同 branch 練習建置 CI 了。

day26 step1-7

版控串接

對其他家 SaaS CI 服務而言,要連結版控系統和 CI Server 才算串接成功,對 GitLab 而言,只要新增 .gitlab-ci.yml 檔,它就算串接完成了。

來看簡單的範例

image: mileschou/php-testing-base:7.0

stages:
  - build
  - test
  - deploy

build_job:
  stage: build
  script:
    - composer install
  cache:
    untracked: true
  artifacts:
    paths:
      - vendor/

test_job:
  stage: test
  script:
    - php vendor/bin/codecept run
  dependencies:
    - build_job

deploy_job:
  stage: deploy
  script:
    - echo Deploy OK
  only:
    - release
  when: manual

建好之後,按下上面的 Pipelines 頁籤,就會看到有一個 Build 開始在跑了

day26 step2-1

有興趣可以翻翻看連結網頁裡面有什麼。

GitLab 的功能比較複雜,先簡單說明。 GitLab 的 build 都是在 Docker 上執行的,因此一開始會需要定義 image 名稱,而它將會成為下面執行 build 的環境。

下面這個例子是我自己寫來測試用的,有興趣可以參考 GitHub 原始碼

image: mileschou/php-testing-base:7.0

接著 GitLab CI 預定義有三個階段,也就是 stages

stages:
  - build
  - test
  - deploy

一個 stages 可以定義一個或多個 job ,而 job 是定義在 yaml 最外層。比方說,上例的 build_job 階段對應的是 build stage

build:
  stage: build
  script:
    - composer install
  cache:
    untracked: true
  artifacts:
    paths:
      - vendor/

job 裡面的定義常用的如上面這個範例:

  • stage 剛剛說明的,定義 job 要在哪個 stage 執行
  • script 是 job 實際會執行的腳本,上例是安裝套件
  • cache 會把套件快取起來,下次啟動同一個 job 的時候會再使用
  • artifacts 會把裡面編譯或程式的產出物存放起來,提供介面給其他需要的人使用

再來 test_job 定義的稍有不同:

test_job:
  stage: test
  script:
    - php vendor/bin/codecept run
  dependencies:
    - build_job

這邊 dependencies 設定意思是指,它這個測試要取用 build_jobartifacts 。別忘了,每個 job 都是獨立的 container ,互不相關,因此要靠這些設定來傳遞 Artifacts

deploy_job 的定義:

deploy_job:
  stage: deploy
  script:
    - echo Deploy OK
  only:
    - release
  when: manual
  • only 代表這個 job 只在 release branch 執行
  • when 代表何時會執行,此例是指要手動觸發 job

使用 Docker

GitLab CI 上要使用 Docker 需要多做一些事,首先 Docker 是 Client / Server 架構,所以代表兩邊都需要準備一些東西才行。 Server 比較簡單,只要最上面定義全域服務即可:

services:
  - docker:dind

它的做法會用 docker run 啟動 docker:dind 並把上面定義的 image 起的容器連結至 docker:dind 。所以另一個比較麻煩相信已經發現了,上面定義的 image 必須要有 Docker Client 與設定才能正常的連接。

因此,如果只是要 build image ,利用 artifacts 和參考官方說明文件應該很容易達成,以下是個簡單的範例:

注意 image 和 service 雖然有全域定義,但也能 job 各自定義

deploy_job:
  stage: deploy
  image: docker:latest
  services:
    - docker:dind
  script:
    - docker build -t xxx:ooo .
  dependencies:
    - build_job

特異功能

GitLab CI 設計的蠻有彈性的,因此可以做的變化也不少。這裡提兩個小技巧:自定義 Stage 與 Job 自由對應,當 CI 流程需要很長的時候, GitLab 提供自定義 stage 的功能,舉例可以有五個 stage:

stages:
  - build
  - test
  - release
  - docker
  - deploy

Stage 自定義功能其實還好,一般 CI 流程應該不會那麼多,但配合 Job 自由對應的彈性就會非常好用。如 CI 想要測 PHP 5.6 / 7.0 的範例:

image: mileschou/php-testing-base:7.0

stages:
  - build
  - test
  - deploy

build:5.6:
  stage: build
  image: mileschou/php-testing-base:5.6
  script:
    - composer install
  cache:
    untracked: true
  artifacts:
    paths:
      - vendor/

build:7.0:
  stage: build
  image: mileschou/php-testing-base:7.0
  script:
    - composer install
  cache:
    untracked: true
  artifacts:
    paths:
      - vendor/

test:5.6:
  stage: test
  image: mileschou/php-testing-base:5.6
  script:
    - php vendor/bin/codecept run
  dependencies:
    - build:5.6

test:7.0:
  stage: test
  image: mileschou/php-testing-base:7.0
  script:
    - php vendor/bin/codecept run
  dependencies:
    - build:7.0

deploy_job:
  stage: deploy
  script:
    - echo Deploy OK
  dependencies:
    - build:7.0
  only:
    - release
  when: manual

上述設定執行結果: https://gitlab.com/MilesChou/book-intro-of-ci/pipelines/5546894

另外,因為是 GitLab 本家出的 CI ,因此它跟 GitLab 的版控與 issue tracker 功能整合都不錯。


今日回顧

撇除 GitLab.com 的速度真的有點慢之外,個人是認為 GitLab CI 對企業來說,會是一個不錯的選擇。

如果公司內部有在用 GitLab 而不能用外部服務的話,趕快看一下版本是不是 8.0 吧!幸運的話,馬上就可以開始 CI 囉!


上一篇
不公開專案的好選擇 -- Circle CI
下一篇
多樣服務整合 -- Pipelines
系列文
CI 從入門到入坑30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
astroneuro
iT邦新手 3 級 ‧ 2018-07-02 17:54:50

想請問GitLab的CI runner所使用的 .gitlab-ci.yml,是否可以寫for loop每個資料夾呢?

因為我的gitlab 的project裡,不只有一個project,而是有多個,
想要在每個專案(資料夾)都執行同個command,eg. dotnet build

資料夾結構如下:
第1層GitlabProject
第2層.gitlab-ci.yml
第2層project folder
第3層Project1-dotnet build
第3層Project2-dotnet build
第3層Project3-dotnet build
.....
我的想法是在forloop(cd 進專案資料夾-> 執行command)
試過直接寫for %L in folder -> L它不認得
也試過在script裡 叫他call 另一個.sh ->它會出現Job succeeded但根本沒執行.sh

我的runner環境是 win7

謝謝:)

我要留言

立即登入留言