如何使用 Gitlab CI 构建 Java Maven 项目?

Posted

技术标签:

【中文标题】如何使用 Gitlab CI 构建 Java Maven 项目?【英文标题】:How to use Gitlab CI to build a Java Maven project? 【发布时间】:2016-01-30 13:18:12 【问题描述】:

我一直在尝试但没有成功,我正在运行一个托管在 Linux 上的 Gitlab,并试图了解 CI 功能。

根据 Gitlab 文档,您只需要创建一个.gitlab-ci.yml 文件,即 Travis-CI 的 Gitlab 实现。现在从它的外观来看,您可以使用.gitlab-ci.yml 完成很多工作,但是很多文档都引用了 Ruby 和其他语言。没有提及如何构建 Java Maven 项目。

如何在 Java 中构建一个简单的应用程序?我可以使用共享运行器,还是应该使用特定的运行器,在这种情况下,我应该选择什么或哪个运行器实现:ssh、docker 或 shell?那么,我应该在.gitlab-ci.yml 文件中至少放入什么来使用 Maven 构建项目?

【问题讨论】:

【参考方案1】:

这里有几个问题。

我将开始回答 Java 构建问题,然后是 Runners 问题。

Java 构建

我将从最基本的 Java 构建配置开始,逐步添加功能。

1。基本 Java 构建

此配置有望运行您的 Maven 构建(并且只有构建,明确排除单元测试):

stages:
  - build

java-build:
  # select the most appropriate image for your project
  image: maven:3.8-openjdk-11
  stage: build
  script:
    - mvn package -DskipTests=true

2。带有工件、缓存和推荐的 Maven 选项

这个新版本:

将 Maven 构建输出声明为 GitLab 工件(供以后在下游管道中使用), 利用GitLab's cache 缓存本地Maven 存储库(在.m2/repository 中), 还强制执行一些推荐的 Maven 选项以在 CI/CD 上下文中使用。
stages:
  - build

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=.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  

java-build:
  # select the most appropriate image for your project
  image: maven:3.8-openjdk-11
  stage: build
  # Cache downloaded dependencies and plugins between builds.
  # The key here separates one cache per branch/tag ($CI_COMMIT_REF_SLUG)
  cache:
    key: "maven-$CI_COMMIT_REF_SLUG"
    paths:
      - .m2/repository
  script:
    - mvn $MAVEN_CLI_OPTS package -DskipTests=true
  artifacts:
    name: "Maven artifacts from $CI_PROJECT_NAME on $CI_COMMIT_REF_SLUG"
    paths:
      - "**/target"

3。带有单元测试

在 CI/CD 管道中集成单元测试时有两种选择:

    在与构建相同的作业中运行它们 在单独的作业中运行它们

出于管道执行速度和绿色 IT 考虑,我绝对更喜欢选项 1,但我承认人们可能更喜欢第二个。

这是.gitlab-ci.yml文件的新版本,同样实现了GitLab unit tests integration:

stages:
  - build

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=.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  

java-build-and-test:
  # select the most appropriate image for your project
  image: maven:3.8-openjdk-11
  stage: build
  # Cache downloaded dependencies and plugins between builds.
  # The key here separates one cache per branch/tag ($CI_COMMIT_REF_SLUG)
  cache:
    key: "maven-$CI_COMMIT_REF_SLUG"
    paths:
      - .m2/repository
  script:
    # the 'verify' goal is definitely the most appropriate here
    - mvn $MAVEN_CLI_OPTS verify
  artifacts:
    name: "Maven artifacts from $CI_PROJECT_NAME on $CI_COMMIT_REF_SLUG"
    paths:
      - "**/target"
    reports:
      # declare the JUnit reports (recursive pattern for multi-module projects)
      junit:
        - "**/target/*-reports/TEST-*.xml"

4。走得更远

从这一步开始,构建作业仍然可以进一步增强,例如代码覆盖率计算和integration,但这需要更多代码。

另一种以更少工作量实现最先进管道的方法是使用 GitLab CI/CD 模板。例如:

GitLab's Maven template 或to-be-continuous template

to be continuous 是一个开源项目,它提供了一系列即用型、可配置、可扩展、可组合的模板。

关于跑步者

GitLab 架构非常通用,具有Runners 的概念。 Runners 是基本的executors pool,可以执行 GitLab CI/CD 作业。

