關於我想看漫畫卻不想看廣告這檔事 (17) —使用 github actions 自動測試程式碼

Seaweed
10 min readNov 23, 2021

--

上 CI 的好處:

看到一片綠很爽(◯)

本篇程式碼

Github Actions 執行流程

實際撰寫程式之前先來了解 github actions 的基本結構:

PS. github actions 的檔案一定要放在主分支的.github/workflow/ 底下,否則讀不到。

首先在 on 內部指定 workflow 的發動條件(可以是某個 git 事件、cron 定時事件甚至是手動觸發),之後於 jobs 內部撰寫實際的 CI 內容。

jobs 內部由一個或多個執行流程(比如這裡的 run-workflow 就是一個執行流程)構成,每個執行流程都會先在第一行設定環境(主要是名稱、作業系統的指定),接著使用 step 定義實際要執行的指令。另外不同執行流程之間也能定義相互的相依性,這次雖然不會特別介紹,不過當作參考記住也好。

其他的詳細寫法我們後續介紹,目前只需知道,一個 workflow 是透過 on 中的定義被觸發,接著執行 jobs 內的指令來完成一次 CI。

可用 trigger

on 作為定義如何觸發 workflow 的部分,主要有三種類別,這邊一一介紹:

依據 git 事件

on:
push:
branches:
- master

這部分應該是最好理解的,比如上面的寫法就是「當 master 被 push 時發動」。

定時執行

這其實就跟 crontab 的寫法相同,熟悉 crontab 的朋友可能會很熟悉:

on:
schedule:
- cron: '5 0-8/2 * * MON-FRI'

比如上面就是「UTC 時間的一至週五每天 0:05~8:05 每兩小時發動一次」。

手動觸發(API 觸發執行)

這裡就比較特殊,這基本上是需要「主動發動 CI」時才寫的規則:

on:
workflow_dispatch:

最基本寫法就長這樣。加上之後就可以在 github 網頁或者透過http API 發動這個 workflow:

github 網頁上看起來會像這樣(在對應專案的 Actions 那個分頁):

HTTP API 的發動方法長這樣:

其中 TOKEN 為個人使用者的 OAuth token(從 github 個人頁面/Settings/Developer settings/Personal access token 取得),之前的資料顯少有提及,但現在是必須$USER 是專案持有者的帳號名(也可以是組織名), REPO 為專案名, PAYLOAD 則是給 workflow 指定參數時的 json 參數。

workflow_dispatch 增加輸入參數:

當然,workflow_dispatch(手動觸發)的 trigger 同樣可以給參數,定義與取得參數的寫法如下:

L3~L9定義的部分其實也很好理解,比較關鍵的部分是 L19~L23 取得輸入參數的部分。

取得方法有直接取得(L20),以及透過 GITHUB_EVENT_PATH 事件結構取得(L23)兩種。前者較直觀,但因為輸入的參數無法被定義於 Secrets 中,其內容會直接被顯示在 Log 當中。而後者雖然稍微複雜(需做一些 json 處理),但因為不會在 log 中留下紀錄,因此傳輸敏感資料時建議採用這種寫法。

關於 trigger 的定義大概就這些,想知道更多詳細資料的可以看這邊:

Jobs 內部寫法介紹

該做的 trigger 設定都寫好之後接著就可以來寫 CI 的本體了。我們將針對是 jobs: 關鍵字的內容做說明,雖然前面同樣有提過,不過這裡詳細解說。

workflow

首先 jobs 內部由一個或多個 workflow 構成,每個 workflow 都會自己帶有一些環境設定(name: workflow 名, runs-on: 作業系統 … 等)以及需要執行的步驟(steps)。另外,不同 workflow (同一個 jobs 內)之間可以設定相依性來指定執行順序。

workflow 環境設定

如前述,每個 workflow 都會有自己的環境設定,內容大致可以包含:

  • 指定作業系統(runs-on)
  • 設定環境變數(env)
  • 指定相依性(needs)
  • 指定 workflow 名(name,本藻不知道這有什麼用)

