如何防止gitlab ci每次都下载sbt?

时间:2017-01-17 13:45:19

标签: scala maven sbt gitlab-ci sbt-plugin

我们正在使用gitlab ci构建play2/scala应用程序。

我们的.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命令时,如果sbt在每次部署期间不会被完全下载6次,我会很高兴。

有人可以解释我如何以正确的方式使用正确的imageimage,或者我如何缓存sbt内容?

更新

在过去的几天里,我与dockergitlab ci进行了很多斗争。我发现这个问题与don't downloading the internet中描述的几乎相同。看起来这是一项艰巨的任务,拥有所有的依赖关系,最好通过安装它们来完成。遗憾的是,在共享的gitlab ci runner上不可能这样。

我继续发现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

我想摆脱所有下载

2 个答案:

答案 0 :(得分:8)

如果您不想使用自定义图片,最佳解决方案是使用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

答案 1 :(得分:2)

你可以做4件事:

  1. 拥有码头图片
  2. 缓存
  3. 伪影
  4. 使用自己的缓存解决方案
  5. 最好的解决方案是将它们混合在一起。

    1. 您可以构建自己的Docker镜像,其中包含您需要的所有依赖项,它是最快的解决方案,因为它不必下载所有内容,但它会引入您需要注意的另一部分谜题的。您可以使用in-built gitlab repository进行存储,然后让gitlab构建它,然后use it
    2. 您可以在Gitlab CI工作中使用cache,因此不必一直下载所有内容。 sbt的默认缓存似乎是〜/ .ivy2所以添加
    3. cache:
        paths:
          - ~/.ivy2/
      

      作为gitlab文件中的第一行,为每个阶段使用缓存。

      1. 将目标目录定义为artifact,以便在构建之间传递它,因此您不必在每个阶段构建它。
      2. artifacts:
          paths:
            - target/
        
        1. 如果gitlab提供的选项不够,您可以将需要缓存的文件存储在自己的s3 / minio / nfs中。这将是一个非常自定义的解决方案,因此您必须找到自己的方法。