GitLab: 建立第一條 CI/CD Pipeline

本系列文是從 iT 邦幫忙鐵人賽系列文章搬至 gitlab-book.tw,鐵人賽撰文時 GitLab 仍為 12.x 版本,因此本系列文內容已有部分過期,本次搬移至此後,會視狀況新增一些補註說明。

本系列文是從 iT 邦幫忙鐵人賽系列文章搬至 gitlab-book.tw,鐵人賽撰文時 GitLab 仍為 12.x 版本,因此本系列文內容已有部分過期,本次搬移至此後,會視狀況新增一些補註說明。 鐵人賽原文網址:https://ithelp.ithome.com.tw/articles/10219427

昨天我們將 GitLab Runner 架設好了,今天要來試行昨天規劃好的 CI/CD Pipeline。

.gitlab-ci.yml 搞定 CI/CD Pipeline

GitLab CI 預設會檢查 Project 內是否含有名為 .gitlab-ci.yml 的檔案,並根據該檔案所定義的內容自動建立 CI/CD Pipeline。因此如果要建立昨天規劃的 dev 與 stg 這兩條 Pipeline,我們可以按以下的步驟撰寫 .gitlab-ci.yml

首先要宣告 Pipeline 有哪些 stages,並排定他們的先後順序。

stages:
  - build
  - deploy
  - test

接著描述每一個 stage 裡面有哪些 job。下面以 dev 的 Pipeline 為例,先為 build 這個 stage 設置 job

# 首先宣告 job 的名稱
dev-build:
  # 宣告此 job 屬於哪一個 stage 
  stage: build
  # 限制只有 develop branch 會執行此 job
  only:
    - develop
  # 最後是此 job 要執行哪些動作
  script:
    - echo "dev build"

按同樣的概念,整個 dev 的 Pipeline 會類似如下:

stages:
  - build
  - deploy
  - test

dev-build:
  stage: build
  only:
    - develop
  script:
    - echo "dev build"

dev-deploy:
  stage: deploy
  only:
    - develop
  script:
    - echo "dev deploy"

dev-test:
  stage: test
  only:
    - develop
  script:
    - echo "dev testing"

接著再用同樣的概念,設置 stg 的 Pipeline,於是整份 .gitlab-ci.yml 就會變成下面的模樣。

stages:
  - build
  - deploy
  - test

dev-build:
  stage: build
  only:
    - develop
  script:
    - echo "dev build"

dev-deploy:
  stage: deploy
  only:
    - develop
  script:
    - echo "dev deploy"

dev-test:
  stage: test
  only:
    - develop
  script:
    - echo "dev testing"

stg-build:
  stage: build
  only:
    - master
  script:
    - echo "stg build"

stg-deploy:
  stage: deploy
  only:
    - master
  script:
    - echo "stg deploy"

stg-test:
  stage: test
  only:
    - master
  script:
    - echo "stg testing"

是不是很簡單?只要一個檔案,就能產生兩條 CI/CD Pipeline。


(develop branch 的 CI Pipeline。)


(master branch 的 CI Pipeline。)

Job 可設置給多個 branch 使用

延續目前的案例,我們目前規劃的 Pipeline 只有三個 Stage、三個 Job,其實可以將 dev 與 stg 合併在一起,不用重複撰寫,只需要在 only: 中指定多個 branch 即可。

stages:
  - build
  - deploy
  - test

build:
  stage: build
  only:
    - develop
    - master
  script:
    - echo "build"

deploy:
  stage: deploy
  only:
    - develop
    - master
  script:
    - echo "deploy"

test:
  stage: test
  only:
    - develop
    - master
  script:
    - echo "testing"

等到針對不同 branch 需要執行不同 Job 時,在做出區分即可。例如下面的範例,有可能你在 build stage 需要針對 dev 與 stg 環境執行不同的 npm 指令。

build:
  stage: build
  only:
    - develop
  script:
    - npm install
    - npm run dev

build:
  stage: build
  only:
    - master
  script:
    - npm install
    - npm run producton

回到我們的案例。最後再加上 Production 的 Pipeline,整份 .gitlab-ci.yml 就變成下面的面貌。

stages:
  - build
  - deploy
  - test
  - prod-deploy

build-for-testing:
  stage: build
  only:
    - develop
    - master
  script:
    - echo "build for testing"

prod-build:
  stage: build
  only:
    - production
  script:
    - echo "build for production"
    
deploy-for-testing:
  stage: deploy
  only:
    - develop
    - master
    - production
  script:
    - echo "deploy for testing"

testing:
  stage: test
  only:
    - develop
    - master
    - production
  script:
    - echo "auto testing"

prod-deploy:
  stage: prod-deploy
  only:
    - production
  script:
    - echo "deploy to production server"
  when: manual

最後的 .gitlab-ci.yml 有再多做了一些調整。我們假設的情境是 dev、stg 兩種環境與 prod 環境要執行的 build 指令不同。另外就是 production branch 會需要先部署至 pre-production 環境,等到通過測試之後,才由主管在指定的時間手動觸發自動部署。

因此上面將 build 的 Job 分為 build-for-testingprod-build 兩種。同時第一個 deploy 改名為 deploy-for-testing,而部署至 Production 環境的 Job 則命名為 prod-deploy,並且增加了 when: manual 即是需要手動觸發。

不過實際將上面的 .gitlab-ci.yml 送進 GitLab 之後,卻發現 Pipeline 出現 stuck 的狀態。


(自以為規畫完美的 Pipeline,卻根本 stuck 卡住了,CI Job 沒有被執行。)

通常 Pipeline 會出現 stuck,主要的原因都是代表當下沒有吻合該 Pipeline 需求的 GitLab Runner。於是我們查看一下昨天架設好的 Runner,Runner 被標上的 tagshell。因此我們再次修改 .gitlab-ci.yml,為每一個 Job 加上如下範例的 tags:

build-for-testing:
  stage: build
  tags:
    - "shell"
  only:
    - develop
    - master
  script:
    - echo "build for testing"


(至 Group 的 Settings > CI/CD > Runners 去查看 Runner 的詳細資料,除了 Tags 之外,亦能查看 Runner 的其他資訊。)

本文最後版本的 .gitlab-ci.yml 在 master branch 會形成如下的 CI Pipeline。


(可以看見 Job 都如前述修改的,是 xxx-for-testing。)

而最後 Production branch 則會形成下圖的 CI Pipeline,其中最後一個 Prod-deploy 則需要有人按下「箭頭」才會執行動作。


(Production branch 的 CI Pipeline 也如規劃的一樣,有兩個不同的 deploy。)

小結

雖然只是模擬情境,尚未在 script: 中撰寫真實可用的動作,但在今天的進度中,我們已經成功練習建立了第一條 CI/CD Pipeline。透過這樣的練習,相信各位已經能體會,只透過一個 yml 檔就能建立 Pipeline 的方便之處。

但 CI/CD Pipeline 真的就這麼簡單嗎?其實一點也不簡單!今天的練習不過是個起步而已,我們還沒碰觸到 CI/CD Pipeline 真正讓人感到辛苦與頭痛的地方,CI/CD 到底難在哪裡?辛苦在哪裡?就讓我們在後續的文章逐一揭曉。(但有太多辛苦的環節了,大概 30 篇文章都不夠講,我們就先根據案例走到哪,揭曉到哪了~)