不過常用的也只有最基本的指定作業系統(runs-on)以及指定 workflow 名(name)。其他的要用的時候 Google 一下就好。

不過這邊特別題一下,多平台/環境的驗證一般比較常用 strategy/matrix,這東西因為可以結合不少東西就留待各位自己慢慢玩了,相關資料可以看看以下:

steps

接著就是 workflow 內部實際撰寫 script 的部份了。基本結構長的像下面:

熟悉 docker 的可能很熟悉,實際上 steps 的結構的確類似 docker 內的 layer。在這裡用了五種寫法,不過實際上只能分為兩種。

前兩個是拉外部別人寫好的 layer 來用(uses),後三個則是自己寫 shell script(run)。最後一個是多行 script 放在一個 run裡的寫法,挺好用的建議記住。另外,這裡需要特別記住:runuse 沒辦法在同一個 layer 使用。

最後,我們同樣可以給 runuses 設定名字(name)之後看 log 比較好看(雖然本藻覺得不好說)。

uses 補充說明

關於第三方的 uses (這裡應該叫 actions),github 本身有提供集中管理的市集:

基本上要什麼功能在這裡都能找到,正常來說只要照對方的 README.md 寫就不會出什麼大問題(有問題就可以貢獻惹)。

比如設定 Golang 環境的 Setup Go enviroment 就長得像下面:

甚至看不懂英文都能用,本藻覺得很棒。

範例程式

執行自動測試的 CI 之前,我們得先寫個測試程式碼

本藻知道你想說什麼,但我們也不能一直勞煩史萊姆,對吧

一個簡單的測試,直接用 python crawler_test.py 就能執行了。

接著我們來看 github actions 的部份

雖然這邊我們實際上是在 github actions 裡面再起一個 docker container 然後在裡面執行測試,不過光看應該就懂了,畢竟都是很熟悉的東西。就兩個部份需要特別說明:

${{ secrets.XXXX }}

從外面帶入的參數,每個專案都可以獨立設定一組(免費的忘記幾個) secret 變數,然後在 CI 執行時代入進來。實際的使用場景就像這裡的 ssh 連線,需要把登入用的 host/port/username/key 帶入時使用。

至於 secrets 的設定方法可以參考這邊:

Build image 的 with 裡的 context 是啥?

這是因為預設的 docker build 會在 . build image,然而我們要用的 dockerfile 卻是放在 section_17 裡面。因此這裡的 context 可以當成 cd 的意思。為避免說太多離題,這裡放上官方文件:

local 端測試

接著,一定會有人認為 CI 這東西都只能在雲端執行,那開發時的測試不就超級麻煩?

對!超級麻煩!

本藻也這麼認為,所以有人針對 github actions 寫了一套可以在 local 執行的 github actions 執行指令(不過目前只支援一部分功能)。

安裝完畢後,執行方法如下(比如要執行本單元的 github actions)

act -j test-crawler -s PEM="$(cat proxy.pem)" --secret-file section_17/.secrets

secret 參數可以透過 -s 單獨設定或者 --secret-file 直接以檔案指定。其中檔案寫法也很簡單:

PROXY_HOST="example.com"
PROXY_PORT="22"
PROXY_USER="user"

真心好用,一定要推薦給親朋好友使用。

結語

這次我們介紹了 github actions 這個好用的 CI 工具,難度上比起之前的 Terraform 應該是簡單許多。下一篇就是本系列的最終章,我們將把 Terraform / Serverless framework 與測試都整合進 github actions 裡,完成我們的 CI/CD 流程。若還有興趣,還請各位再陪本藻走一段路,那麼最後一篇再見。

下篇預告

Github actions + Terraform + Serverless framwork = 大團圓

下篇傳送門

--

--

Seaweed

最大的才能是行光合作用,朋友是矽藻的海藻。