如何为 GitLab CI runner 启用 Maven 工件缓存?

How to enable maven artifact caching for GitLab CI runner?

我们使用 GitLab CI 和共享运行器来进行持续集成。对于每个构建,运行器都会下载大量的 Maven 工件。

有没有办法配置 GitLab CI 来缓存这些工件,这样我们就可以通过防止一遍又一遍地下载相同的工件来加快构建过程?

Gitlab CI 允许您定义某些路径,其中包含应在构建之间缓存的数据,基于每个作业或构建(有关详细信息,请参阅 here)。结合khmarbaise的推荐,这可以用来缓存多个构建之间的依赖关系。

在您的构建中缓存所有作业依赖项的示例:

cache:
  paths:
    - .m2/repository

variables:
  MAVEN_OPTS: "-Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository"

maven_job:
  script:
    - mvn clean install

根据 GitLab's issue tracker 上的对话,我设法更改了 Maven 本地存储库路径并将其放入 ./.m2/repository/ 目录,然后我们将在 运行 之间保留该目录通过将此全局块添加到 CI 配置:

cache:
  paths:
    - ./.m2/repository
  # keep cache across branch
  key: "$CI_BUILD_REF_NAME"

不幸的是,根据 this Whosebug answer,maven 本地存储库路径只能在每个 运行 上使用 -Dmaven.repo.local 或通过编辑您的 settings.xml 来设置,这很乏味在 gitlab-ci 配置脚本中完成的任务。一个选项是使用默认的 Maven 选项设置一个变量并将其传递给每个 运行。

此外,重要的是本地 Maven 存储库是当前目录的子目录。cial。出于某种原因,将它放在 /cache/builds 中对我不起作用,尽管来自 GitLab 的人声称它应该。

Maven + Java:

的工作 gitlab-ci.yml 配置文件示例
image: maven:3-jdk-8

variables:
  MAVEN_OPTS: "-Djava.awt.headless=true -Dmaven.repo.local=./.m2/repository"
  MAVEN_CLI_OPTS: "--batch-mode --errors --fail-at-end --show-version"

cache:
  paths:
    - ./.m2/repository
  # keep cache across branch
  key: "$CI_BUILD_REF_NAME"

stages:
  - build
  - test
  - deploy

build-job:
  stage: build
  script:
    - "mvn clean compile $MAVEN_CLI_OPTS"
  artifacts:
    paths:
      - target/

unittest-job:
  stage: test
  dependencies:
    - build-job
  script:
    - "mvn package $MAVEN_CLI_OPTS"
  artifacts:
    paths:
      - target/

integrationtest-job:
  stage: test
  dependencies:
    - build-job
  script:
    - "mvn verify $MAVEN_CLI_OPTS"
  artifacts:
    paths:
      - target/

deploy-job:
  stage: deploy
  artifacts:
    paths:
      - "target/*.jar"

您可以将缓存文件夹添加到 gitlab-ci runner 配置并传递给 maven。

/etc/gitlab-runner/config.toml

[[runners]]
...
  [runners.docker]
  ...
   volumes = ["/cache", "/.m2"]
  ...

.gitlab-ci.yml

variables:
  MAVEN_OPTS: "-Dmaven.repo.local=/.m2"

build:
  script:
    - mvn package

接受的答案不适合我。

正如 zlobster 提到的,GitLab 的人有这个惊人的 repository 在那里你可以找到用于 Maven 项目的 .gitlab-ci.yml 文件的正确示例.

基本上,您需要的是这些行:

cache:
  paths:
    - .m2/repository

请记住,如果您决定为某个作业添加本地缓存,则上面添加的全局缓存将被替换。关于此的更多信息 here

如果你使用kubernetes作为gitlab-runner的执行器,你也可以使用maven缓存。我选择在 NFS 上使用 k8s PV 进行持久缓存(但由于 NFS 提供的持久性,gitlab-runner). The following configuration doesn't use the cache gitlab 功能支持其他卷类型。

1) 在您的集群上创建一个 PersistentVolume,例如这里使用 NFS(适应您的持久层和您的选项):

apiVersion: v1
kind: PersistentVolume
metadata:
  name: gitlabrunner-nfs-volume
spec:
  capacity:
    storage: 10Gi
  mountOptions:
    - nolock
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Recycle
  nfs:
    path: /gitlabrunner
    server: 1.2.3.4

2) 引用 PV 以在 runner pod 中作为卷获取声明:

[[runners.kubernetes.volumes.pvc]]
  name = "pvc-1"
  mount_path = "/path/to/mount/point1"

注意 (03/09/18):这些参数的命令行选项尚不存在。有空issue.

3) 为gitlab-runner缓存指定相同的路径:

[[runners]]
  executor = "kubernetes"
  # ...
  cache_dir = "/path/to/mount/point1"

--cache-dir "/path/to/mount/point1" 处于交互模式

4) 使用-Dmaven.repo.local选项中的“/path/to/mount/point1”目录

我能够使用主机卷来共享我的 .m2 存储库目录。这也有共享我的 settings.xml 文件的优势(不是每个人都想要)。我发现这比使用提到的 cache 解决方案更快。

[[runners]]
  [runners.docker]
    volumes = ["/home/<user>/.m2:/root/.m2"]

还有一种方法。不要使用 gitlab 缓存并使用自定义(每个项目)docker image.

一些细节:

首先,您需要创建一个 Maven docker 映像,其中显示了项目依赖项所需的全部(或大部分)。将其发布到您的注册表(gitlab 有一个)并将其用于任何工作 运行ning maven。

要创建这样的图像,我通常会在 CI 中手动创建一个额外的作业。您需要在初始阶段以及项目依赖项被大量修改时触发它。

可在此处找到工作示例:

https://gitlab.com/alexej.vlasov/syncer/blob/master/.gitlab-ci.yml - 这个项目正在使用准备好的图像,它也有准备这个图像的工作。

https://gitlab.com/alexej.vlasov/maven/blob/master/Dockerfile - docker文件到 运行 maven 并下载依赖项一次。

优点:

  • 不需要每次都下载依赖 - 它们在 docker 图像(并且 docker 图层缓存在 运行 用户上)
  • 作业完成后不需要上传工件
  • 不使用 maven 的作业中未下载缓存

当您使用 CI_PROJECT_DIR 变量时,您不必在变量部分声明 MAVEN_OPTS(克隆存储库的完整路径和作业所在的位置 运行)

cache:
    key: maven-cache
    paths:
    - $CI_PROJECT_DIR/.m2/