如何防止gitlab ci每次都下载sbt?
Posted
技术标签:
【中文标题】如何防止gitlab ci每次都下载sbt?【英文标题】:how to prevent gitlab ci from downloading sbt every time? 【发布时间】:2017-06-01 14:42:00 【问题描述】:我们有一个play2/scala
应用程序,我们正在使用 gitlab ci 构建它。
我们的.gitlab-ci.yml
(至少是重要部分)如下所示:
image: hseeberger/scala-sbt
variables:
SBT_GLOBAL_BASE_DIR: "$CI_PROJECT_DIR/cache/.sbt"
IVY2_CACHE_DIR: "$CI_PROJECT_DIR/cache/.ivy2"
SBT_BOOT_DIR: "$CI_PROJECT_DIR/cache/.sbt/boot"
M2_HOME_DIR: "$CI_PROJECT_DIR/cache/.m2"
before_script:
# Log the sbt version
- sbt sbt-version
build:
stage: build
script:
- ./build.sh
build.sh
:
sbt -Dsbt.global.base=$SBT_GLOBAL_BASE_DIR \
-Dsbt.ivy.home=$IVY2_CACHE_DIR \
-Dsbt.boot.directory=$SBT_BOOT_DIR \
compile
不幸的是,我们的管道在所有步骤(构建、验证、部署)中总是运行大约 30-40 分钟。大部分时间都花在一遍又一遍地下载sbt
上真的很烦人。
我可能对gitlab ci runners
不够了解,但据我了解,通过使用hseeberger/scala-sbt作为图像,sbt
应该是全球可用的,应该不需要下载它。
那么也不需要来自 gitlab 的 this 解决方案。
无论如何,只要服务器运行任何sbt
命令,在每次部署期间不会总共下载 6 次 sbt
,我会很高兴。
谁能解释我如何以正确的方式使用正确的image
或image
,或者我如何缓存sbt
的东西?
更新
在过去的几天里,我与docker
和gitlab ci
进行了很多战斗。我发现这个问题和don't downloading the internet 中描述的差不多。拥有所有依赖项似乎是一项艰巨的任务,最好通过挂载它们来完成。不幸的是,这在共享的 gitlab ci 运行器上是不可能的。
我继续发现sbt-docker,它允许您从build.sbt
文件构建docker 容器。使用package basic approach,我尝试将项目的所有本地可用依赖项作为global sbt plugins 包含到容器中。但这也无济于事。
我最后的发现是关于maven
solution 的答案,并试图将其转化为我们的sbt
项目:
.gitlab-ci.yml
image: hseeberger/scala-sbt
variables:
MAVEN_OPTS: -Dmaven.repo.local=/cache/maven.repository
stages:
- build
- test
- staging
- deploy
build:
stage: build
script:
- sbt compile -Dsbt.ivy.home=/cache/.ivy2 -Dsbt.global.base=/cache/.sbt/0.13 -Dsbt.boot.directory=/cache/.sbt/boot -Dsbt.repository.config=/cache/.sbt/repositories
我可以再次访问gitlab ci
日志。它们基本上如下所示:
[info] Loading project definition from /builds/kwiqjobs/backend/project
[info] Updating file:/builds/kwiqjobs/backend/project/backend-build...
[info] Resolving com.typesafe.play#sbt-plugin;2.5.4 ...
[info] Resolving com.typesafe.play#sbt-plugin;2.5.4 ...
[info] Resolving com.typesafe.play#sbt-routes-compiler_2.10;2.5.4 ...
[info] Resolving com.typesafe.play#sbt-routes-compiler_2.10;2.5.4 ...
[info] Resolving org.scala-lang#scala-library;2.10.6 ...
[info] Resolving com.typesafe.play#twirl-api_2.10;1.1.1 ...
[info] Resolving com.typesafe.play#twirl-api_2.10;1.1.1 ...
... a **lot** more
[info] [SUCCESSFUL ] com.typesafe.sbt#sbt-twirl;1.1.1!sbt-twirl.jar (1033ms)
[info] downloading https://repo.scala-sbt.org/scalasbt/sbt-plugin-releases/com.typesafe.sbt/sbt-native-packager/scala_2.10/sbt_0.13/1.0.3/jars/sbt-native-packager.jar ...
[info] [SUCCESSFUL ] com.typesafe.sbt#sbt-native-packager;1.0.3!sbt-native-packager.jar (954ms)
[info] downloading https://repo.scala-sbt.org/scalasbt/sbt-plugin-releases/com.typesafe.sbt/sbt-web/scala_2.10/sbt_0.13/1.3.0/jars/sbt-web.jar ...
[info] [SUCCESSFUL ] com.typesafe.sbt#sbt-web;1.3.0!sbt-web.jar (1010ms)
[info] downloading https://repo.scala-sbt.org/scalasbt/sbt-plugin-releases/com.typesafe.sbt/sbt-js-engine/scala_2.10/sbt_0.13/1.1.3/jars/sbt-js-engine.jar ...
[info] [SUCCESSFUL ] com.typesafe.sbt#sbt-js-engine;1.1.3!sbt-js-engine.jar (1147ms)
[info] downloading https://repo1.maven.org/maven2/com/typesafe/play/twirl-api_2.10/1.1.1/twirl-api_2.10-1.1.1.jar ...
[info] [SUCCESSFUL ] com.typesafe.play#twirl-api_2.10;1.1.1!twirl-api_2.10.jar (89ms)
[info] downloading https://repo1.maven.org/maven2/commons-io/commons-io/2.4/commons-io-2.4.jar ...
[info] [SUCCESSFUL ] commons-io#commons-io;2.4!commons-io.jar (48ms)
a **lot** more
[info] Done updating.
[info] Compiling 228 Scala sources and 4 Java sources to /builds/kwiqjobs/backend/target/scala-2.11/classes...
[info] 'compiler-interface' not yet compiled for Scala 2.11.8. Compiling...
[info] Compilation completed in 17.735 s
[success] Total time: 149 s, completed Jan 20, 2017 2:22:52 PM
Build succeeded
我想摆脱所有的下载。
【问题讨论】:
您链接到的 gitlab 的解决方案未包含在您的构建脚本中,您是否使用它?也请发布输出的相关部分。 不,不包括在内。我主要想知道是否应该避免使用 hseeberger/scala-sbt 图像下载sbt
at all。在这个 docker 镜像上,sbt
已经安装好了。那么是否需要缓存或者安装呢?
我现在似乎无法访问日志,gitlab.com 没有响应。但是您会看到,在调用sbt sbt-version
之后,所有sbt
依赖项都将被解析并下载。之后,当build.sh
被调用时,它将重新开始下载它们。然后,在verification.sh
和deploy.sh
再次 everything 将再次下载。 gitlab solution 是我需要的吗?我可以在那里做一些额外的缓存吗?
您正在下载所有依赖项并构建应用程序 3 次。我添加了您可以使用的大部分选项。
请查看leonard.io/blog/2017/05/gitlab-ci-caching-for-sbt-projects,了解如何启用缓存。我测试了它,它按预期工作。
【参考方案1】:
如果您不想使用自定义图像,最好的解决方案是使用 Gitlab CI 的caching mechanism。
要做到这一点有点困难,但this blog post 描述了如何为 SBT 做到这一点。
示例.gitlab-ci.yml
引自博文,小错误自行更正:
# some parts originally from https://github.com/randm-ch/units-of-information/blob/master/.gitlab-ci.yml
image: "hseeberger/scala-sbt"
variables:
SBT_VERSION: "0.13.9"
SBT_OPTS: "-Dsbt.global.base=sbt-cache/.sbtboot -Dsbt.boot.directory=sbt-cache/.boot -Dsbt.ivy.home=sbt-cache/.ivy"
cache:
key: "$CI_BUILD_REF_NAME" # contains either the branch or the tag, so it's caching per branch
untracked: true
paths:
- "sbt-cache/.ivy/cache"
- "sbt-cache/.boot"
- "sbt-cache/.sbtboot"
- "sbt-cache/target"
stages:
- test
test:
script:
- sbt test
第二个例子,也包括apt-get
缓存
这是我在项目中使用的,可用于更一般的用例和 Docker 映像:
image: java:8
stages:
- test
variables:
SBT_VERSION: "0.13.9"
SBT_OPTS: "-Dsbt.global.base=sbt-cache/.sbtboot -Dsbt.boot.directory=sbt-cache/.boot -Dsbt.ivy.home=sbt-cache/.ivy"
SBT_CACHE_DIR: "sbt-cache/.ivy/cache"
cache:
key: "$CI_BUILD_REF_NAME" # contains either the branch or the tag, so it's caching per branch
untracked: true
paths:
- "apt-cache/"
- "sbt-cache/.ivy/cache"
- "sbt-cache/.boot"
- "sbt-cache/.sbtboot"
- "sbt-cache/target"
before_script:
- export APT_CACHE_DIR=`pwd`/apt-cache
- mkdir -pv $APT_CACHE_DIR
- ls $APT_CACHE_DIR || echo "no apt-cache dir found"
- apt-get -o dir::cache::archives=$APT_CACHE_DIR update -y
- apt-get -o dir::cache::archives=$APT_CACHE_DIR install apt-transport-https -y
# Install SBT
- mkdir -pv $SBT_CACHE_DIR
- ls $SBT_CACHE_DIR || echo "no ivy2 cache fir found"
- echo "deb http://dl.bintray.com/sbt/debian /" | tee -a /etc/apt/sources.list.d/sbt.list
- apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 642AC823
- apt-get -o dir::cache::archives=$APT_CACHE_DIR update -y
- apt-get -o dir::cache::archives=$APT_CACHE_DIR install sbt -y
- sbt -v sbtVersion
test:
stage: test
script:
- sbt -v sbtVersion
【讨论】:
【参考方案2】:你可以做 4 件事:
-
自己的docker镜像
缓存
人工制品
使用自己的缓存解决方案
最好的解决方案是混合使用它们。
-
您可以使用所需的所有依赖项构建自己的 docker 映像,这是最快的解决方案,因为它不必下载所有内容,但它会引入您需要处理的另一块难题。您可以使用in-built gitlab repository 存储它并让gitlab 构建它,然后use it。
您可以在 Gitlab CI 作业中使用 cache,这样它就不必一直下载所有内容。 sbt 的默认缓存似乎是 ~/.ivy2 所以添加
cache: paths: - ~/.ivy2/
作为 gitlab 文件中的第一行,为每个阶段使用缓存。
-
将目标目录定义为 artifact 以在构建之间传递它,因此您不必在每个阶段都构建它。
artifacts: paths: - target/
-
如果 gitlab 提供的选项不够用,可以将需要缓存的文件存储在自己的 s3/minio/nfs 中。这将是一个非常自定义的解决方案,因此您必须找到自己的解决方案。
【讨论】:
谢谢!我会测试它们。但是关于 1:如果我从公共存储库使用的镜像应该已经具有它在构建期间下载的 sbt 依赖项,为什么我需要创建自己的 docker 镜像?为什么这不起作用? @stubbi 好吧,我对 stb 不熟悉,但我认为它正在拉动项目的依赖关系或自我更新。至少当我尝试运行示例项目时看起来是这样的。 我发现了问题。容器和我们项目中的 sbt 版本必须匹配!我们在哪里使用0.13.11
,而在容器中有0.13.13
。这加快了一切,但仍然存在应该在容器中的依赖项。充其量它们也应该始终保持最新状态。我在这里找到了this 问题,并在sbt native packager docker plugin 上有提示,现在将尝试。
我更新了问题。你能再看看吗?也许您现在可以更好地看到问题所在。以上是关于如何防止gitlab ci每次都下载sbt?的主要内容,如果未能解决你的问题,请参考以下文章
如何为 GitLab CI 运行器启用 Maven 工件缓存?
如何创建一个工件,以便它可以在 .gitlab-ci.yml 中下载