使用 CircleCI 构建原生 Quarkus 应用

任何软件项目(包括 Quarkus 应用)的一个重要部分就是持续集成。CI 领域中一个流行的工具是 CircleCI,尤其是对于开源项目。关于如何为标准的 Maven 项目配置 CircleCI,有很多文档。但是,构建一个原生的 Quarkus 可执行文件需要一两个额外的步骤。这篇博文将介绍如何实现这一点。

如果您赶时间,可以直接滚动到本文底部的完整(带注释)示例。

CircleCI 作业的结构

如果您不熟悉 CircleCI,一个好的起点可能是他们的 配置文档参考。这篇博文假设您对 CircleCI 有基本的了解,只是想在配置原生 Quarkus 构建方面获得一些帮助。总的来说,作业的配置方式与任何标准的 Maven 构建一样,包括:

  • 从源检出

  • 依赖缓存

  • 构建

  • 测试

然而,对于原生 Quarkus 构建,额外的配置集中在安装 GraalVM,然后执行(并验证)原生镜像构建。

Docker 与 Machine

CircleCI 允许使用 三种类型的“执行器”(执行构建作业的运行时环境)。它们是:

  • docker

  • machine

  • macos

似乎在使用 docker 进行构建时,很容易耗尽内存。因此,建议您为执行器使用 machine。幸运的是,所使用的默认虚拟机已经包含了大部分必要的构建工具,包括(但不限于):

  • Java

  • Maven

  • Chrome

  • PhantomJS

您唯一需要但未预先安装的构建工具是 GraalVM……

GraalVM 和 native-image

为了成功构建 Quarkus 原生应用(使用 `mvnw package -Pnative` 命令),必须安装 GraalVM 并将其设置为 `GRAALVM_HOME` 环境变量。这意味着您的构建配置必须包含下载、解压和安装 GraalVM 所需的相应命令。您还需要正确配置 `GRAALVM_HOME` 环境变量。安装 GraalVM 有多种方法,但这里有一个示例:

      - run:
          name: Install GraalVM
          command: curl https://github.com/oracle/graal/releases/download/vm-19.1.1/graalvm-ce-linux-amd64-19.1.1.tar.gz -O -J -L && tar xfz graalvm-ce-linux-amd64-19.1.1.tar.gz && mv graalvm-ce-19.1.1 .graalvm && rm graalvm-ce-linux-amd64-19.1.1.tar.gz

安装 GraalVM 后,您还需要安装 native-image,它是 GraalVM 的一个附加组件。这可以通过使用 GraalVM 附带的 `gu` 工具来完成。在 CircleCI 配置中,它可能看起来像这样:

      - run:
          name: Install native-image
          command: $GRAALVM_HOME/bin/gu install native-image

如前所述,您需要设置 `GRAALVM_HOME` 环境变量。您可以在配置的 `environment` 部分全局设置它,也可以为每个 run 命令单独设置。通常前者最简单:

    environment:
      GRAALVM_HOME: /home/circleci/repo/.graalvm

原生构建和验证

在安装了 GraalVM 和 native-image 之后,您只需创建一个或多个 run 命令来构建和验证您的原生 Quarkus 应用。它看起来会像这样:

      - run:
          name: Build (Native)
          command: ./mvnw clean package -Pnative -DskipTests -Dmaven.test.skip=true
          no_output_timeout: 30m
      - run:
          name: Verify (Native)
          command: ./mvnw verify -Pnative
          no_output_timeout: 30m

您会注意到这两个命令都有一个额外的 `no_output_timeout` 设置。似乎 native-image 工具并不总是能及时完成。有时很快,但有时需要一些时间——超过 CircleCI 的默认超时时间 10 分钟。我相信随着 GraalVM native-image 工具的成熟,这一点会得到改善(包括运行的总时间和变动性)。在此之前,简单地增加超时时间似乎效果很好。

完整示例(带注释)

您可能直接跳过了上面的所有信息,想直接复制粘贴示例,对吧?嗯,我也是这么做的!这是一个完整的、可工作的 CircleCI 原生 Quarkus 构建作业示例(.circleci/config.yml)。

#
# Native Quarkus CircleCI configuration file
#
version: 2
jobs:
  build:
    # Use "machine" instead of e.g. "docker" for better/faster results
    machine: true
    # Uses a "medium" sized machine - maybe increase this to "large" if you pay for CircleCI
    resource_class: medium
    working_directory: ~/repo
    environment:
      MAVEN_OPTS: -Xmx6400m
      # Set the GRAALVM_HOME env variable to the location where we will be installing GraalVM
      GRAALVM_HOME: /home/circleci/repo/.graalvm
    steps:
      # Checkout the source code
      # ########################
      - checkout

      # Restore any files we may have cached
      # ########################
      - restore_cache:
          keys:
            - v1-dependencies-{{ checksum "pom.xml" }}
            # fallback to using the latest cache if no exact match is found
            - v1-dependencies-

      # Download maven dependencies so that we can cache them
      # ########################
      - run:
          name: Download Dependencies
          command: mvn dependency:go-offline
      # Cache the maven dependencies
      - save_cache:
          paths:
            - ~/.m2
          key: v1-dependencies-{{ checksum "pom.xml" }}

      # Standard maven build and test phases - does not perform a native build (or verify)
      # ########################
      - run:
          name: Build (Standard)
          command: ./mvnw clean package -DskipTests -Dmaven.test.skip=true
      - run:
          name: Verify (Standard)
          command: ./mvnw test

      # Install GraalVM and native-image, needed for a native Quarkus build
      # ########################
      - run:
          name: Install GraalVM
          command: curl https://github.com/oracle/graal/releases/download/vm-19.1.1/graalvm-ce-linux-amd64-19.1.1.tar.gz -O -J -L && tar xfz graalvm-ce-linux-amd64-19.1.1.tar.gz && mv graalvm-ce-19.1.1 .graalvm && rm graalvm-ce-linux-amd64-19.1.1.tar.gz
      - run:
          name: Install native-image
          command: $GRAALVM_HOME/bin/gu install native-image

      # Perform a native Quarkus build and verify
      # ########################
      - run:
          name: Build (Native)
          command: ./mvnw clean package -Pnative -DskipTests -Dmaven.test.skip=true
          no_output_timeout: 30m
      - run:
          name: Verify (Native)
          command: ./mvnw verify -Pnative
          no_output_timeout: 30m