Gitlab的CI工具比較好用霎褐,通常我們會把代碼的push或者Tag標簽的生成作為觸發(fā)事件,啟動代碼的編譯亚亲、測試和部署救拉,這些都離不開Build tool的參與难审,而Gitlab-runner可以使用多種類型的Runner,或者將Build tools安裝在本機亿絮,直接在Shell里邊執(zhí)行告喊,或者采用Docker/Kubernetes類似的容器技術(shù)拂铡,配合Build tools的鏡像執(zhí)行編譯操作,前者的問題在于每臺機器都要進行編譯工具的安裝配置葱绒,擴容相對繁瑣,每增加一個Runner都要自己在新的機器上進行一批操作斗锭,后者的好處顯而易見只要是啟動了Docker daemon的機器地淀,都可以自動的pull對應的Build tool image來進行編譯,減少了很多重復操作岖是。
在Docker鏡像里邊使用Sbt等編譯工具需要考慮到每次編譯所下載的依賴緩存到哪里帮毁,默認情況會放到對應的鏡像運行時所對應的Container里邊的目錄,一旦鏡像升級或者運行時的container被刪除豺撑,所有的緩存的依賴在下次編譯的時候都要重新下載烈疚,雖然可以通過Volumn掛載的方式將緩存產(chǎn)生在宿主機的某些目錄,不過用這種方案依然避免不了在每個宿主機器上進行額外的緩存目錄的配置聪轿,本文主要以SBT/Maven為例爷肝,說明如何在Gitlab CI工具中使用Docker類型的Runner來進行代碼的編譯,并且依賴GItlab CI的Cache功能來緩存編譯時下載的各種依賴陆错,加速重復編譯的速度灯抛。
關(guān)于如何構(gòu)建SBT/Maven的鏡像就不多說了,Docker hub上邊有很多成熟的例子音瓷,基于Alpine Linux構(gòu)造出來盡可能小的鏡像即可对嚼。如何讓每次Sbt鏡像進行編譯的時候能夠重復的使用緩存,不需要重新下載依賴才是關(guān)鍵绳慎。
- SBT目錄結(jié)構(gòu)
ls ~/.sbt
0.13 1.0 boot gpg launchers preloaded repositories .credentials
ls .sbt/1.0
build.sbt plugins server staging target templates zinc
其中0.13和1.0對應不同大版本號的sbt.global.base目錄纵竖,因為二者差別較大,boot對應sbt.boot.directory杏愤,repositories和.credentials是我們自己定義的倉庫列表和所授權(quán)的用戶名密碼靡砌。
sbt.global.base目錄里邊的內(nèi)容不是那么純粹,build.sbt以及plugins目錄里邊的*.sbt文件是我們預先配置好的插件和授權(quán)驗證等信息声邦,也包含了一些插件在update過程中所下載的依賴乏奥,因此這個目錄的緩存是比較麻煩的,只能緩存其中一部分
- SBT緩存哪些數(shù)據(jù)
- sbt 啟動自身需要的依賴和插件等數(shù)據(jù)亥曹,比如我們每次修改buid.properties換一個更新的sbt版本號時可能就會觸發(fā)的get sbt xxx version的提示
- ivy cache and local邓了,這部分是我們所編譯的工程的依賴,默認路徑是
$HOME/.ivy2/{cache, local}
- coursier cache, 如果我們使用了coursier來并行的解決依賴媳瞪,也需要緩存這個插件的數(shù)據(jù)骗炉,默認位置是
$HOME/.coursier/cache
- SBT項目.gitlab-ci.yml
image: "xxxxx/sbt:1.1.0-alpine"
variables:
SBT_OPTS: "-Dsbt.global.base=/{absolute path}/sbt-cache/base -Dsbt.boot.directory=sbt-cache/boot -Dsbt.ivy.home=sbt-cache/ivy -Xmx3096m -Dsbt.override.build.repos=true -Dsbt.repository.config=/root/.sbt/repositories" # 修改默認的路徑,統(tǒng)一將sbt需要的東西都保存到某個sbt-cache目錄蛇受,這個目錄在下邊的gitlab cache部分會定義
# 注意sbt.global.base的路徑只能是絕對路徑句葵,我們只能寫具體的gitlab runner里邊的build路徑
# 注意sbt.repository.config后邊的路徑也必須是絕對路徑,如果用環(huán)境變量$HOME或者~替代,則會出現(xiàn)無法使用正確的倉庫的問題
COURSIER_CACHE: sbt-cache/coursier # 當使用Coursier時需要這一行乍丈,定義Coursier Cache
SBT_CREDENTIALS: "/root/.sbt/.credentials" # 此處也是必須使用絕對路徑剂碴,用$HOME環(huán)境變量無法找到正確的文件路徑,這個環(huán)境變量主要在upgrade sbt的時候使用轻专,如果不指定是無法使用私服去更新sbt的忆矛,此時沒有開始加載basedir/credentials.sbt 這個文件,因此會報授權(quán)錯誤
cache:
#key: "$CI_BUILD_REF_NAME" # 每個分支一個緩存请垛,還有其他的常量定義Tag等緩存的區(qū)分催训,默認是整個工程所有的Job都使用同一個緩存
# 對于編譯工具來說,不需要每個分支額外緩存一份宗收,注釋掉這行即可
untracked: true
paths: #以下出現(xiàn)的路徑都會在編譯的時候由gitlab ci的runner負責創(chuàng)建和管理漫拭,只要相對路徑即可,對應上邊環(huán)境變量里邊所設(shè)置的路徑
- "sbt-cache/ivy/cache"
- "sbt-cache/ivy/local"
- "sbt-cache/boot"
- "sbt-cache/base"
- "sbt-cache/coursier" #only needed if you use coursier
before_script:
- which sbt
- mkdir -p sbt-cache/base/plugins
# 接下來比較奇怪混稽,因為sbt的這兩個路徑里邊不只有緩存的東西采驻,還有一些我們預先配置好的腳本,比如plugin.sbt, build.sbt等匈勋,
# 一般這些內(nèi)容我們會直接打包到鏡像里邊挑宠,而緩存只有在第一次運行之后才會創(chuàng)建,如果不拷貝過去颓影,因為上邊的SBT_OPTS里邊定義的路徑都是緩存里邊的路徑各淀,
# 會導致我們配置的repositories和credentials不生效,如果不用上邊的環(huán)境變量來修改诡挂,會導致有些內(nèi)容不會被緩存碎浇,每次都會get sbt到臨時的docker container中,重復下載
- cp ~/.sbt/0.13/build.sbt sbt-cache/base/ # 根據(jù)情況0.13要改成1.0
- cp ~/.sbt/0.13/plugins/*.sbt sbt-cache/base/plugins/ # 同上
stages:
- build
- deploy
compile:
stage: build
script:
- sbt compile
allow_failure: true
tags:
- sbt
最終在執(zhí)行完成后我們可以看到如下日志:
......
HEAD is now at ddb6c5c modified: .gitlab-ci.yml
Checking out ddb6c5c4 as docker_env...
Skipping Git submodules setup
Checking cache for default...
Successfully extracted cache
......
Creating cache default...
sbt-cache/ivy/cache: found 528 matching files
WARNING: sbt-cache/ivy/local: no matching files
sbt-cache/boot: found 66 matching files
sbt-cache/base: found 174 matching files
sbt-cache/coursier: found 9544 matching files
untracked: found 17215 files
Created cache
Job succeeded
能夠看到緩存在各個目錄的文件的情況
- Maven目錄結(jié)構(gòu)
Maven相對來說要簡單很多璃俗,我們只要緩存.m2/repository就可以了 - Maven工程的.gitlab-ci.yml
image: "xxxxx/tools/maven:3.3.9-alpine"
variables:
MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository"
cache:
untracked: true
paths:
- .m2/repository
......