关于跑步者需要了解的 2 件事

1。你可以让你的跑步者专业化

使用 GitLab,您可以注册多种跑步者,用于特殊和互补目的。

为了隔离它们,GitLab 支持Tags 的概念。注册跑步者时,应将它们与 functional 标签名称相关联,这将有助于开发人员在其.gitlab-ci.yml 文件中选择最合适的名称。

例如,假设您有 4 名跑步者:

# Description Proposed Tags
1 Linux-based general purpose runners for building code, running tests, ... with transparent access to the internet linux, general, internet you should also allow this one to run untagged jobs (makes it kind of default runner)
2 Microsoft-based general purpose runners for building your .NET code windows, general, internet
3 compute-optimized runners, made for - say - training super-secret neural networks with no access to the internet linux, compute, ml (for machine learning)
4 runners located behind your DMZ in your on-premises datacenter, used to perform code/infrastructure deployments linux, deploy, datacenter

通过此设置,具有 Java 和 .NET 代码的 monorepo 项目可以声明以下 .gitlab-ci.yml 文件:

stages:
  - build
  - test
  - deploy

# this job declares no tag: will be executed by default runner (#1)
java-build:
  image: maven:3.8-openjdk-11
  stage: build
  script:
    - Java build code here

dotnet-build:
  image: mcr.microsoft.com/dotnet/sdk:5.0
  stage: build
  tags:
    - windows
    - general
  script:
    - .NET build code here

# this job declares no tag: will be executed by default runner (#1)
java-test:
  image: maven:3.8-openjdk-11
  stage: test
  script:
    - Java test code here

dotnet-test:
  image: mcr.microsoft.com/dotnet/sdk:5.0
  stage: test
  tags:
    - windows
    - general
  script:
    - .NET test code here

deploy:
  stage: deploy
  tags:
    - deploy
    - datacenter
  script:
    - deployment code here

2。跑步者有不同的范围

引用official documentation:

根据您想要访问的人,可以使用跑步者:

Shared runners 可用于 GitLab 实例中的所有组和项目。 Group runners 可用于组中的所有项目和子组。 Specific runners 与特定项目相关联。通常,特定的跑步者一次用于一个项目。

【讨论】:

【参考方案2】:

Register a Docker runner 并在您的.gitlab-ci.yml 文件中使用official Maven Docker images 之一,例如maven:3-jdk-11

image: maven:3-jdk-11

build:
  script: "mvn install -B"

注意-B flag,建议用于非交互式使用。

据我了解,跑步者是共享的还是特定的并不重要。

【讨论】:

所以当被问到是在注册跑步者时运行shell、ssh还是docker时,我应该选择docker对吗? 谢谢,就像一个魅力!只是一个问题:当我们在.gitlab-ci.yml 文件中指定图像时,gitlab-runner 创建期间指定的图像会被忽略吗?例如我用图像 ubuntu:latest 创建了一个跑步者,并在 yml 文件中使用 maven:3-jdk-7 运行作业 @jeanMarcAssin 关于这方面的文档有点稀疏,但本节:doc.gitlab.com/ce/ci/docker/… 和以下两个建议您在.gitlab-ci.yml 文件中指定的图像将覆盖 i> 运行器配置的图像。 这张图片现在有点老了,由于缺乏对 NPM 下载的 EC 支持,我遇到了问题。在 JDK 11 (maven:3.6-jdk-11) 中使用更新的 docker 映像对我来说效果更好。见***.com/a/63027888/768795【参考方案3】:

在How to deploy Maven projects to Artifactory with GitLab CI/CD的帮助下

您只需将.gitlab-ci.yml 文件添加到存储库的根目录,即可编译您的java maven 项目,其内容如下:

image: maven:latest

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

cache:
  paths:
    - .m2/repository/
    - target/

build:
  stage: build
  script:
    - mvn compile

【讨论】:

.m2/repository 位于执行运行器的服务器路径中?【参考方案4】:

我花了相当多的时间尝试在 Gitlab CI 上设置我们的 Java 项目。我得到了一定程度的成功。正如 rolve 所说,最直接的解决方案是使用官方 repo 中的图像:https://hub.docker.com/_/maven

但是,我们有一个公司代理,导致我的构建在获取项目的依赖项时收到超时请求。我尝试了很多解决方案,最后看到了这个帖子:https://gitlab.com/gitlab-org/gitlab-ce/issues/15167。

