別怕!.gitlab-ci.yml 勇敢寫下去!
身為一個研發人,我有著閱讀官方文件的習慣,但當我打開了 GitLab CI/CD 的官方文件後…
好的,資訊量爆炸!!!
我始終堅信著,每個研發人都應該要有的信念:
科技應要讓使用者專注在心中想解決的問題,而不是在處理使用該科技所碰到的問題。
by Arren Ping
同樣地,我對 GitLab CI/CD 的期望亦是如此。不過,本來也清楚 CI/CD 不是件簡單的事情,文件數量多,反而是好事,不怕碰到困難解不了。
我這麼說服自己,研發人的心臟很強健,不屈不撓,勇敢向前,沒在怕的!
多看了幾份文件後,我理解到,GitLab CI/CD 是透過設定在專案根目錄底下的 .gitlab-ci.yml 這個檔案來驅動,而在經歷了多次的改版,已經有了很多方便使用的措施,其中一個就是 範本,對初學者來說真的是大大大大大……幫助!
找不到的捧油請在專案首頁尋找一個叫做 “Set up CI/CD” 的功能,勇敢地按下去,就會出現可以編輯 .gitlab-ci.yml 的界面,裡頭就有範本可以選。
我所需要的 maven 的範本自然也被包括在內,如下:
# This file is a template, and might need editing before it works on your project.
# Build JAVA applications using Apache Maven (http://maven.apache.org)
# For docker image tags see https://hub.docker.com/_/maven/
#
# For general lifecycle information see https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html
# This template will build and test your projects
# * Caches downloaded dependencies and plugins between invocation.
# * Verify but don't deploy merge requests.
# * Deploy built artifacts from master branch only.
variables:
# This will suppress any download for dependencies and plugins or upload messages which would clutter the console log.
# `showDateTime` will show the passed time in milliseconds. You need to specify `--batch-mode` to make this work.
MAVEN_OPTS: "-Dhttps.protocols=TLSv1.2 -Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=WARN -Dorg.slf4j.simpleLogger.showDateTime=true -Djava.awt.headless=true"
# As of Maven 3.3.0 instead of this you may define these options in `.mvn/maven.config` so the same config is used
# when running from the command line.
# `installAtEnd` and `deployAtEnd` are only effective with recent version of the corresponding plugins.
MAVEN_CLI_OPTS: "--batch-mode --errors --fail-at-end --show-version -DinstallAtEnd=true -DdeployAtEnd=true"
# This template uses jdk8 for verifying and deploying images
image: maven:3.3.9-jdk-8
# Cache downloaded dependencies and plugins between builds.
# To keep cache across branches add 'key: "$CI_JOB_NAME"'
cache:
paths:
- .m2/repository
# For merge requests do not `deploy` but only run `verify`.
# See https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html
.verify: &verify
stage: test
script:
- 'mvn $MAVEN_CLI_OPTS verify'
except:
- master
# Verify merge requests using JDK8
verify:jdk8:
<<: *verify
# To deploy packages from CI, create a ci_settings.xml file
# For deploying packages to GitLab's Maven Repository: See https://docs.gitlab.com/ee/user/project/packages/maven_repository.html#creating-maven-packages-with-gitlab-cicd for more details.
# Please note: The GitLab Maven Repository is currently only available in GitLab Premium / Ultimate.
# For `master` branch run `mvn deploy` automatically.
deploy:jdk8:
stage: deploy
script:
- if [ ! -f ci_settings.xml ];
then echo "CI settings missing\! If deploying to GitLab Maven Repository, please see https://docs.gitlab.com/ee/user/project/packages/maven_repository.html#creating-maven-packages-with-gitlab-cicd for instructions.";
fi
- 'mvn $MAVEN_CLI_OPTS deploy -s ci_settings.xml'
only:
- master我想,或許不少人跟我一樣看到範本後呈現呆滯狀(汗~
碰到困難就想辦法解決
面對這種狀況,我的做法是:
不要心生恐懼
思考自己期望達成的效果
勇敢再看一次
身為一個 CI/CD 的初心者,我想要的效果其實很簡單,在每次 merge 之後只要有人能幫我打包好,讓我能方便的下載包好的結果就好了!
這個幫忙打包的人,我希望是 GitLab CI/CD。(其實不要是我就可以,是誰做我都 OK!溜~
CI 就是持續地整合,打包就是其中一個過程;CD 就是持續地部署,打包的結果被放置到特定的位置,就是部署的一種形式。
先講個題外話,原本在我的想像裡,我以為 GitLab CI/CD 會嚴謹的定義 CI 與 CD 的每個步驟,以及在每個步驟中可以做的事情,最好是提供了種種的外掛可以讓使用者開心地挑選、使用,然後 Just Work!!!在我充分瞭解之後,以上純屬想像,不是 GitLab 的做法。
GitLab 提供的方案一樣是 Just Work,但有哪些步驟及步驟中該做哪些事情的決定權,完全交給了 Developer 本人,給了開發者最大的彈性可自由揮灑,擁有無限多種可能!是的,只要寫好自己想要的 .gitlab-ci.yml 就可以!
發揮研發人的想像力
回過頭來看範本的結構,可以發現 .gitlab-ci.yml 中有縮排,有些詞帶有 : 結尾,我們先從第一級(無縮排)的這些詞開始看:
variables
image
cache
.verify
verify:jdk8
deploy:jdk8
發揮想像力的時間到了,來猜猜這些詞的用途或目的是什麼:
variables => 應該是宣告變數吧
image => 感覺在 GitLab 這種純 command line 的執行環境裡一定不是影像,應該是指映像檔
cache => 快取,跑不掉了
.verify => 唔… 前面有個點,是什麼鬼,跳過
(逃~verify:jdk8 => 驗證 JDK 8??
deploy:jdk8 => 部署 JDK 8??
接著,我們依照前面的做法補上第二級:
variables => 應該是宣告變數吧
MAVEN_OPTS:
MAVEN_CLI_OPTS:
image => 感覺在 GitLab 這種純 command line 的執行環境裡一定不是影像,應該是指映像檔
cache => 快取,跑不掉了
paths
.verify => 唔… 前面有個點,是什麼鬼,跳過
(逃~stage
script
except
verify:jdk8 => 驗證 JDK 8??
<<
deploy:jdk8 => 部署 JDK 8??
stage
script
only
好的,一樣,有 耐心 地發揮想像力,但請將第一級的推測也加入一起考慮,來理解第二級可能的意思:
variables => 應該是宣告變數吧
MAVEN_OPTS => 這個名稱和 maven 定義的環境變數相同,應該就是給 maven 使用的設定值
MAVEN_CLI_OPTS => 有個 CLI 感覺像是執行時期使用的
image => 感覺在 GitLab 這種純 command line 的執行環境裡一定不是影像,應該是指映像檔
cache => 快取,跑不掉了
paths => 路徑,應該是快取資料的來源位置,或者是要把快取資料存放的位置
.verify => 唔… 前面有個點,是什麼鬼,跳過
(逃~stage => 絕對不是舞台
(溜~,應該是階段吧!script => 要執行的 script
except => 要排除什麼東西??
verify:jdk8 => 驗證 JDK 8??
<< => 迷樣符號,跳過
(逃~
deploy:jdk8 => 部署 JDK 8??
stage => 第二次出現,應該是階段!
script => 要執行的 script
only => 只能有什麼東西??
當這些推測都做完了之後,我們可以開始看解釋 .gitlab-ci.yml 的官方文件了,請參考這份 GitLab CI/CD Pipeline Configuration Reference。
有些人喜歡從上到下閱讀整份文件,而我的習慣是,部分理解後若有必要再補全整體知識,所以,我先從關鍵字下手!
確立正確的知識
關鍵字理解了之後,再重新更新一次:
variables => 宣告變數
MAVEN_OPTS => 給 maven 環境使用的設定值
MAVEN_CLI_OPTS => 使用者定義的變數,在 script 期間可以選擇代入使用
image => 指定要使用的 docker 映像檔,映像檔可以在 Dock Hub 上找
cache => 設定要使用快取
paths => 快取的路徑,要被快取的資料來源路徑
.verify => 自訂的 anchors,在執行時期時,會將引用此 anchors 的位置替換為 anchors 宣告的內容
stage => 執行階段
script => 要執行的 script
except => 在哪些情況下不執行
verify:jdk8 => 不是保留字,是個使用者自訂的 job。配合註解來看,應該是想要採用 jdk8 執行 maven 的驗證工作
<< => 引用 anchors
deploy:jdk8 => 不是保留字,是個使用者自訂的 job。配合註解來看,應該是想要採用 jdk8 執行 maven 的驗證工作
stage => 執行階段
script => 要執行的 script
only => 只在哪些情況下執行
至此,整個輪廓變得清晰了許多,要特別提醒 務必理解 幾個我覺得最重要的問題:
stage 是什麼?
stage 是怎麼定義的?
job 是做什麼用的?
為什麼需要 cache?
stage 是什麼?
stage 是工作階段
一個 stage 中可以包含多個 job,job 的執行不保證順序
stage 之間是有順序相依的,必須確保前一個 stage 完成後,才會執行下一個 stage
一般情況下 stage 中的 job 都必須正確無誤完成後,才能執行下一個 stage
stage 是怎麼定義的?
在使用者沒有定義的情況下,預設提供三個 stage => build、test 和 deploy
使用者可以透過
stages定義自己想要的階段及順序
stages:
- build
- test
- deployjob 是做什麼用的?
job 定義了要完成的工作
GitLab CI/CD 會安排 Runner 也就是派遣工來承接 job,依照 job 中的定義來執行工作
GitLab CI/CD 的派遣工有個缺點 => 有失憶症,就算來幫忙執行 job 的是同一人,他也完全不記得之前做過些什麼
就算是被歸類為同一個 stage 的 job,也不保證誰先執行、誰後執行,彼此之間也互不認識
為什麼需要 cache?
其實沒有 cache 也可以,有了或許可以加速 job 的執行速度
有些工作需要一些資源才能執行,例如:相依的函式庫,但因為派遣工每次都會失憶症發作,在沒有設定 cache 的情況下,就會重新獲取所有需要的資源,這樣很慢且很貴(Runner 若非開放原始碼專案是有總執行時間上限的),設定了 cache 後,就可以避免這個問題,而是直接從 cache 中取得
回歸需求,大膽執行!
現階段我的需求是 => 在每次 merge 之後只要有人能幫我打包好,讓我能方便的下載包好的結果。
換言之,
不需要測試
因為我已經人工本地測完了
沒有特殊的部署
沒有要發佈到 production 環境的需求
也沒有要版本庫
只要能有個地方下載檔案就好
別忘了,是用 maven + JDK 11
基於以上,第一版 .gitlab-ci.yml 如下:
# 請上 Docker Hub 找適合自己的
image: maven:3.6.3-jdk-11
stages:
- build
# 完全引用 template 中的設定
variables:
MAVEN_OPTS: "-Dhttps.protocols=TLSv1.2 -Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=WARN -Dorg.slf4j.simpleLogger.showDateTime=true -Djava.awt.headless=true"
MAVEN_CLI_OPTS: "--batch-mode --errors --fail-at-end --show-version -DinstallAtEnd=true -DdeployAtEnd=true"
build:
stage: build
only:
- master
script:
- mvn $MAVEN_CLI_OPTS package
# 產生出的成果會被保留供下載
artifacts:
# GitLab 提供的環境變數,意思是產生出的成果下載時的檔名將會是專案名稱
name: "$CI_PROJECT_TITLE"
# 要保留哪些成果的路徑
paths:
- target/*.jar做到這只差最後一步 => 請勇敢的將 .gitlab-ci.yml commit & push!
真的完全不需要擔心,GitLab CI/CD 會先驗證檔案的正確性,且 Runner 並不會因為這樣就壞掉。
頂多只是 job 有誤,流程沒有成功跑完而已。
所以,
恭喜跨出了 GitLab CI/CD 的第一步,請愉悅地享受 CI/CD 的效果及成就感吧!