如何使用 Gitlab 搭配 Gitlab CI/CD 進行自動化測試

如何對在 Gitlab 上面的專案進行 CI/CD 可以怎麼做呢? Gitlab 可以搭配 Gitlab CI/CD 來執行 CI/CD , Gitlab CI/CD 會依照所設定的設定檔將指令交由 Gitlab Runner 來執行進而完成整個 Pipeline ,在 Gitlab CI 的世界有幾個名詞。

  • Pipeline: 一個 CI/CD 的流程,串接多個 Job 與多個 Stage 組成,任何一個 Job 失敗都視為這個 Pipeline 失敗(除非該 Job 有設定為 allow fail )。
  • Stage: 階段,一個 Stage 可以由多個 Job 組成,同個 Stage 中的 Job 都必須通過才會執行下個 Stage 。
  • Job: 工作,依照 .gitlab-ci.yaml 所設定之設定交由 Gitlab Runner 來執行,並且提交這個 Job 的執行狀態(綠燈、橘燈、紅燈)。

在 repository 根目錄直接新增 .gitlab-ci.yaml 檔案,這邊有個範例給大家參考。

stages: // 定義這個 Pipeline 有的 Stage
  - build // Stage 名稱
  - test

Build: // Job 名稱
  stage: build // stage name 需要與上方的 stages 名稱一致
  image: composer // 這個 Job 需要使用的 docker image ,以範例來說使用的是 compose:latest
  cache:
    key: "$CI_COMMIT_REF_SLUG"
    paths:
      - vendor/
  script: // 需要執行的指令
    - composer install --ignore-platform-reqs
  artifacts: // 透過 artifacts 將 vendor 這個資料夾 pass 給下個 Stage 的 Job 使用
    expire_in: '10 mins'
    paths:
      - vendor/

Test:
  stage: test
  image: php:7.4-cli
  script:
    - ./vendor/bin/phpunit // 執行 PHPUnit 測試

通常在 Continuous Integration(CI) 階段我們會設計一些流程來進行專案的驗證,目的在於透過自動化導入檢測並且減少人為介入進而提升專案穩定度。

  • 專案安裝
  • 專案檢測(靜態程式碼分析、 coding style 檢查、 docker image best practice 檢測 …)
  • 專案測試
    • 單元測試 Unit Test
    • 整合測試 Acceptance Test
    • End-to-End Testing
  • 專案打包(在容器化世代通常會需要打包 docker image 供其他容器管理器進行使用)

當然在 CI 階段可以做的事情不只這些,就看專案的特性來進行調整即可,撰寫 .gitlab-ci.yaml 完成後執行 git push 推送到專案上就會生效了,即可在 Gitlab > Repo > CI/CD > Pipelines 看到執行結果。

https://gitlab.com/coosos810609/phpunit-demo-with-ci/pipelines/134780795

每個 Stage 中各自 Job 的執行狀態也可以直接點擊查看,畫面中可以看到會將設定在 .gitlab-ci.yaml 中的指令一一執行,並且將執行結果呈現在畫面中。

https://gitlab.com/coosos810609/phpunit-demo-with-ci/-/jobs/506685408

如果執行的過程中有任何的錯誤都可以透過這邊進行 Debug ,下篇再與大家分享如何優化所撰寫的 .gitlab-ci.yaml 檔案。

如何透過 Docker 來使用 Fluentd

首先先介紹一下 Fluentd 怎麼念,這個詞從我進 KKBOX 以來到現在一直都不知道怎麼念,但同事都是念「 Fluent and d 」所以我也跟著這樣念了,今天好奇查了一下真正的念法是「 Fluent dee 」或是可以唸成「 Fluent d 」,詳細可以參考這篇文章

Fluentd 是一套開源軟體的資料蒐集器,時常備用在蒐集各式各樣的 Log 然後整理拋送到另外一個地方,講這樣很玄可以參考下面這張圖。

可以看到 Fluentd 會蒐集各式各樣的 Log 像是 Apache 的 access log 、應用程式的 log 或是系統記錄等等,經過 Fluentd 的 filter 整理後轉送給各式各樣的 Output , Fluentd 支援太多的 Output 了,詳細可以直接到這個網站上面直接查詢,真的是想的到的服務都有。

在 Docker 非常盛行的時代想要實做一個服務你不用自己架設,起一個 Docker 就可以了,下面會跟說明要如何進行測試,我將這次測試的原始碼放在這邊,有興趣可以直接 clone 下來玩玩。

首先需要先撰寫一個 fluent.conf 的設定檔讓 fluentd 執行使用,如下可以看到我有兩個來源分別是 apache-access.log 與 lumen.log 為了測試方便每次執行都會從頭開始讀取到結束,在輸出的部分我使用 file 來儲存並且透過 tag 與時間來區分我的 log 檔案。

<source>
  @type tail
  path /pod-data/apache-access.log
  pos_file /pod-data/apache-access.log.pos
  read_from_head true
  tag apache.access
  <parse>
    @type apache2
  </parse>
</source>

<source>
  @type tail
  path /pod-data/lumen.log
  pos_file /pod-data/lumen.log.pos
  read_from_head true
  tag lumen
  <parse>
    @type json
  </parse>
</source>

<match **>
  @type file
  path /fluentd/log/${tag}/${tag}.%Y%m%d
  <buffer tag,time>
    @type file
    flush_thread_count 8
    flush_at_shutdown true
    timekey_use_utc true
    timekey_wait 1m
    path /fluentd/log/buffer
  </buffer>
</match>

接著就是來使用 Docker 搭配我的設定檔來執行我的 Fluentd 測試。

> git clone https://github.com/hashman/docker-learning.git
> cd docker-learning/fluentd-demo
> docker run --rm --name fluentd -v ${PWD}/fluent.conf:/fluentd/etc/fluent.conf -v ${PWD}/dest_logs:/fluentd/log -v ${PWD}/src_logs:/pod-data fluent/fluentd:v1.10.1-debian-arm64-1.0

因為我是用 Raspberry Pi 來跑,所以我需要使用 arm base 的 docker image 來執行,如是 x86 / x64 的可以直接用 fluent/fluentd:v1.10.1-debian 這個 image tag 來使用就可以了,執行完成最終的 output 資料夾結構會長成這樣的分類。

├── dest_logs
│   ├── apache.access
│   │   └── apache.access.20200405_0.log
│   ├── buffer
│   │   ├── buffer.b5a2b33a4f6b37cbdd626aadd8b4d121f.log
│   │   └── buffer.b5a2b33a4f6b37cbdd626aadd8b4d121f.log.meta
│   └── lumen
│       └── lumen.20200405_0.log

相關的原始碼我有放在 Github 上面,有興趣可以抓下來玩玩,有任何問題歡迎留言或是 Github Issue 發問。