这篇文章本身是关于设置 maven 以将下载的依赖项缓存在本地 repo 中,该 repo 可以在构建之间访问。这个想法是你可以通过在 .gitlab-ci.yml 中编写一个本地 maven 配置文件来设置你的缓存目录和你的代理。

before_script:
  -echo '<settings
          xmlns="http://maven.apache.org/SETTINGS/1.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
          https://maven.apache.org/xsd/settings-1.0.0.xsd">
          <localRepository>/cache/.m2</localRepository>
          <proxies>
              <proxy>
                  <active>true</active>
                  <protocol>'$PROXY_PROTOCOL'</protocol>
                  <host>'$PROXY_HOST'</host>
                  <port>'$PROXY_PORT'</port>
              </proxy>
          </proxies>
      </settings>' > $HOME/.m2/settings.xml

build_debug1:
  stage: build
  script: "echo $PROXY_HOST"

build_debug2:
  stage: build
  script: "cat $HOME/.m2/settings.xml"

build_maven:
  stage: build
  script: "mvn $MAVEN_CLI_OPTS package"
  artifacts:
    paths:
      - target/*.jar

deploy_debug1:
  stage: package
  script: "ls target/"

请注意,构建调试作业只是为了查看代理设置是否被正确注入。您可以使用 Gitlab 将代理环境变量设置为机密,方法是转到项目 -> 设置 -> CI/CD 管道 -> 机密变量。

最后一个deploy_debug 工作是查看目标目录中生成的内容。

【讨论】:

【参考方案5】:

文档描述了用于控制构建的 YAML 语法:

https://gitlab.com/help/ci/yaml/README.md

那么你为什么不尝试从以下开始呢?:

job1:
  script: "mvn package"

大概只有在已经安装了 Maven 的情况下这才有效,所以你需要一个支持这个的runner。

我没有使用 GitLab,但 documentation 建议您可以进一步自定义它以使用 official Maven Docker image 执行构建。看起来很有趣,但我同意文档缺少 Java 示例。

【讨论】:

【参考方案6】:

我想在这里补充一点信息。首先让我们澄清一些关于共享和特定跑步者的困惑。

共享跑步者: 顾名思义,共享运行器是构建流程实例,可用于在启用了 Allowed Shared runners 选项的已安装 gitlab 实例中执行每个项目的作业。当然,要做到这一点,您需要管理权限。根据当前的 gitlab 文档,只有使用管理权限才能定义共享运行器。

特定的跑步者这种跑步者只执行一个项目的工作。

此外,在为您的项目选择跑步者时,请牢记以下几点。

    Shared Runners对于在多个项目之间具有相似要求的工作很有用。您可以让一个或少量的跑步者处理多个项目,而不是让多个跑步者闲置在许多项目中。这使得维护和更新常见项目的运行器变得更加容易。 特定跑步者对于具有特殊要求的工作或具有特定需求的项目很有用。如果工作有一定的要求,你可以考虑到这一点来设置特定的跑步者,而不必对所有跑步者都这样做。例如,如果您想部署某个项目,您可以设置一个特定的运行器以获得正确的凭据。

现在要为项目选择正确的执行器,重要的是我们对 gitlab runner 的所有可用执行器有鸟瞰图。 Gitlab 在here 上提供了很好的文档,解释了使用不同的执行器可以获得哪些不同的选项,从而使我们的工作变得轻松。

如果您想了解更多关于 runner 和不同 executor 的信息,我建议您从这篇文章开始, Gitlab Runner

【讨论】:

【参考方案7】:

我使用这个命令,但一般来说关于 java/maven 构建的文档似乎很少见

maven-package:
  script: "mvn install -B"

【讨论】:

以上是关于如何使用 Gitlab CI 构建 Java Maven 项目?的主要内容,如果未能解决你的问题,请参考以下文章

Unity如何使用Gitlab-CI做自动构建

如何使用GitLab和Rancher构建CI/CD流水线 – Part 2

如何在 gitlab ci 的构建脚本中使用 sudo?

如何在 .gitlab-ci.yml 中指定通配符工件子目录?

Linux云计算 --中国三大电商大厂都在使用的《 GitLab与Jenkins结合构建持续集成(CI)环境》是如何排列

如何更新 Gitlab.com CI 中使用的 docker 镜像