本篇程式碼
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
裡的寫法,挺好用的建議記住。另外,這裡需要特別記住:run
與 use
沒辦法在同一個 layer 使用。
最後,我們同樣可以給 run
與 uses
設定名字(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 = 大團圓