GitLab CI/CD 練習
前言
這是我 Android 實習的第一份作業,為了讓我的主管們知道我理解的程度,記錄一下學習的過程~
任務清單
- 1. 使用 Android Studio 創建一個 ”Hello World!” 專案
- 2. 試著在該專案寫一個 Unit Test (Java Test),並成功執行測試
- 3. 試著在該專案寫一個執行 androidTest,並成功執行測試
- 4. 在 GitLab 上新增該專案的 Repository
- 5. 嘗試在 Windows 或是 MacOS 或是 Linux 上架設 GitLabRunner (三擇一)
- 6. 再嘗試使用架設 GitLab Runner 在 Docker container 之中
- 7. 然後將架設好的 GitLab Runner 註冊至題目 4 的 GitLab Repository
- 8. 研究 yml 檔案如何撰寫及其中所代表的意義
CI / CD 簡介
一個軟體開發後,需要經過很多個測試,可能還需要維護,為了讓開發團隊以及維護團隊能夠更快、有效率的運作,產生出一個 DevOps (Development & Operations)的概念。它算是一個慣例,更準確來說是一種規範,而 CI/CD 就是其中的一個環節!
CI
Continuous Integration 持續整合,通常是讓程式能夠 build 以及 test
CD
Continuous Deploy / Development 持續部署,讓這些程式能夠依照我們想要的環境部署
Why
就以測試來講每寫一個 test code,就要跑一遍,這樣太沒效率了,如果可以把它自動化就會變得非常方便,所以 CI/CD 就顯得非常重要。
我們可以利用一些 lint
檢查 code 的語法或是風格使它們一致;也可以建立虛擬環境
讓它在產品階段部署,把這些產品的產線自動化後,後續的維護會節省很多的人力成本,而且也可以把每一個步驟拆分給更專業的人員,這就是它的精神!
以下會用 Gitlab
來實作簡單的 CI!
撰寫測試
Android 的測試分兩種:test、androidTest,與平常寫程式的地方 main
在同一層目錄
簡單寫一個 HelloWorld
的類別,以利後面進行測試
package com.cppdesign.helloworld
class HelloWorld(private val name: String) {
override fun toString(): String {
return "Hello, $name!"
}
}
這裡使用
Kotlin
,後續 test 都用Java
test
- test 包含
UnitTest
- 驗證邏輯與功能(Model 的 function 之類的)
- 在 local 的 JVM(Java Virtual Machine) 跑
需要 import
Junit
的類別,以及需要的Assert
functions
package com.cppdesign.helloworld;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class HelloWorldUnitTest {
private HelloWorld helloWorld;
@Test
public void toString_correct() {
helloWorld = new HelloWorld("Steven");
assertEquals("Hello, Steven!", helloWorld.toString());
}
// it must be fail because the sentence is missing one symbol (!)
@Test
public void toString_fail() {
helloWorld = new HelloWorld("Steven");
assertEquals("Hello, Steven", helloWorld.toString());
}
}
上述函式在進行測試時,會有一個成功、一個失敗(少一個
!
)
androidTest
- androidTest 包含
InstrumentedTest
- 會需要在模擬器或是實體裝置上運行
- 通常驗證整體行為與 Android 平台的互動
不確定要測試什麼,所以就學
ExampleInstrumentedTest.kt
package com.cppdesign.helloworld;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import android.content.Context;
import androidx.test.platform.app.InstrumentationRegistry;
public class HelloWorldInstrumentedTest {
Context appContext;
@Before
public void createInstrumentationRegistry() {
appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
}
@Test
public void useAppName() {
assertEquals("Hello World!", appContext.getApplicationInfo().loadLabel(appContext.getPackageManager()).toString());
}
@Test
public void useAppNameFail() {
assertEquals("Hello, World!", appContext.getApplicationInfo().loadLabel(appContext.getPackageManager()).toString());
}
}
利用
@Before
把會用到的的變數實體化。一樣會一成功、一失敗(多了!
)
Gitlab 介紹
因為自己都使用 Github
託管程式碼,第一次接觸到 Gitlab
發現很多地方很相似,所以記錄一些都會用到的功能以及名詞
名詞比較
Gitlab / Github
- project / repository
- ci / action
- group / organization
連接方式
它也跟 Github
一樣提供了 SSH
與 PAT
的功能,讓讀取更方便,可以不用打密碼登入帳號
SSH Key
從頭像點進去 Edit profile
(User settings
) > SSH Keys
Personal Access Token
這功能在 Github
裡是可以在 Android Studio
操作相關 repo
,但是我在 AS 裡找不到 Gitlab
的選項,所以只好寫起來放
跟 SSH Keys 同一層,要點
Access Tokens
Android Studio VCS
VCS(Version Control System) 是 AS 提供版本控制的系統,一開始要把 VCS 打開,但因為找不到 Gitlab
的選項,所以只能手動加入 remote
利用
token
連接 Project 可以不用打帳密登入紅色部分為 token
在
push
前,把 branch 名稱改成main
因為平權意識抬頭,現在 branch 提倡用 main/others 命名方式
上傳程式碼
這部分就是一系列的 git
操作,沒有什麼差別
Workflow
Gitlab flow 就與 Git flow 有差別了,想知道更多可以看這部影片
GitLab CI 實作
這次用 Gitlab 主要是使用它的 CI
功能,不像 Github Actions 有很多套件可以選擇,反而需要自己寫 workflow 還有建製 runner
名詞介紹
https://www.opengeosys.org/docs/devguide/testing/gitlab-ci/GitLab-Pipeline.png
Pipelines
上圖一整個畫面就是一個 pipeline
,在 Gitlab 中的 pipeline 與 CPU pipeline 相似,目的都是讓程式能夠更快的執行完畢,在這裡是為了讓我們的 CI 各方便快速。
Stages
最上面那一列的粗體黑字就是 stage
,代表這一個 pipeline 的各個階段,Gitlab 的官方文件有簡易的寫法,也可以自定義。
Jobs
stage 裡面每一個方框就是 job
,代表它的工作,實際上要做什麼事都在裡面定義
Runners
這些 jobs 需要架機器在上面跑,這時候就需要 runner
- 在 Gitlab 中分成這三種:
- shared runner
- group runner
- project runner
.gitlab-ci.yml
上述說到 Gitlab CI 非常的客製化,可以自定義 pipeline,而這些檔案就需要寫在 .gitlab-ci.yml
.
指在目錄中預設隱藏(不會顯示),與.gitignore
一樣gitlab-ci
是 Gitlab 的預設檔名,會自動加入 pipelineyml
是一種標籤語言(YAML Ain’t a Markup Language),常用來記錄設定檔(configuration)
這是官方文件的設定檔範例
|
|
一般來說會有以下 stages
:
- build
- test
- staging
- production
stages
標籤是記錄各種階段,對應到每個 job 裡面的stage
(line 2, 7, 12, 20)jobs
的名稱沒有硬性規定,就像變數命名一樣(line 1, 6, 11, 19)script
就跟shell script
很像,可以執行一些指令(line 3, 8, 13, 21)
官方文件還有很多關鍵字參考
Assigned Runner
寫完設定檔之後,再來就要架設 runner,規則大概如下:
新建 runner
在 project 裡面點進 Settings
> CI/CD
> Runners
> 點進 Expand
左右邊分成兩種 runner:
- project runner
- shared runner (credit card validate)
第二種 shared runner 是官方提供的 runner,但是需要信用卡認證(不用錢),但自己還是有疑慮就沒試了
點進 project runners > new project runner
填寫 Operating System
、Tags
、Details
,就可以 Create runner
了
在
Tags
下有一個 checkbox 建議勾選(當初沒勾選卡了很久)
安裝 gitlab-runner
在註冊 runner 前,需要在自己的機器上建立環境,分成兩種:
- local runner (很麻煩)
- docker (推薦用這個)
安裝記錄就不寫了,放幾個當時遇到問題的圖片以及 references:
主要是權限環境問題,所以很推薦直接用 docker 建立虛擬環境,會它的基本指令直接照文件下就好了
註冊 runner
建立完 runner 後再來就是 register
,這步驟就像是你的 repo 與你電腦裡的 runner 連接
紅色部分為 token,每個 runner 的 token 都是唯一的
接著照著下指令寫 runner 的設定檔(config.toml
):
- INSTANCE URL (你的 repo 的前綴網址)
詳情看這裡
- token
- name (Description)
- executor
它有很多種可以選,如果 runner 架在 local,想直接跑
.gitlab-ci.yml
選擇shell
就好;用 docker 架設的話就選docker
這個設定檔預設放在 /etc/gitlab-runner
因為每建一個 runner 都要再設定一次 config,也不可能改 config 位置,所以用 docker 建 runner 真的很方便
執行 runner
再來就是 run runner 了
local 端就下
$ gitlab-runner run
docker 就用
image
建立實例$ docker run --rm -it -v /srv/gitlab-runner/config:/etc/gitlab-runner gitlab/gitlab-runner register
結果
到 Project 裡的 Build
> Pipelines
,可以看到這個 pipeline 的運行結果
如果看到左邊的 Status 一直在
pending
可能是你的 runner 沒打開
心得
Gitlab CI 的自由度好高,感覺可以把很多後續維護的步驟全部自動化。而且後來研究過程中才發現我用過 Github Actions
它也是 CI 的一種,我這個部落格的架設就是利用它!
因為我的 code 沒有太龐大,所以沒有寫到 auto test,只有簡單的 echo,希望之後可以學到更多~
相關連結
參考
- Build local unit tests
- Build instrumented tests
- Continuous Integration with GitLab (overview demo)
- GitLab Runner
- Install GitLab Runner
- 架設 GitLab CI Runner
- What Is GitLab Workflow | GitLab Flow | GitLab Tutorial For Beginners | Part III
- 別怕!.gitlab-ci.yml 勇敢寫下去!
- .gitlab-ci.yml keyword reference
- Gitlab CI/CD 介紹與 Runner 的架設
- CI/CD pipelines
- https://linyencheng.github.io/2022/05/30/devops-gitlab-ci-and-gitlab-runner/
- Tutorial: Create and run your first GitLab CI/CD pipeline
- Gitlab instance URL
- Android GitLab CI + Docker 工程实践
- Change Gitlab CI Runner user
- Pipelines jobs without tag
- Registering runners Docker part
- Run GitLab Runner in a container